mirror of
https://github.com/devfake/flox.git
synced 2024-11-14 22:22:39 +01:00
search and create episodes
This commit is contained in:
parent
0bf58b12f6
commit
5cc5802231
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Episode;
|
||||
use App\Item;
|
||||
use App\Services\Storage;
|
||||
use App\Services\TMDB;
|
||||
@ -27,16 +28,33 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all items for home with pagination.
|
||||
* Return all items with pagination.
|
||||
*
|
||||
* @param $orderBy
|
||||
* @return mixed
|
||||
*/
|
||||
public function items($orderBy)
|
||||
public function items($type, $orderBy)
|
||||
{
|
||||
$orderType = $orderBy == 'rating' ? 'asc' : 'desc';
|
||||
|
||||
return $this->item->orderBy($orderBy, $orderType)->simplePaginate($this->loadingItems);
|
||||
$item = $this->item->orderBy($orderBy, $orderType)->with('latestEpisode');
|
||||
|
||||
if($type != 'home') {
|
||||
$item = $item->where('media_type', $type);
|
||||
}
|
||||
|
||||
return $item->simplePaginate($this->loadingItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Episodes of an tv show.
|
||||
*
|
||||
* @param $tmdb_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function episodes($tmdb_id)
|
||||
{
|
||||
return Episode::where('tmdb_id', $tmdb_id)->get()->groupBy('season_number');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,7 +111,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete movie in database and delete the poster image file.
|
||||
* Delete movie or tv show (with episodes) and remove the poster image file.
|
||||
*
|
||||
* @param $itemID
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
|
||||
@ -107,8 +125,13 @@
|
||||
}
|
||||
|
||||
$this->storage->removePosterFile($item->poster);
|
||||
$tmdb_id = $item->tmdb_id;
|
||||
|
||||
$item->delete();
|
||||
|
||||
// Delete all related episodes
|
||||
// todo: Make this possible in migrations
|
||||
Episode::where('tmdb_id', $tmdb_id)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,11 +140,15 @@
|
||||
* @param $data
|
||||
* @return Item
|
||||
*/
|
||||
private function createItem($data)
|
||||
private function createItem($data, TMDB $tmdb)
|
||||
{
|
||||
return $this->item->create([
|
||||
'tmdb_id' => $data['tmdb_id'],
|
||||
$tmdbId = $data['tmdb_id'];
|
||||
$mediaType = $data['media_type'];
|
||||
|
||||
$item = $this->item->create([
|
||||
'tmdb_id' => $tmdbId,
|
||||
'title' => $data['title'],
|
||||
'media_type' => $mediaType,
|
||||
'original_title' => $data['original_title'],
|
||||
'poster' => $data['poster'],
|
||||
'rating' => 1,
|
||||
@ -129,5 +156,45 @@
|
||||
'genre' => $data['genre'],
|
||||
'created_at' => time(),
|
||||
]);
|
||||
|
||||
if($mediaType == 'tv') {
|
||||
$this->createEpisodes($tmdbId, $tmdb);
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function setSeen($id)
|
||||
{
|
||||
$episode = Episode::find($id);
|
||||
$episode->seen = ! $episode->seen;
|
||||
|
||||
if( ! $episode->save()) {
|
||||
return response('Server Error', 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all episodes of each season.
|
||||
*
|
||||
* @param $seasons
|
||||
* @param $tmdbId
|
||||
*/
|
||||
private function createEpisodes($tmdbId, TMDB $tmdb)
|
||||
{
|
||||
$seasons = $tmdb->tvEpisodes($tmdbId);
|
||||
|
||||
foreach($seasons as $season) {
|
||||
foreach($season->episodes as $episode) {
|
||||
$new = new Episode();
|
||||
$new->season_tmdb_id = $season->id;
|
||||
$new->episode_tmdb_id = $episode->id;
|
||||
$new->season_number = $episode->season_number;
|
||||
$new->episode_number = $episode->episode_number;
|
||||
$new->name = $episode->name;
|
||||
$new->tmdb_id = $tmdbId;
|
||||
$new->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,10 +18,22 @@
|
||||
'original_title',
|
||||
'poster',
|
||||
'media_type',
|
||||
'tv_data',
|
||||
'rating',
|
||||
'released',
|
||||
'created_at',
|
||||
'genre',
|
||||
];
|
||||
|
||||
public function episodes()
|
||||
{
|
||||
return $this->hasMany(Episode::class, 'tmdb_id', 'tmdb_id');
|
||||
}
|
||||
|
||||
public function latestEpisode()
|
||||
{
|
||||
return $this->hasOne(Episode::class, 'tmdb_id', 'tmdb_id')
|
||||
->orderBy('id', 'desc')
|
||||
->where('seen', true)
|
||||
->latest();
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
private $client;
|
||||
private $apiKey;
|
||||
private $translation;
|
||||
|
||||
/**
|
||||
* Get the API Key for TMDB and create an instance of Guzzle.
|
||||
@ -17,24 +18,23 @@
|
||||
public function __construct()
|
||||
{
|
||||
$this->apiKey = config('app.TMDB_API_KEY');
|
||||
$this->translation = config('app.TRANSLATION');
|
||||
$this->client = new Client(['base_uri' => 'http://api.themoviedb.org/']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search TMDB for an movie by 'title'.
|
||||
* Search TMDB by 'title'.
|
||||
*
|
||||
* @param $title
|
||||
* @return array
|
||||
*/
|
||||
public function search($title)
|
||||
{
|
||||
$translation = config('app.TRANSLATION');
|
||||
|
||||
$response = $this->client->get('/3/search/movie', [
|
||||
$response = $this->client->get('/3/search/multi', [
|
||||
'query' => [
|
||||
'api_key' => $this->apiKey,
|
||||
'query' => $title,
|
||||
'language' => strtolower($translation)
|
||||
'language' => strtolower($this->translation)
|
||||
]
|
||||
]);
|
||||
|
||||
@ -54,13 +54,14 @@
|
||||
/**
|
||||
* Search TMDB for recommendations and similar movies.
|
||||
*
|
||||
* @param $mediaType
|
||||
* @param $tmdbID
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function suggestions($tmdbID)
|
||||
public function suggestions($mediaType, $tmdbID)
|
||||
{
|
||||
$recommendations = $this->searchSuggestions($tmdbID, 'recommendations');
|
||||
$similar = $this->searchSuggestions($tmdbID, 'similar');
|
||||
$recommendations = $this->searchSuggestions($mediaType, $tmdbID, 'recommendations');
|
||||
$similar = $this->searchSuggestions($mediaType, $tmdbID, 'similar');
|
||||
|
||||
$items = $recommendations->merge($similar);
|
||||
|
||||
@ -73,16 +74,22 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $mediaType
|
||||
* @param $tmdbID
|
||||
* @param $type
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function searchSuggestions($tmdbID, $type)
|
||||
private function searchSuggestions($mediaType, $tmdbID, $type)
|
||||
{
|
||||
$response = $this->client->get('/3/movie/' . $tmdbID . '/' . $type, ['query' => ['api_key' => $this->apiKey]]);
|
||||
$response = $this->client->get('/3/' . $mediaType . '/' . $tmdbID . '/' . $type, [
|
||||
'query' => [
|
||||
'api_key' => $this->apiKey,
|
||||
'language' => strtolower($this->translation)
|
||||
]
|
||||
]);
|
||||
|
||||
return collect($this->createItems($response));
|
||||
return collect($this->createItems($response, $mediaType));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,7 +100,12 @@
|
||||
*/
|
||||
private function searchTrendingOrUpcoming($type)
|
||||
{
|
||||
$response = $this->client->get('/3/movie/' . $type, ['query' => ['api_key' => $this->apiKey]]);
|
||||
$response = $this->client->get('/3/movie/' . $type, [
|
||||
'query' => [
|
||||
'api_key' => $this->apiKey,
|
||||
'language' => strtolower($this->translation)
|
||||
]
|
||||
]);
|
||||
|
||||
$items = collect($this->createItems($response));
|
||||
$allID = $items->pluck('tmdb_id');
|
||||
@ -116,20 +128,32 @@
|
||||
* @param $response
|
||||
* @return array
|
||||
*/
|
||||
private function createItems($response)
|
||||
private function createItems($response, $type = null)
|
||||
{
|
||||
$items = [];
|
||||
$response = json_decode($response->getBody());
|
||||
|
||||
foreach($response->results as $result) {
|
||||
$dtime = DateTime::createFromFormat('Y-m-d', ($result->release_date ?: '1970-12-1'));
|
||||
// Suggestions doesn't deliver 'media type' by default
|
||||
$mediaType = $type ?: $result->media_type;
|
||||
|
||||
if($mediaType == 'person') continue;
|
||||
|
||||
$dtime = DateTime::createFromFormat('Y-m-d', (array_key_exists('release_date', $result)
|
||||
? ($result->release_date ?: '1970-12-1')
|
||||
: ($result->first_air_date ?: '1970-12-1')
|
||||
));
|
||||
|
||||
// 'name' is from tv, 'title' from movies
|
||||
$items[] = [
|
||||
'tmdb_id' => $result->id,
|
||||
'title' => $result->title,
|
||||
'original_title' => $result->original_title,
|
||||
'title' => array_key_exists('name', $result) ? $result->name : $result->title,
|
||||
'original_title' => array_key_exists('name', $result) ? $result->original_name : $result->original_title,
|
||||
'poster' => $result->poster_path,
|
||||
'media_type' => $mediaType,
|
||||
'released' => $dtime->getTimestamp(),
|
||||
'genre' => $this->parseGenre($result->genre_ids),
|
||||
'episodes' => [],
|
||||
];
|
||||
}
|
||||
|
||||
@ -144,11 +168,69 @@
|
||||
*/
|
||||
public function movie($tmdb_id)
|
||||
{
|
||||
$response = $this->client->get('/3/movie/' . $tmdb_id, ['query' => ['api_key' => $this->apiKey]]);
|
||||
$response = $this->client->get('/3/movie/' . $tmdb_id, [
|
||||
'query' => [
|
||||
'api_key' => $this->apiKey,
|
||||
'language' => strtolower($this->translation)
|
||||
]
|
||||
]);
|
||||
|
||||
return json_decode($response->getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current count of seasons.
|
||||
*
|
||||
* @param $result
|
||||
* @return integer | null
|
||||
*/
|
||||
private function tvSeasonsCount($id, $mediaType)
|
||||
{
|
||||
if($mediaType == 'tv') {
|
||||
$response = $this->client->get('/3/tv/' . $id, [
|
||||
'query' => [
|
||||
'api_key' => $this->apiKey,
|
||||
'language' => strtolower($this->translation)
|
||||
]
|
||||
]);
|
||||
|
||||
$seasons = collect(json_decode($response->getBody())->seasons);
|
||||
|
||||
return $seasons->filter(function ($season) {
|
||||
// We don't need pilots
|
||||
return $season->season_number > 0;
|
||||
})->count();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all episodes of each season.
|
||||
*
|
||||
* @param $id
|
||||
* @param $seasons
|
||||
* @return array
|
||||
*/
|
||||
public function tvEpisodes($id)
|
||||
{
|
||||
$seasons = $this->tvSeasonsCount($id, 'tv');
|
||||
$data = [];
|
||||
|
||||
for($i = 1; $i <= $seasons; $i++) {
|
||||
$response = $this->client->get('/3/tv/' . $id . '/season/' . $i, [
|
||||
'query' => [
|
||||
'api_key' => $this->apiKey,
|
||||
'language' => strtolower($this->translation)
|
||||
]
|
||||
]);
|
||||
|
||||
$data[$i] = json_decode($response->getBody());
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create genre string from genre_ids.
|
||||
*
|
||||
|
@ -4,10 +4,10 @@
|
||||
Route::post('/login', 'UserController@login');
|
||||
Route::get('/logout', 'UserController@logout');
|
||||
|
||||
Route::get('/items/{orderBy}', 'ItemController@items');
|
||||
Route::get('/items/{type}/{orderBy}', 'ItemController@items');
|
||||
Route::get('/search-items', 'ItemController@search');
|
||||
|
||||
Route::get('/suggestions/{tmdbID}', 'TMDBController@suggestions');
|
||||
Route::get('/suggestions/{tmdbID}/{mediaType}', 'TMDBController@suggestions');
|
||||
Route::get('/trending', 'TMDBController@trending');
|
||||
Route::get('/upcoming', 'TMDBController@upcoming');
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
Route::patch('/settings', 'SettingController@changeSettings');
|
||||
|
||||
Route::patch('/userdata', 'UserController@changeUserData');
|
||||
Route::patch('/set-seen/{id}', 'ItemController@setSeen');
|
||||
Route::get('/episodes/{tmdb_id}', 'ItemController@episodes');
|
||||
|
||||
Route::get('/search-tmdb', 'TMDBController@search');
|
||||
Route::post('/add', 'ItemController@add');
|
||||
|
@ -10,15 +10,15 @@
|
||||
<i class="icon-add" v-if=" ! rated"></i>
|
||||
</span>
|
||||
|
||||
<router-link :to="'/suggestions?for=' + localItem.tmdb_id" class="recommend-item">{{ lang('suggestions') }}</router-link>
|
||||
<router-link :to="'/suggestions?for=' + localItem.tmdb_id + '&type=' + localItem.media_type" class="recommend-item">{{ lang('suggestions') }}</router-link>
|
||||
<span class="remove-item" v-if="localItem.rating && auth" @click="removeItem()">{{ lang('delete movie') }}</span>
|
||||
|
||||
<img v-if="localItem.poster" :src="poster" class="item-image" width="185" height="278">
|
||||
<img v-if=" ! localItem.poster" :src="noImage" class="item-image" width="185" height="278">
|
||||
|
||||
<span class="show-episode" @click="changeEpisode()" v-if="localItem.type == 'tv'">
|
||||
<span class="season-item"><i>S</i>1/2</span>
|
||||
<span class="episode-item"><i>E</i>03/10</span>
|
||||
<span class="show-episode" @click="editEpisodes()" v-if="localItem.media_type == 'tv' && localItem.rating">
|
||||
<span class="season-item"><i>S</i>{{ season }}</span>
|
||||
<span class="episode-item"><i>E</i>{{ episode }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
import http from 'axios';
|
||||
import Helper from '../../helper';
|
||||
|
||||
import { mapMutations, mapActions } from 'vuex';
|
||||
|
||||
export default {
|
||||
mixins: [Helper],
|
||||
|
||||
@ -43,6 +45,7 @@
|
||||
data() {
|
||||
return {
|
||||
localItem: this.item,
|
||||
latestEpisode: this.item.latest_episode,
|
||||
saveTimeout: null,
|
||||
auth: config.auth,
|
||||
prevRating: null,
|
||||
@ -83,14 +86,46 @@
|
||||
|
||||
youtube() {
|
||||
return `https://www.youtube.com/results?search_query=${this.localItem.title} ${this.released} Trailer`;
|
||||
},
|
||||
|
||||
season() {
|
||||
if(this.latestEpisode) {
|
||||
return this.addZero(this.latestEpisode.season_number);
|
||||
}
|
||||
|
||||
return '01';
|
||||
},
|
||||
|
||||
episode() {
|
||||
if(this.latestEpisode) {
|
||||
return this.addZero(this.latestEpisode.episode_number);
|
||||
}
|
||||
|
||||
return '0';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
changeEpisode()
|
||||
{
|
||||
...mapMutations([ 'OPEN_MODAL' ]),
|
||||
...mapActions([ 'fetchEpisodes' ]),
|
||||
|
||||
editEpisodes() {
|
||||
this.fetchEpisodes({
|
||||
tmdb_id: this.localItem.tmdb_id,
|
||||
title: this.localItem.title
|
||||
});
|
||||
this.openModal();
|
||||
},
|
||||
|
||||
openModal() {
|
||||
if(this.auth) {
|
||||
console.log("changed");
|
||||
this.OPEN_MODAL({
|
||||
type: 'season',
|
||||
data: {
|
||||
tmdb_id: this.localItem.tmdb_id,
|
||||
title: this.localItem.title
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -122,6 +157,7 @@
|
||||
http.post(`${config.api}/add`, {item: this.localItem}).then(value => {
|
||||
this.localItem = value.data;
|
||||
this.disabled = false;
|
||||
this.rated = false;
|
||||
}, error => {
|
||||
if(error.status == 409) {
|
||||
alert(this.localItem.title + ' already exists!');
|
||||
|
Loading…
Reference in New Issue
Block a user