From 5dda561d73c9a5698386d643d56a142aa4bbdeec Mon Sep 17 00:00:00 2001 From: horus Date: Thu, 5 Mar 2020 16:02:10 +0100 Subject: Committing intermediate state. --- app/Airing.php | 16 +++ app/Anime.php | 100 ++++++++++++++----- app/AnimeStats.php | 163 ++++++++++++++++++++++--------- app/Calendar.php | 33 +++++++ app/Console/Kernel.php | 10 ++ app/Http/Controllers/IndexController.php | 54 +++++++++- app/Http/Controllers/TestController.php | 113 +++++++++++++++++++++ app/Libraries/AnimeSchedule.php | 56 +++++++++-- app/Libraries/AnimeSeason.php | 22 ++++- app/Libraries/Background.php | 94 ++++++++++++++++++ app/Libraries/Helper.php | 89 +++++++++++++++++ app/MALUser.php | 90 +++++++++++++++++ 12 files changed, 760 insertions(+), 80 deletions(-) create mode 100644 app/Airing.php create mode 100644 app/Calendar.php create mode 100644 app/Http/Controllers/TestController.php create mode 100644 app/Libraries/Background.php create mode 100644 app/Libraries/Helper.php create mode 100644 app/MALUser.php (limited to 'app') 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 @@ +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 @@ +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 "
";
+		#$season = new AnimeSeason();
 		#$stats = new AnimeScore( 21 );
 
 		#var_dump($stats);
 		#echo "
";
 		#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 "
";
+		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 @@
+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 "
";
+		#$season = new AnimeSeason();
+		#$stats = new AnimeScore( 21 );
+
+		#var_dump($stats);
+		#echo "
";
+		#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 "
";
+		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 "
";
+		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 "
";
 			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 @@
+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 @@
+";
+		$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 "
";
+                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 @@
+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 "
";
+		var_dump( $this->getIsWatching() );
+	}
+}
-- 
cgit v1.2.3