Add first batch of Trakt tv processing

This commit is contained in:
DariusIII
2015-11-04 15:06:58 +01:00
parent 217120d6bf
commit 30e5014023
20 changed files with 309 additions and 24 deletions
+7 -4
View File
@@ -12,16 +12,19 @@ if (!empty($argv[1]) && is_numeric($argv[2]) && is_numeric($argv[3])) {
// Test if your Trakt API key and configuration are working
// If it works you should get a printed array of the show/season/episode entered
$season = (int)$argv[2];
$episode = (int)$argv[3];
// Search for a show
$series = $trakt->client->showSearch((string)$argv[1], 'show');
$series = $trakt->client->showSummary((string)$argv[1]);
// Use the first show found (highest match) and get the requested season/episode from $argv
if (is_array($series)) {
$episode = $trakt->client->episodeSummary((int)$series[0]['show']['ids']['trakt'], (int)$argv[2], (int)$argv[3], 'full');
$ep = $trakt->client->episodeSummary((int)$series['ids']['trakt'], $season, $episode, 'full');
print_r($series[0]);
print_r($episode);
print_r($series);
print_r($ep);
} else {
exit($c->error("Error retrieving Trakt data."));
+1 -2
View File
@@ -273,7 +273,7 @@ HEADERS;
public function showSearch($show = '', $type = 'show')
{
$searchUrl = self::API_URL . 'search?query=' .
str_replace([' ', '_', '.'], '-', str_replace(['(', ')'], '', $show)) .
$this->slugify($show) .
'&type=' . $type;
return $this->getJsonArray($searchUrl, '');
@@ -312,7 +312,6 @@ HEADERS;
default:
$extended = '';
}
return $this->getJsonArray($showUrl, $extended);
}
+12
View File
@@ -730,6 +730,18 @@ abstract class TV extends Videos
case 'tvmazeE':
$required = ['name', 'season', 'number', 'airdate', 'summary'];
break;
case 'tmdbS':
$required = ['id', 'original_name', 'overview', 'first_air_date', 'origin_country'];
break;
case 'tmdbE':
$required = ['name', 'season_number', 'episode_number', 'air_date', 'overview'];
break;
case 'traktS':
$required = ['ids', 'title', 'overview', 'first_aired', 'country'];
break;
case 'traktE':
$required = ['title', 'season', 'number', 'airs', 'overview'];
break;
}
if (is_array($required)) {
+289 -18
View File
@@ -2,6 +2,7 @@
namespace newznab\processing\tv;
use newznab\libraries\TraktAPI;
use newznab\ReleaseImage;
/**
* Class TraktTv
@@ -10,6 +11,8 @@ use newznab\libraries\TraktAPI;
*/
class TraktTv extends TV
{
const MATCH_PROBABILITY = 75;
/**
* Client for Trakt API
*
@@ -27,7 +30,132 @@ class TraktTv extends TV
public function __construct(array $options = [])
{
parent::__construct($options);
$this->client = new TraktAPI(['clientID' => $this->pdo->getSetting('trakttvclientkey')]);
$this->client = new TraktAPI(['clientId' => $this->pdo->getSetting('trakttvclientkey')]);
$this->timeZone = new \DateTimeZone('UTC');
$this->timeFormat = 'Y-m-d H:i:s';
}
/**
* Main processing director function for Trakt
* Calls work query function and initiates processing
*
* @param $groupID
* @param $guidChar
* @param $processTV
* @param bool|false $local
*/
public function processTrakt($groupID, $guidChar, $processTV, $local = false)
{
$res = $this->getTvReleases($groupID, $guidChar, $processTV, parent::PROCESS_TRAKT);
$tvcount = $res->rowCount();
if ($this->echooutput && $tvcount > 1) {
echo $this->pdo->log->header("Processing TRAKT lookup for " . number_format($tvcount) . " release(s).");
}
if ($res instanceof \Traversable) {
foreach ($res as $row) {
$traktid = false;
// Clean the show name for better match probability
$release = $this->parseNameEpSeason($row['searchname']);
if (is_array($release) && $release['name'] != '') {
// Find the Video ID if it already exists by checking the title.
$videoId = $this->getByTitle($release['cleanname'], parent::TYPE_TV);
if ($videoId !== false) {
$traktid = $this->getSiteByID('trakt', $videoId);
}
// Force local lookup only
if ($local == true) {
$lookupSetting = false;
} else {
$lookupSetting = true;
}
if ($traktid === false && $lookupSetting) {
// If it doesnt exist locally and lookups are allowed lets try to get it.
if ($this->echooutput) {
echo $this->pdo->log->primaryOver("Video ID for ") .
$this->pdo->log->headerOver($release['cleanname']) .
$this->pdo->log->primary(" not found in local db, checking web.");
}
// Check if we have a valid country and set it in the array
$country = (isset($release['country']) && strlen($release['country']) == 2
? (string)$release['country']
: ''
);
// Get the show from TRAKT
$traktShow = $this->getShowInfo((string)$release['cleanname']);
if (is_array($traktShow)) {
$traktShow['country'] = $country;
$videoId = $this->add($traktShow);
$traktid = (int)$traktShow['ids']['trakt'];
}
} else if ($this->echooutput) {
echo $this->pdo->log->primaryOver("Video ID for ") .
$this->pdo->log->headerOver($release['cleanname']) .
$this->pdo->log->primary(" found in local db, attempting episode match.");
}
if (is_numeric($videoId) && $videoId > 0 && is_numeric($traktid) && $traktid > 0) {
// Now that we have valid video and trakt ids, try to get the poster
$this->getPoster($videoId, $traktid);
$seasonNo = preg_replace('/^S0*/i', '', $release['season']);
$episodeNo = preg_replace('/^E0*/i', '', $release['episode']);
if ($episodeNo === 'all') {
// Set the video ID and leave episode 0
$this->setVideoIdFound($videoId, $row['id'], 0);
echo $this->pdo->log->primary("Found TRAKT Match for Full Season!");
continue;
}
// Download all episodes if new show to reduce API/bandwidth usage
if ($this->countEpsByVideoID($videoId) === false) {
$this->getEpisodeInfo($traktid, -1, -1, '', $videoId);
}
// Check if we have the episode for this video ID
$episode = $this->getBySeasonEp($videoId, $seasonNo, $episodeNo, $release['airdate']);
if ($episode === false && $lookupSetting) {
// Send the request for the episode to TRAKT
$traktEpisode = $this->getEpisodeInfo(
$traktid,
$seasonNo,
$episodeNo,
$release['airdate']
);
if ($traktEpisode) {
$episode = $this->addEpisode($videoId, $traktEpisode);
}
}
if ($episode !== false && is_numeric($episode) && $episode > 0) {
// Mark the releases video and episode IDs
$this->setVideoIdFound($videoId, $row['id'], $episode);
if ($this->echooutput) {
echo $this->pdo->log->primary("Found TRAKT Match!");
}
continue;
}
}
} //Processing failed, set the episode ID to the next processing group
$this->setVideoNotFound(parent::PROCESS_IMDB, $row['id']);
}
}
}
/**
@@ -44,46 +172,189 @@ class TraktTv extends TV
}
/**
* Retrieve info of TV episode from site using its API.
* Gets the specific episode info for the parsed release after match
* Returns a formatted array of episode data or false if no match
*
* @param integer $siteId
* @param integer $series
* @param integer $traktid
* @param integer $season
* @param integer $episode
* @param string $airdate
* @param integer $videoId
*
* @return array|false False on failure, an array of information fields otherwise.
* @return array|bool
*/
public function getEpisodeInfo($siteId, $series, $episode)
protected function getEpisodeInfo($traktid, $season, $episode, $airdate = '', $videoId = 0)
{
;
$return = $response = false;
if ($videoId > 0) {
try {
$response = $this->client->showSummary($traktid);
} catch (\Exception $error) {
}
} else {
try {
$response = $this->client->episodeSummary($traktid, $season, $episode);
} catch (\Exception $error) {
}
}
sleep(1);
if (is_object($response)) {
if ($this->checkRequired($response, 'traktE')) {
$return = $this->formatEpisodeArr($response);
}
} else if (is_array($response) && $videoId > 0) {
if ($this->checkRequired($response, 'traktE')) {
$this->addEpisode($videoId, $this->formatEpisodeArr($response));
}
}
return $return;
}
public function getMovieInfo()
{
return false;
}
/**
* Retrieve poster image for TV episode from site using its API.
* Retrieves the poster art for the processed show
*
* @param integer $videoId ID from videos table.
* @param integer $siteId ID that this site uses for the programme.
* @param int $videoId -- the local Video ID
* @param int $showId -- the TRAKT ID
*
* @return null
*/
public function getPoster($videoId, $siteId)
protected function getPoster($videoId, $showId)
{
;
$ri = new ReleaseImage($this->pdo);
$poster = $this->client->showSummary($showId, 'images');
// Try to get the Poster
$hascover = $ri->saveImage($videoId, $poster['images']['poster']['thumb'], $this->imgSavePath, '', '');
// Couldn't get poster, try fan art instead
if ($hascover !== 1) {
$hascover = $ri->saveImage($videoId, $poster['images']['fanart']['thumb'], $this->imgSavePath, '', '');
}
// Mark it retrieved if we saved an image
if ($hascover == 1) {
$this->setCoverFound($videoId);
}
}
/**
* Retrieve info of TV programme from site using it's API.
* Calls the API to perform initial show name match to TRAKT title
* Returns a formatted array of show data or false if no match
*
* @param string $name Title of programme to look up. Usually a cleaned up version from releases table.
* @param string $cleanName
*
* @return array|false False on failure, an array of information fields otherwise.
* @param string $country
*
* @return array|bool
*/
public function getShowInfo($name)
protected function getShowInfo($cleanName, $country = '')
{
;
$return = $response = false;
$highestMatch = 0;
try {
$response = (array)$this->client->showSummary($cleanName, 'full');
} catch (\Exception $error) {
}
sleep(1);
if (is_array($response)) {
foreach ($response as $show) {
if ($this->checkRequired($show, 'traktS')) {
// Check for exact title match first and then terminate if found
if ($show->name === $cleanName) {
$highest = $show;
break;
}
// Check each show title for similarity and then find the highest similar value
$matchPercent = $this->checkMatch($show->name, $cleanName, self::MATCH_PROBABILITY);
// If new match has a higher percentage, set as new matched title
if ($matchPercent > $highestMatch) {
$highestMatch = $matchPercent;
$highest = $show;
}
// Check for show aliases and try match those too
if (!empty($show->aliasNames)) {
foreach ($show->aliasNames as $key => $name) {
$matchPercent = $this->CheckMatch($name, $cleanName, $matchPercent);
if ($matchPercent > $highestMatch) {
$highestMatch = $matchPercent;
$highest = $show;
}
}
}
}
}
if (isset($highest)) {
$return = $this->formatShowArr($highest);
}
}
return $return;
}
/**
* Assigns API show response values to a formatted array for insertion
* Returns the formatted array
*
* @param $show
*
* @return array
*/
private function formatShowArr($show)
{
$show->firstAired->setTimezone($this->timeZone);
preg_match('/tt(?P<imdbid>\d{6,7})$/i', $show->imdbId, $imdb);
return [
'type' => (int)parent::TYPE_TV,
'title' => (string)$show->name,
'summary' => (string)$show->overview,
'started' => (string)$show->firstAired->format($this->timeFormat),
'publisher' => (string)$show->network,
'source' => (int)parent::SOURCE_TRAKT,
'imdb' => (int)(isset($imdb['imdbid']) ? $imdb['imdbid'] : 0),
'tvdb' => 0,
'trakt' => (int)$show->id,
'tvrage' => (int)(isset($tvrage['tvaregid']) ? $tvrage['tvrageid'] : 0),
'tvmaze' => 0,
'tmdb' => (int)(isset($tmdb['tmdbid']) ? $tmdb['tmdbid'] : 0),
'aliases' => (!empty($show->aliasNames) ? (array)$show->aliasNames : '')
];
}
/**
* Assigns API episode response values to a formatted array for insertion
* Returns the formatted array
*
* @param $episode
*
* @return array
*/
private function formatEpisodeArr($episode)
{
$episode->firstAired->setTimezone($this->timeZone);
return [
'title' => (string)$episode->name,
'series' => (int)$episode->season,
'episode' => (int)$episode->number,
'se_complete' => (string)'S' . sprintf('%02d', $episode->season) . 'E' . sprintf('%02d', $episode->number),
'firstaired' => (string)$episode->firstAired->format($this->timeFormat),
'summary' => (string)$episode->overview
];
}
}
View File
View File
View File
Regular → Executable
View File
View File
View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File
View File
View File
View File
View File
View File
View File
Regular → Executable
View File
View File

Before

Width:  |  Height:  |  Size: 300 KiB

After

Width:  |  Height:  |  Size: 300 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB