1<?php 2 3class TheTVDBBridge extends BridgeAbstract { 4 5 const MAINTAINER = 'Astyan'; 6 const NAME = 'TheTVDB'; 7 const URI = 'http://thetvdb.com/'; 8 const APIURI = 'https://api.thetvdb.com/'; 9 const CACHE_TIMEOUT = 43200; // 12h 10 const DESCRIPTION = 'Returns latest episodes of a serie with theTVDB api. You can contribute to theTVDB.'; 11 const PARAMETERS = array( 12 array( 13 'serie_id' => array( 14 'type' => 'number', 15 'name' => 'ID', 16 'required' => true, 17 ), 18 'nb_episode' => array( 19 'type' => 'number', 20 'name' => 'Number of episodes', 21 'defaultValue' => 10, 22 'required' => true, 23 ), 24 ) 25 ); 26 const APIACCOUNT = 'RSSBridge'; 27 const APIKEY = '76DE1887EA401C9A'; 28 const APIUSERKEY = 'B52869AC6005330F'; 29 30 private function getApiUri(){ 31 return self::APIURI; 32 } 33 34 private function getToken(){ 35 //login and get token, don't use curlJob to do less adaptations 36 $login_array = array( 37 'apikey' => self::APIKEY, 38 'username' => self::APIACCOUNT, 39 'userkey' => self::APIUSERKEY 40 ); 41 42 $login_json = json_encode($login_array); 43 $ch = curl_init($this->getApiUri() . 'login'); 44 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); 45 curl_setopt($ch, CURLOPT_POSTFIELDS, $login_json); 46 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 47 curl_setopt($ch, CURLOPT_HTTPHEADER, array( 48 'Content-Type: application/json', 49 'Accept: application/json' 50 ) 51 ); 52 53 curl_setopt($ch, CURLOPT_TIMEOUT, 5); 54 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); 55 $result = curl_exec($ch); 56 curl_close($ch); 57 $token_json = (array)json_decode($result); 58 if(isset($token_json['Error'])) { 59 throw new Exception($token_json['Error']); 60 die; 61 } 62 $token = $token_json['token']; 63 return $token; 64 } 65 66 private function curlJob($token, $url){ 67 $token_header = 'Authorization: Bearer ' . $token; 68 $ch = curl_init($url); 69 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); 70 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 71 curl_setopt($ch, CURLOPT_HTTPHEADER, array( 72 'Accept: application/json', 73 $token_header 74 ) 75 ); 76 curl_setopt($ch, CURLOPT_TIMEOUT, 5); 77 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); 78 $result = curl_exec($ch); 79 curl_close($ch); 80 $result_array = (array)json_decode($result); 81 if(isset($result_array['Error'])) { 82 throw new Exception($result_array['Error']); 83 die; 84 } 85 return $result_array; 86 } 87 88 private function getLatestSeasonNumber($token, $serie_id){ 89 // get the last season 90 $url = $this->getApiUri() . 'series/' . $serie_id . '/episodes/summary'; 91 $summary = $this->curlJob($token, $url); 92 return max($summary['data']->airedSeasons); 93 } 94 95 private function getSerieName($token, $serie_id){ 96 $url = $this->getApiUri() . 'series/' . $serie_id; 97 $serie = $this->curlJob($token, $url); 98 return $serie['data']->seriesName; 99 } 100 101 private function getSeasonEpisodes($token, 102 $serie_id, 103 $season, 104 $seriename, 105 &$episodelist, 106 $nbepisodemin, 107 $page = 1){ 108 $url = $this->getApiUri() 109 . 'series/' 110 . $serie_id 111 . '/episodes/query?airedSeason=' 112 . $season 113 . '?page=' 114 . $page; 115 116 $episodes = $this->curlJob($token, $url); 117 // we don't check the number of page because we assume there is less 118 //than 100 episodes in every season 119 $episodes = (array)$episodes['data']; 120 $episodes = array_slice($episodes, -$nbepisodemin, $nbepisodemin); 121 foreach($episodes as $episode) { 122 $episodedata = array(); 123 $episodedata['uri'] = $this->getURI() 124 . '?tab=episode&seriesid=' 125 . $serie_id 126 . '&seasonid=' 127 . $episode->airedSeasonID 128 . '&id=' 129 . $episode->id; 130 131 // check if the absoluteNumber exist 132 if(isset($episode->absoluteNumber)) { 133 $episodedata['title'] = 'S' 134 . $episode->airedSeason 135 . 'E' 136 . $episode->airedEpisodeNumber 137 . '(' 138 . $episode->absoluteNumber 139 . ') : ' 140 . $episode->episodeName; 141 } else { 142 $episodedata['title'] = 'S' 143 . $episode->airedSeason 144 . 'E' 145 . $episode->airedEpisodeNumber 146 . ' : ' 147 . $episode->episodeName; 148 } 149 $episodedata['author'] = $seriename; 150 $date = DateTime::createFromFormat( 151 'Y-m-d H:i:s', 152 $episode->firstAired . ' 00:00:00' 153 ); 154 155 $episodedata['timestamp'] = $date->getTimestamp(); 156 $episodedata['content'] = $episode->overview; 157 $episodelist[] = $episodedata; 158 } 159 } 160 161 public function getIcon() { 162 return self::URI . 'application/themes/thetvdb/images/logo.png'; 163 } 164 165 public function collectData(){ 166 $serie_id = $this->getInput('serie_id'); 167 $nbepisode = $this->getInput('nb_episode'); 168 $episodelist = array(); 169 $token = $this->getToken(); 170 $maxseason = $this->getLatestSeasonNumber($token, $serie_id); 171 $seriename = $this->getSerieName($token, $serie_id); 172 $season = $maxseason; 173 while(sizeof($episodelist) < $nbepisode && $season >= 1) { 174 $nbepisodetmp = $nbepisode - sizeof($episodelist); 175 $this->getSeasonEpisodes( 176 $token, 177 $serie_id, 178 $season, 179 $seriename, 180 $episodelist, 181 $nbepisodetmp 182 ); 183 184 $season = $season - 1; 185 } 186 // add the 10 last specials episodes 187 try { // catch to avoid error if empty 188 $this->getSeasonEpisodes( 189 $token, 190 $serie_id, 191 0, 192 $seriename, 193 $episodelist, 194 $nbepisode 195 ); 196 } catch(Exception $e) { 197 unset($e); 198 } 199 // sort and keep the 10 last episodes, works bad with the netflix serie 200 // (all episode lauch at once) 201 usort( 202 $episodelist, 203 function ($a, $b){ 204 return $a['timestamp'] < $b['timestamp']; 205 } 206 ); 207 $this->items = array_slice($episodelist, 0, $nbepisode); 208 } 209} 210