summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhorus2020-03-05 16:02:10 +0100
committerhorus2020-03-05 16:02:10 +0100
commit5dda561d73c9a5698386d643d56a142aa4bbdeec (patch)
tree55afe2db98d0fa15fc845cc3da3afe6b517bbd3d
parent420e44e0fe4623a439e26dfd0526ee5ef606a170 (diff)
downloadsenpai-5dda561d73c9a5698386d643d56a142aa4bbdeec.tar.gz
Committing intermediate state.
-rw-r--r--app/Airing.php16
-rw-r--r--app/Anime.php100
-rw-r--r--app/AnimeStats.php163
-rw-r--r--app/Calendar.php33
-rw-r--r--app/Console/Kernel.php10
-rw-r--r--app/Http/Controllers/IndexController.php54
-rw-r--r--app/Http/Controllers/TestController.php113
-rw-r--r--app/Libraries/AnimeSchedule.php56
-rw-r--r--app/Libraries/AnimeSeason.php22
-rw-r--r--app/Libraries/Background.php94
-rw-r--r--app/Libraries/Helper.php89
-rw-r--r--app/MALUser.php90
-rw-r--r--config/app.php2
-rw-r--r--database/migrations/2020_02_23_235746_create_anime_table.php11
-rw-r--r--database/migrations/2020_02_23_235949_create_stats_table.php46
-rw-r--r--database/migrations/2020_02_27_185936_create_airing_table.php35
-rw-r--r--database/migrations/2020_02_27_190422_add_fk_airing.php32
-rw-r--r--database/migrations/2020_03_01_151652_create_malusers.php34
-rw-r--r--database/migrations/2020_03_01_152954_create_is_watching.php42
-rw-r--r--database/migrations/2020_03_05_004655_add_duration_to_airing.php33
-rw-r--r--database/migrations/2020_03_05_011440_add_episodes_to_anime.php32
-rw-r--r--database/migrations/2020_03_05_162010_create_calendar.php52
-rw-r--r--query.sql35
-rw-r--r--routes/web.php4
-rw-r--r--todo.txt8
25 files changed, 1097 insertions, 109 deletions
diff --git a/app/Airing.php b/app/Airing.php
new file mode 100644
index 0000000..9e14571
--- /dev/null
+++ b/app/Airing.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Airing extends Model
+{
+ protected $table = 'airing';
+ protected $fillable = [
+ 'mal_id',
+ 'episode',
+ 'aired_at',
+ 'duration'
+ ];
+}
diff --git a/app/Anime.php b/app/Anime.php
index ac5c650..7971430 100644
--- a/app/Anime.php
+++ b/app/Anime.php
@@ -10,30 +10,28 @@ use Jikan\MyAnimeList\MalClient;
class Anime extends Model {
- /*
- public $id;
- public $mal_id;
-
- public $url;
- public $image_url;
-
- public $title_eng;
- public $title_rom;
- public $title_nat;
- public $title_pref;
-
- public $type;
- */
-
- private $animeInfo;
-
/**
* Eloquent ORM
*/
+ #protected $primarykey = 'mal_id';
protected $table = 'anime';
- protected $fillable = ['mal_id','url','image_url','title_eng','title_rom','title_nat','title_pref','type',];
+ protected $fillable = [
+ 'mal_id',
+ 'url',
+ 'image_url',
+ 'title_eng',
+ 'title_rom',
+ 'title_nat',
+ 'title_pref',
+ 'anime_type',
+ 'broadcasted',
+ 'episodes'
+ ];
+
+ public function __construct() {
+ }
- public function __construct( $id, $parse_info = true ) {
+ public function fill( $id, $parse_info = true ) {
$this->mal_id = $id;
if ( $parse_info ) {
@@ -51,18 +49,74 @@ class Anime extends Model {
$this->title_nat = $this->animeInfo->getTitleJapanese();
$this->title_pref = $this->animeInfo->getTitle();
- $this->type = $this->animeInfo->getType();
+ $this->anime_type = $this->animeInfo->getType();
+ $this->broadcasted = $this->animeInfo->getBroadcast();
+
+ $this->episodes = $this->animeInfo->getEpisodes();
}
}
- /*
public function getStats() {
- return $this->hasMany('App\AnimeStats');
+ return $this->hasMany('App\AnimeStats', 'mal_id', 'mal_id');
}
-*/
+
+ public function getAiring() {
+ return $this->hasMany('App\Airing', 'mal_id', 'mal_id');
+ }
protected function getInfo() {
return $this->animeInfo;
}
+ public function user() {
+ return $this->belongsToMany('App\MALUser', 'is_watching', 'mal_id', 'user_id')
+ ->as('anime')
+ ->withPivot('episodes_watched', 'score_user')
+ ->withTimestamps();
+ }
+
+ public function getDataFromAnilist() {
+ $query = '
+ query($id: Int!) {
+ Media(idMal: $id, type: ANIME) {
+ title {
+ romaji
+ english
+ native
+ userPreferred
+ }
+ nextAiringEpisode {
+ airingAt
+ timeUntilAiring
+ episode
+ }
+ episodes
+ duration
+ }
+ }
+ ';
+
+ // Define our query variables and values that will be used in the query request
+ $variables = [
+ "id" => $this->mal_id,
+ ];
+
+ // Make the HTTP Api request
+ try {
+ $http = new \GuzzleHttp\Client;
+ $response = $http->post('https://graphql.anilist.co', [
+ 'json' => [
+ 'query' => $query,
+ 'variables' => $variables,
+ ]
+ ]);
+
+ $data = json_decode( $response->getBody() )->data->Media;
+ } catch (\Exception $e) {
+ echo "Problem with Guzzle connecting to Anilist on anime: (" . $this->mal_id . ")\n";
+ return "";
+ }
+ return $data;
+ }
+
}
diff --git a/app/AnimeStats.php b/app/AnimeStats.php
index 3bc6d25..827032c 100644
--- a/app/AnimeStats.php
+++ b/app/AnimeStats.php
@@ -5,54 +5,83 @@ use Illuminate\Database\Eloquent\Model;
use Jikan\MyAnimeList\MalClient;
-#class AnimeStats extends Anime {
class AnimeStats extends Model {
/*
- public $mal_id;
-
- public $season_year;
- public $season_name;
-
- public $score;
- public $scored_by;
- public $rank;
- public $popularity;
- public $members;
- public $favorites;
-
- public $watching;
- public $completed;
- public $onhold;
- public $dropped;
- public $plan_to_watch;
-
- public $score_1;
- public $score_2;
- public $score_3;
- public $score_4;
- public $score_5;
- public $score_6;
- public $score_7;
- public $score_8;
- public $score_9;
- public $score_10;
+ private $mal_id;
+
+ private $season_year;
+ private $season_name;
+
+ private $score;
+ private $scored_by;
+ private $rank;
+ private $popularity;
+ private $members;
+ private $favorites;
+
+ private $watching;
+ private $completed;
+ private $onhold;
+ private $dropped;
+ private $plan_to_watch;
+
+ private $score_1;
+ private $score_2;
+ private $score_3;
+ private $score_4;
+ private $score_5;
+ private $score_6;
+ private $score_7;
+ private $score_8;
+ private $score_9;
+ private $score_10;
*/
/**
* Eloquent ORM
*/
protected $table = 'stats';
- protected $fillable = ['mal_id','season_year','season_name','score','scored_by','rank','popularity','members','favorites', 'watching','completed','onhold','dropped','plan_to_watch', 'score_1','score_2','score_3','score_4','score_5','score_6','score_7','score_8','score_9','score_10'];
+ protected $fillable = [
+ 'mal_id',
+
+ 'season_year',
+ 'season_name',
+
+ 'score',
+ 'scored_by',
+ 'rank',
+ 'popularity',
+ 'members',
+ 'favorites',
+
+ 'watching',
+ 'completed',
+ 'onhold',
+ 'dropped',
+ 'plan_to_watch',
+
+ 'score_1',
+ 'score_2',
+ 'score_3',
+ 'score_4',
+ 'score_5',
+ 'score_6',
+ 'score_7',
+ 'score_8',
+ 'score_9',
+ 'score_10'
+ ];
+
+ public function __construct() {
+ }
- public function __construct( $id, $season_year = 0, $season_name = "" ) {
+ public function fill( $id, $season_year = 0, $season_name = "" ) {
$this->mal_id = $id;
- #parent::__construct($this->mal_id);
-
$jikan = new Malclient;
-# if ( 0 == $season_year || "" == $season_name ) {
+ if ( 0 == $season_year || "" == $season_name ) {
$season = $jikan->getSeasonal(
(new \Jikan\Request\Seasonal\SeasonalRequest(
))
@@ -60,12 +89,10 @@ class AnimeStats extends Model {
$this->season_year = $season->seasonYear;
$this->season_name= $season->seasonName;
- /*
} else {
$this->season_year = $season_year;
$this->season_name= $season_name;
}
-*/
#$animeInfo = $this->getInfo();
$animeInfo = $jikan->getAnime(
@@ -90,16 +117,60 @@ class AnimeStats extends Model {
$scores = $animeStats->getScores();
- $this->score_1 = $scores[1]->getVotes();
- $this->score_2 = $scores[2]->getVotes();
- $this->score_3 = $scores[3]->getVotes();
- $this->score_4 = $scores[4]->getVotes();
- $this->score_5 = $scores[5]->getVotes();
- $this->score_6 = $scores[6]->getVotes();
- $this->score_7 = $scores[7]->getVotes();
- $this->score_8 = $scores[8]->getVotes();
- $this->score_9 = $scores[9]->getVotes();
- $this->score_10 = $scores[10]->getVotes();
+ if ( isset($scores[1] )) {
+ $this->score_1 = $scores[1]->getVotes();
+ } else {
+ $this->score_1 = 0;
+ }
+ if ( isset($scores[2]) ) {
+ $this->score_2 = $scores[2]->getVotes();
+ } else {
+ $this->score_2 = 0;
+ }
+ if ( isset($scores[3]) ) {
+ $this->score_3 = $scores[3]->getVotes();
+ } else {
+ $this->score_3 = 0;
+ }
+ if ( isset($scores[4]) ) {
+ $this->score_4 = $scores[4]->getVotes();
+ } else {
+ $this->score_4 = 0;
+ }
+ if ( isset($scores[5]) ) {
+ $this->score_5 = $scores[5]->getVotes();
+ } else {
+ $this->score_5 = 0;
+ }
+ if ( isset($scores[6]) ) {
+ $this->score_6 = $scores[6]->getVotes();
+ } else {
+ $this->score_6 = 0;
+ }
+ if ( isset($scores[7]) ) {
+ $this->score_7 = $scores[7]->getVotes();
+ } else {
+ $this->score_7 = 0;
+ }
+ if ( isset($scores[8]) ) {
+ $this->score_8 = $scores[8]->getVotes();
+ } else {
+ $this->score_8 = 0;
+ }
+ if ( isset($scores[9]) ) {
+ $this->score_9 = $scores[9]->getVotes();
+ } else {
+ $this->score_9 = 0;
+ }
+ if ( isset($scores[10]) ) {
+ $this->score_10 = $scores[10]->getVotes();
+ } else {
+ $this->score_10 = 0;
+ }
+ }
+
+ public function anime() {
+ return $this->belongsTo('App\Anime', 'mal_id', 'mal_id');
}
}
diff --git a/app/Calendar.php b/app/Calendar.php
new file mode 100644
index 0000000..a42e190
--- /dev/null
+++ b/app/Calendar.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Calendar extends Model
+{
+ protected $table = 'calendar';
+
+ protected $fillable = [
+ 'mal_id',
+ 'user_id',
+ 'airing_at',
+ 'duration',
+ 'episode',
+ 'episode_watched',
+ 'episode_complete',
+ 'score',
+ 'score_user',
+ ];
+
+ public function __construct() {
+ }
+
+ public function user() {
+ return $this->belongsTo('App\MALUser', 'user_id', 'id');
+ }
+
+ public function anime() {
+ return $this->belongsTo('App\Anime', 'mal_id', 'mal_id');
+ }
+}
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index a8c5158..fa58874 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -5,6 +5,9 @@ namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
+use App\Libraries\AnimeSeason;
+use App\Libraries\Helper;
+
class Kernel extends ConsoleKernel
{
/**
@@ -26,6 +29,13 @@ class Kernel extends ConsoleKernel
{
// $schedule->command('inspire')
// ->hourly();
+ $schedule->call( function(){
+ #$season = new AnimeSeason();
+ #$season->save();
+ #$helper = new Helper();
+ #$helper->setAiringForAll();
+ #$helper->setCalendar( 'll-' );
+ });
}
/**
diff --git a/app/Http/Controllers/IndexController.php b/app/Http/Controllers/IndexController.php
index e254c50..11e587f 100644
--- a/app/Http/Controllers/IndexController.php
+++ b/app/Http/Controllers/IndexController.php
@@ -6,7 +6,9 @@ use Illuminate\Http\Request;
use App\Libraries\AnimeSchedule;
use App\Libraries\AnimeSeason;
+use App\Anime;
use App\AnimeStats;
+use App\MALUser;
class IndexController extends Controller {
/**
@@ -36,11 +38,61 @@ class IndexController extends Controller {
}
public function test($param = null) {
- $season = new AnimeSeason();
+ echo "<pre>";
+ #$season = new AnimeSeason();
#$stats = new AnimeScore( 21 );
#var_dump($stats);
#echo "<pre>";
#var_dump($season);
+ #
+ #$test = new AnimeSchedule("", false);
+
+ #var_dump( Anime::where('mal_id', 38408)->with('user')->get() );
+ #var_dump( MALUser::where('username', 'll-')->with('anime')->toSql() );
+ #var_dump( MALUser::find(10)->anime()->get() );
+ $test = MALUser::where('username', 'll-')->get()->first();
+ #$test = MALUser::where('username', 'll-')->with('IsWatching')->first();
+ #var_dump($test);
+ #var_dump( MALUser::where('username', 'll-')->with('IsWatching')->firstOrFail() );
+ #var_dump( $test );
+ #var_dump( MALUser::with('IsWatching')->firstOrFail() );
+ echo "<pre>";
+ foreach( $test->IsWatching as $anime ) {
+ echo $anime->title_pref . "\n";
+ }
+ #var_dump($test->IsWatching);
+
+ }
+
+ public function saveWatchingAnime() {
+ $test = MALUser::where('username', 'll-')->get()->first();
+
+ $is_watching= $test->getIsWatching();
+ foreach( $is_watching as $anime_details ) {
+ $anime = Anime::where('mal_id', $anime_details["mal_id"])->get()->first();
+ #$anime->fill( $is_watching["mal_id"] );
+ $test->IsWatching()->save( $anime, $anime_details );
+ #var_dump($anime);
+ #exit;
+ }
+ #echo $test->test();
+ echo "OK";
+ }
+
+ public function createUser( $username ) {
+ $user = MALUser::where('username', $username)->get()->first();
+ var_dump( $user );
+
+ if ( is_null($user) ) {
+ $user = new MALUser();
+ $user->set( $username );
+
+ var_dump( $user );
+
+ $user->save();
+ }
+
+ echo $user->get();
}
}
diff --git a/app/Http/Controllers/TestController.php b/app/Http/Controllers/TestController.php
new file mode 100644
index 0000000..0ac9ba2
--- /dev/null
+++ b/app/Http/Controllers/TestController.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace App\Http\Controllers;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Http\Request;
+
+use Carbon\Carbon;
+
+use App\Libraries\AnimeSchedule;
+use App\Libraries\AnimeSeason;
+use App\Libraries\Helper;
+use App\Anime;
+use App\AnimeStats;
+use App\MALUser;
+use App\Calendar;
+use App\Airing;
+
+class TestController extends Controller {
+ /**
+ * Shows the index page.
+ *
+ * @return Response
+ */
+ public function showPage() {
+
+ return view('index', [ ]);
+ }
+
+ public function getCalendar( $username ) {
+ $helper = new Helper();
+ echo $helper->getCalendar( $username );
+ }
+
+ public function setCalendar( $username ) {
+ $helper = new Helper();
+ $helper->setCalendar( $username );
+ }
+
+ #public function iCal(Request $request) {
+ public function iCal($username) {
+
+ if ( ! Cache::has('schedule_' . $username)) {
+ $userSchedule = new AnimeSchedule( $username );
+ $schedule = $userSchedule->getCalendar();
+ Cache::put('schedule_' . $username, $schedule, 360);
+ } else {
+ $schedule = Cache::get('schedule_' . $username);
+ }
+
+ header('Content-Type: text/calendar; charset=utf-8');
+ #var_dump($schedule);
+ echo $schedule;
+ }
+
+ public function test($param = null) {
+ echo "<pre>";
+ #$season = new AnimeSeason();
+ #$stats = new AnimeScore( 21 );
+
+ #var_dump($stats);
+ #echo "<pre>";
+ #var_dump($season);
+ #
+ #$test = new AnimeSchedule("", false);
+
+ #var_dump( Anime::where('mal_id', 38408)->with('user')->get() );
+ #var_dump( MALUser::where('username', 'll-')->with('anime')->toSql() );
+ #var_dump( MALUser::find(10)->anime()->get() );
+ $test = MALUser::where('username', 'll-')->get()->first();
+ #$test = MALUser::where('username', 'll-')->with('IsWatching')->first();
+ #var_dump($test);
+ #var_dump( MALUser::where('username', 'll-')->with('IsWatching')->firstOrFail() );
+ #var_dump( $test );
+ #var_dump( MALUser::with('IsWatching')->firstOrFail() );
+ echo "<pre>";
+ foreach( $test->IsWatching as $anime ) {
+ echo $anime->title_pref . "\n";
+ }
+ #var_dump($test->IsWatching);
+
+ }
+
+ public function saveWatchingAnime() {
+ $test = MALUser::where('username', 'll-')->get()->first();
+
+ $is_watching= $test->getIsWatching();
+ foreach( $is_watching as $anime_details ) {
+ $anime = Anime::where('mal_id', $anime_details["mal_id"])->get()->first();
+ #$anime->fill( $is_watching["mal_id"] );
+ $test->IsWatching()->save( $anime, $anime_details );
+ #var_dump($anime);
+ #exit;
+ }
+ #echo $test->test();
+ echo "OK";
+ }
+
+ public function createUser( $username ) {
+ $user = MALUser::where('username', $username)->get()->first();
+ var_dump( $user );
+
+ if ( is_null($user) ) {
+ $user = new MALUser();
+ $user->set( $username );
+
+ var_dump( $user );
+
+ $user->save();
+ }
+
+ echo $user->get();
+ }
+}
diff --git a/app/Libraries/AnimeSchedule.php b/app/Libraries/AnimeSchedule.php
index 4c16f11..3b22494 100644
--- a/app/Libraries/AnimeSchedule.php
+++ b/app/Libraries/AnimeSchedule.php
@@ -16,19 +16,22 @@ class AnimeSchedule {
private $animeSchedule = array();
private $jikan;
- private $userProfile;
private $animeList;
private $animeInfo;
private const STATUS_WATCHING = 1;
- public function __construct( $username ) {
+ public function __construct( $username = "", $autoparse = true ) {
+
+ if ( $autoparse && "" != $username ) {
+ $this->parse( $username );
+ }
+ }
+
+ public function parse( $username ) {
$this->jikan = new MalClient;
- $this->userProfile = $this->jikan->getUserProfile(
- new \Jikan\Request\User\UserProfileRequest( $username )
- );
$this->animeList = $this->jikan->getUserAnimelist(
- new \Jikan\Request\User\UserAnimeListRequest( $this->userProfile->getUsername(), 1 )
+ new \Jikan\Request\User\UserAnimeListRequest( $username, 1, 1 )
);
foreach ( $this->animeList as $entry ) {
@@ -50,6 +53,8 @@ class AnimeSchedule {
$anime = new AnimeWatching( $entry->getMalID(), false );
+ $anime->url = $entry->getUrl();
+
$anime->title_eng = $data->title->english;
$anime->title_rom = $data->title->romaji;
$anime->title_nat = $data->title->native;
@@ -89,7 +94,7 @@ class AnimeSchedule {
->setNoTime(false)
->setSummary( $anime->title_pref . " (" . $anime->episode . "/" . $anime->episodes_complete . ")" )
->setUrl( env("APP_URL") )
- ->setDescription( "(Episode " . $anime->episode . "/" . $anime->episodes_complete . ") You have watched " . $anime->episodes_watched . " episodes of " . $anime->title_pref . " and scored it with " . $anime->score_user . ". (Public score: ". $anime->score .")" );
+ ->setDescription( "(Episode " . $anime->episode . "/" . $anime->episodes_complete . ") You have watched " . $anime->episodes_watched . " episodes of " . $anime->title_pref . " and scored it with " . $anime->score_user . ". (Public score: ". $anime->score .")\n\n" . $anime->url );
$vCalendar->addComponent($vEvent);
}
@@ -135,4 +140,41 @@ class AnimeSchedule {
$data = json_decode( $response->getBody() )->data->Media;
return $data;
}
+
+ protected function getIsWatching( $username ) {
+ $animeList = $this->getUserAnimeList( $username );
+
+ $anime = array();
+
+ foreach ( $animeList as $entry ) {
+ // currently watching
+ if ( $this::STATUS_WATCHING != $entry->getAiringStatus() ){
+ continue;
+ }
+
+ $anime[] = array(
+ "mal_id" => $entry->getMalID(),
+ "episodes_watched" => $entry->getWatchedEpisodes(),
+ "score_user" => $entry->getScore(),
+ );
+ }
+
+ return $anime;
+ }
+
+
+ protected function getUserAnimeList( $username ) {
+ $jikan = new MalClient;
+
+ $animeList = $jikan->getUserAnimelist(
+ new \Jikan\Request\User\UserAnimeListRequest( $username, 1, 1 )
+ );
+
+ return $animeList;
+ }
+
+ public function test() {
+ echo "<pre>";
+ var_dump( $this->getIsWatching('ll-') );
+ }
}
diff --git a/app/Libraries/AnimeSeason.php b/app/Libraries/AnimeSeason.php
index 1bc3655..f0296af 100644
--- a/app/Libraries/AnimeSeason.php
+++ b/app/Libraries/AnimeSeason.php
@@ -21,7 +21,10 @@ class AnimeSeason {
public $anime;
public function __construct() {
- #Anime::where('mal_id', 2 );
+ }
+
+ public function save() {
+ #Anime::where('mal_id', 2 );
$jikan = new MalClient;
$season = $jikan->getSeasonal(
@@ -34,10 +37,23 @@ class AnimeSeason {
$count = 0;
foreach($season->anime as $entry) {
+ /**
+ * Debug
+ if ( DB::table('stats')->where('mal_id', $entry->getMalID())->exists() ) {
+ continue;
+ }
+ #*/
+
+ /**
+ * Sleep to avoid 403 by MAL.
+ */
+ sleep(10);
+
$count++;
#Anime::where('mal_id', $entry->getMalID() );
- $anime = new Anime( $entry->getMalID() );
+ $anime = new Anime();
+ $anime->fill( $entry->getMalID() );
if( ! DB::table('anime')->where('mal_id', $entry->getMalID() )->exists() ) {
$anime->save();
@@ -51,11 +67,11 @@ class AnimeSeason {
/*
echo "<pre>";
var_dump($animeStats);
- */
if ( $count == 1) {
return;
}
+ */
}
}
diff --git a/app/Libraries/Background.php b/app/Libraries/Background.php
new file mode 100644
index 0000000..6c84e97
--- /dev/null
+++ b/app/Libraries/Background.php
@@ -0,0 +1,94 @@
+<?php
+namespace App\Libraries;
+
+use Carbon\Carbon;
+
+use App\Libraries\AnimeSchedule;
+use App\Libraries\AnimeSeason;
+use App\Anime;
+use App\AnimeStats;
+use App\MALUser;
+use App\Calendar;
+use App\Airing;
+
+use Eluceo\iCal\Component\Calendar as iCalendar;
+use Eluceo\iCal\Component\Event;
+
+class Background {
+
+ public function setAiring(Anime $anime) {
+ $stats = $anime->getStats()->get()->first();
+ if ( is_null($stats->score) ) {
+ return;
+ }
+
+ $airing = Airing::where('mal_id', $stats->mal_id)->get()->first();
+ if ( is_null($airing) ) {
+ $airing = new Airing();
+ }
+
+ /**
+ * Try to get Data from Anilist.
+ * On error return early.
+ */
+ try {
+ $airing_data = $anime->getDataFromAnilist();
+ } catch( Exception $e ) {
+ echo "Getting Data from Anilist failed for anime: " . $anime->title_pref . " (" . $anime->mal_id . ")\n";
+ return;
+ }
+ if ( "" == $airing_data ) {
+ echo "Got empty data from Anilist for anime: " . $anime->title_pref . " (" . $anime->mal_id . ")\n";
+ return;
+ }
+
+ /**
+ * Check if we need to save the airing data or if we already have it in database.
+ */
+ if ( ! is_null( $airing->episode ) ) {
+ if ( ! is_null( $airing_data->nextAiringEpisode ) &&
+ ( $airing->episode == $airing_data->nextAiringEpisode->episode) ) {
+ if ( $airing->aired_at == $airing_data->nextAiringEpisode->airingAt ) {
+ /**
+ * Double entry.
+ */
+ return;
+ }
+ /**
+ * We need to update because the airing data was postponed.
+ */
+ }
+ }
+
+ $airing->mal_id = $anime->mal_id;
+ if ( ! is_null($airing_data->nextAiringEpisode) ) {
+ $airing->episode = $airing_data->nextAiringEpisode->episode;
+ }
+ if ( ! is_null($airing_data->nextAiringEpisode) ) {
+ $airing->aired_at = Carbon::createFromTimestamp($airing_data->nextAiringEpisode->airingAt);
+ }
+ if ( ! is_null($airing_data) ) {
+ $airing->duration = $airing_data->duration;
+ }
+
+ if ( is_null($airing_data->duration) ) {
+ echo "No duration found for anime: " . $anime->title_pref . " (" . $anime->mal_id . "). (Autoset to 20.)\n";
+ $airing->duration = 20;
+ }
+
+ if ( is_null($airing->aired_at) ) {
+ echo "No airing date found for anime: " . $anime->title_pref . " (" . $anime->mal_id . ")\n";
+ return;
+ }
+
+ $airing->save();
+ }
+
+ public function setAiringForAll() {
+ $anime_all = Anime::get();
+ foreach( $anime_all as $anime ) {
+ $this->setAiring($anime);
+ sleep(1);
+ }
+ }
+}
diff --git a/app/Libraries/Helper.php b/app/Libraries/Helper.php
new file mode 100644
index 0000000..0652570
--- /dev/null
+++ b/app/Libraries/Helper.php
@@ -0,0 +1,89 @@
+<?php
+namespace App\Libraries;
+
+use Carbon\Carbon;
+
+use App\Libraries\AnimeSchedule;
+use App\Libraries\AnimeSeason;
+use App\Anime;
+use App\AnimeStats;
+use App\MALUser;
+use App\Calendar;
+use App\Airing;
+
+use Eluceo\iCal\Component\Calendar as iCalendar;
+use Eluceo\iCal\Component\Event;
+
+class Helper {
+ public function getCalendar( $username ) {
+ echo "<pre>";
+ $user = MALUser::where('username', $username)->get()->first();
+
+ $vCalendar = new iCalendar('animes.iamfabulous.de');
+ $vCalendar->setName('Anime Schedule');
+
+ foreach( $user->calendar()->get() as $anime ) {
+
+ if ( is_null($anime->episodes_completes) ) {
+ $episodes_complete = '?';
+ } else {
+ $episodes_complete = $anime->episodes_completes;
+ }
+
+ $vEvent = new Event();
+
+ $vEvent
+ ->setDtStart(new \DateTime($anime->airing_at))
+ ->setDtEnd( new \DateTime(Carbon::create($anime->airing_at)->add($anime->duration, 'minutes')) )
+ ->setNoTime(false)
+ ->setSummary( $anime->title . " (" . $anime->episode . "/" . $episodes_complete . ")" )
+ ->setUrl( env("APP_URL") )
+ ->setDescription( "(Episode " . $anime->episode . "/" . $episodes_complete . ") You have watched " . $anime->episodes_watched . " episodes of " . $anime->title . " and scored it with " . $anime->score_user . ". (Public score: ". $anime->score .")\n\n" . $anime->url );
+
+ $vCalendar->addComponent($vEvent);
+ }
+
+ return $vCalendar->render();
+
+ }
+
+ public function setCalendar($username) {
+ #$this->setAiring(); return;
+ $user = MALUser::where('username', $username)->get()->first();
+ echo "<pre>";
+ foreach( $user->IsWatching as $anime ) {
+ $stats = $anime->getStats()->get()->first();
+ $airing = $anime->getAiring()->get()->first();
+
+ /**
+ * Check for duplicate entry.
+ */
+ $check = Calendar::where('mal_id', $anime->mal_id)->where('user_id', $user->id)->where(
+ function($q) use ($airing){
+ $q->where('episode', $airing->episode)->orWhere('airing_at', $airing->aired_at);
+ })->get()->first();
+
+ if ( ! is_null( $check ) ) {
+ echo "duplicate entry. ".$anime->mal_id." continue\n"; continue;
+ }
+
+ $calendar = new Calendar();
+ $calendar->mal_id = $anime->mal_id;
+ $calendar->user_id = $anime->Watching->user_id;
+ $calendar->username = $username;
+ $calendar->airing_at = $airing->aired_at;
+ $calendar->duration = $airing->duration;
+ $calendar->episode = $airing->episode;
+ $calendar->episodes_watched = $anime->Watching->episodes_watched;
+ $calendar->episodes_complete = $anime->episodes;
+ $calendar->score = $stats->score;
+ $calendar->score_user = $anime->Watching->score_user;
+ $calendar->title = $anime->title_pref;
+ $calendar->mal_url = $anime->url;
+
+ $calendar->save();
+ }
+ }
+
+
+}
diff --git a/app/MALUser.php b/app/MALUser.php
new file mode 100644
index 0000000..6c62e30
--- /dev/null
+++ b/app/MALUser.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+use Jikan\MyAnimeList\MalClient;
+
+class MALUser extends Model
+{
+ protected $table = 'malusers';
+ protected $fillable = 'username';
+
+ public function __construct() {
+ }
+
+ public function set( $username ) {
+ $this->username = $username;
+ }
+
+ public function get() {
+ return $this->username;
+ }
+
+ public function IsWatching() {
+ return $this->belongsToMany('App\Anime', 'is_watching', 'user_id', 'mal_id', '', 'mal_id')
+ ->as('Watching')
+ ->withPivot('episodes_watched', 'score_user')
+ ->withTimestamps();
+ }
+
+ public function calendar() {
+ return $this->belongsTo('App\Calendar', 'id', 'user_id');
+ }
+
+ public function getIsWatching() {
+
+ $jikan = new MalClient;
+
+ $animeList = $jikan->getUserAnimelist(
+ new \Jikan\Request\User\UserAnimeListRequest( $this->username, 1, 1 )
+ );
+
+ $anime = array();
+
+ foreach ( $animeList as $entry ) {
+ // currently watching
+ if ( 1 != $entry->getAiringStatus() ){
+ continue;
+ }
+
+ $anime[] = array(
+ "user_id" => $this->id,
+ "mal_id" => $entry->getMalID(),
+ "episodes_watched" => $entry->getWatchedEpisodes(),
+ "score_user" => $entry->getScore(),
+ );
+ }
+
+ return $anime;
+ }
+
+ public function createCalendar() {
+ }
+
+ public function getCalendar() {
+ $vCalendar = new Calendar('animes.iamfabulous.de');
+ $vCalendar->setName('Anime Schedule');
+
+ foreach ( $this->animeSchedule as $anime ) {
+ $vEvent = new Event();
+
+ $vEvent
+ ->setDtStart(new \DateTime($anime->airing_at))
+ ->setDtEnd( new \DateTime($anime->airing_at->add($anime->duration, 'minutes')) )
+ ->setNoTime(false)
+ ->setSummary( $anime->title_pref . " (" . $anime->episode . "/" . $anime->episodes_complete . ")" )
+ ->setUrl( env("APP_URL") )
+ ->setDescription( "(Episode " . $anime->episode . "/" . $anime->episodes_complete . ") You have watched " . $anime->episodes_watched . " episodes of " . $anime->title_pref . " and scored it with " . $anime->score_user . ". (Public score: ". $anime->score .")\n\n" . $anime->url );
+
+ $vCalendar->addComponent($vEvent);
+ }
+
+ return $vCalendar->render();
+ }
+
+ public function test() {
+ echo "<pre>";
+ var_dump( $this->getIsWatching() );
+ }
+}
diff --git a/config/app.php b/config/app.php
index c9960cd..3bf8946 100644
--- a/config/app.php
+++ b/config/app.php
@@ -67,7 +67,7 @@ return [
|
*/
- 'timezone' => 'UTC',
+ 'timezone' => 'Europe/Berlin',
/*
|--------------------------------------------------------------------------
diff --git a/database/migrations/2020_02_23_235746_create_anime_table.php b/database/migrations/2020_02_23_235746_create_anime_table.php
index 985812e..f2df40f 100644
--- a/database/migrations/2020_02_23_235746_create_anime_table.php
+++ b/database/migrations/2020_02_23_235746_create_anime_table.php
@@ -21,12 +21,13 @@ class CreateAnimeTable extends Migration
$table->string('url')->default('');
$table->string('image_url')->default('');
- $table->string('title_eng')->default('');
- $table->string('title_rom')->default('');
- $table->string('title_nat')->default('');
- $table->string('title_pref')->default('');
+ $table->string('title_eng')->default('')->nullable();
+ $table->string('title_rom')->default('')->nullable();
+ $table->string('title_nat')->default('')->nullable();
+ $table->string('title_pref')->default('')->nullable();
- $table->string('type')->default('');
+ $table->string('anime_type')->default('')->nullable();
+ $table->string('broadcasted')->default('')->nullable();
$table->timestamps();
});
diff --git a/database/migrations/2020_02_23_235949_create_stats_table.php b/database/migrations/2020_02_23_235949_create_stats_table.php
index 142374c..5516789 100644
--- a/database/migrations/2020_02_23_235949_create_stats_table.php
+++ b/database/migrations/2020_02_23_235949_create_stats_table.php
@@ -21,29 +21,29 @@ class CreateStatsTable extends Migration
$table->string('season_name')->default('');
$table->integer('season_year')->default(0);
- $table->float('score')->default(0);
- $table->integer('scored_by')->default(0);
- $table->integer('rank')->default(0);
- $table->integer('popularity')->default(0);
- $table->integer('members')->default(0);
- $table->integer('favorites')->default(0);
-
- $table->integer('watching')->default(0);
- $table->integer('completed')->default(0);
- $table->integer('onhold')->default(0);
- $table->integer('dropped')->default(0);
- $table->integer('plan_to_watch')->default(0);
-
- $table->integer('score_1')->default(0);
- $table->integer('score_2')->default(0);
- $table->integer('score_3')->default(0);
- $table->integer('score_4')->default(0);
- $table->integer('score_5')->default(0);
- $table->integer('score_6')->default(0);
- $table->integer('score_7')->default(0);
- $table->integer('score_8')->default(0);
- $table->integer('score_9')->default(0);
- $table->integer('score_10')->default(0);
+ $table->float('score')->default(0)->nullable();
+ $table->integer('scored_by')->default(0)->nullable();
+ $table->integer('rank')->default(0)->nullable();
+ $table->integer('popularity')->default(0)->nullable();
+ $table->integer('members')->default(0)->nullable();
+ $table->integer('favorites')->default(0)->nullable();
+
+ $table->integer('watching')->default(0)->nullable();
+ $table->integer('completed')->default(0)->nullable();
+ $table->integer('onhold')->default(0)->nullable();
+ $table->integer('dropped')->default(0)->nullable();
+ $table->integer('plan_to_watch')->default(0)->nullable();
+
+ $table->integer('score_1')->default(0)->nullable();
+ $table->integer('score_2')->default(0)->nullable();
+ $table->integer('score_3')->default(0)->nullable();
+ $table->integer('score_4')->default(0)->nullable();
+ $table->integer('score_5')->default(0)->nullable();
+ $table->integer('score_6')->default(0)->nullable();
+ $table->integer('score_7')->default(0)->nullable();
+ $table->integer('score_8')->default(0)->nullable();
+ $table->integer('score_9')->default(0)->nullable();
+ $table->integer('score_10')->default(0)->nullable();
$table->timestamps();
});
diff --git a/database/migrations/2020_02_27_185936_create_airing_table.php b/database/migrations/2020_02_27_185936_create_airing_table.php
new file mode 100644
index 0000000..efc0a1d
--- /dev/null
+++ b/database/migrations/2020_02_27_185936_create_airing_table.php
@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateAiringTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create('airing', function (Blueprint $table) {
+ $table->bigIncrements('id');
+ $table->timestamps();
+
+ $table->unsignedBigInteger('mal_id')->default(0);
+ $table->integer('episode')->default(0);
+ $table->dateTime('aired_at');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('airing');
+ }
+}
diff --git a/database/migrations/2020_02_27_190422_add_fk_airing.php b/database/migrations/2020_02_27_190422_add_fk_airing.php
new file mode 100644
index 0000000..24de5cb
--- /dev/null
+++ b/database/migrations/2020_02_27_190422_add_fk_airing.php
@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddFkAiring extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::table('airing', function (Blueprint $table) {
+ $table->foreign('mal_id')->references('mal_id')->on('anime');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('airing', function (Blueprint $table) {
+ //
+ });
+ }
+}
diff --git a/database/migrations/2020_03_01_151652_create_malusers.php b/database/migrations/2020_03_01_151652_create_malusers.php
new file mode 100644
index 0000000..cd55278
--- /dev/null
+++ b/database/migrations/2020_03_01_151652_create_malusers.php
@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateMalusers extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create('malusers', function (Blueprint $table) {
+ $table->bigIncrements('id');
+
+ $table->string('username')->unique()->default('');
+
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('malusers');
+ }
+}
diff --git a/database/migrations/2020_03_01_152954_create_is_watching.php b/database/migrations/2020_03_01_152954_create_is_watching.php
new file mode 100644
index 0000000..30c5bd6
--- /dev/null
+++ b/database/migrations/2020_03_01_152954_create_is_watching.php
@@ -0,0 +1,42 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateIsWatching extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create('is_watching', function (Blueprint $table) {
+ $table->bigIncrements('id');
+
+ $table->unsignedBigInteger('mal_id')->default(0);
+ $table->unsignedBigInteger('user_id')->default(0);
+
+ $table->integer('episodes_watched')->nullable()->default(0);
+ $table->float('score_user')->nullable()->default(0);
+
+ $table->unique( ['mal_id', 'user_id'] );
+ $table->foreign('mal_id')->references('mal_id')->on('anime');
+ $table->foreign('user_id')->references('id')->on('malusers');
+
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('is_watching');
+ }
+}
diff --git a/database/migrations/2020_03_05_004655_add_duration_to_airing.php b/database/migrations/2020_03_05_004655_add_duration_to_airing.php
new file mode 100644
index 0000000..4b3c992
--- /dev/null
+++ b/database/migrations/2020_03_05_004655_add_duration_to_airing.php
@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddDurationToAiring extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::table('airing', function (Blueprint $table) {
+ $table->integer('duration')->default(0);
+ $table->unique(['mal_id', 'episode']);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('airing', function (Blueprint $table) {
+ //
+ });
+ }
+}
diff --git a/database/migrations/2020_03_05_011440_add_episodes_to_anime.php b/database/migrations/2020_03_05_011440_add_episodes_to_anime.php
new file mode 100644
index 0000000..948a84e
--- /dev/null
+++ b/database/migrations/2020_03_05_011440_add_episodes_to_anime.php
@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddEpisodesToAnime extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::table('anime', function (Blueprint $table) {
+ $table->integer('episodes')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('anime', function (Blueprint $table) {
+ //
+ });
+ }
+}
diff --git a/database/migrations/2020_03_05_162010_create_calendar.php b/database/migrations/2020_03_05_162010_create_calendar.php
new file mode 100644
index 0000000..3a6cb8f
--- /dev/null
+++ b/database/migrations/2020_03_05_162010_create_calendar.php
@@ -0,0 +1,52 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateCalendar extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create('calendar', function (Blueprint $table) {
+ $table->bigIncrements('id');
+
+ $table->unsignedBigInteger('mal_id')->default(0);
+ $table->unsignedBigInteger('user_id')->default(0);
+
+ $table->string('username')->default('');
+ $table->timestamp('airing_at');
+ $table->integer('duration')->default('20');
+ $table->integer('episode')->default(0);
+ $table->integer('episodes_watched')->default(0)->nullable();
+ $table->integer('episodes_complete')->default(0)->nullable();
+ $table->float('score')->default(0)->nullable();
+ $table->integer('score_user')->default(0)->nullable();
+ $table->string('mal_url')->default('');
+ $table->string('title')->default('');
+
+ $table->foreign('mal_id')->references('mal_id')->on('anime');
+ $table->foreign('user_id')->references('id')->on('malusers');
+
+ $table->unique(['mal_id', 'user_id', 'airing_at']);
+ $table->unique(['mal_id', 'user_id', 'episode']);
+
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('calendar');
+ }
+}
diff --git a/query.sql b/query.sql
new file mode 100644
index 0000000..f1f28e9
--- /dev/null
+++ b/query.sql
@@ -0,0 +1,35 @@
+-- query every anime with recent score
+select
+ title_pref, score
+from anime
+join stats on stats.id =
+ (
+ select
+ id
+ from stats
+ where
+ anime.mal_id = stats.mal_id
+ order by created_at desc limit 1
+ )
+order by title_pref, score desc;
+
+-- query historic stats for one anime
+select
+ title_pref,
+ anime_type,
+ score,
+ popularity,
+ members,
+ (watching+completed+onhold+dropped) as members_watching,
+ plan_to_watch,
+ favorites,
+ season_name,
+ season_year,
+ stats.created_at
+from anime
+join stats on
+ anime.mal_id = stats.mal_id
+where
+ anime.mal_id = 38883
+order by stats.created_at;
+
diff --git a/routes/web.php b/routes/web.php
index ebf4494..7c5a948 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -14,3 +14,7 @@
Route::get('/', 'IndexController@showPage');
Route::get('/ical/{username}', 'IndexController@ical');
Route::get('/test/{param?}', 'IndexController@test');
+Route::get('/create/user/{param}', 'IndexController@createUser');
+Route::get('/save', 'IndexController@saveWatchingAnime');
+Route::get('/test/getcal/{username}', 'TestController@getCalendar');
+Route::get('/test/setcal/{username}', 'TestController@setCalendar');
diff --git a/todo.txt b/todo.txt
new file mode 100644
index 0000000..b5f6f48
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1,8 @@
+Background jobs:
+
+1. Alle Anime der Season downloaden und in Datenbank einpflegen
+2. Für jeden Anime die Statistiken downloadnen
+3. Für alle aktuellen Anime den nächsten Airing Zeitpunkt einpflegen
+4. Für jeden User einen Kalender generieren
+5. Die Top 1000 der populärsten Anime in die Datenbank übertragen
+6. Dasselbe für die Top 1000 der besten Anime.