mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-29 00:01:21 +00:00
Add first batch of Trakt tv processing
This commit is contained in:
@@ -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."));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
|
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 300 KiB |
Regular → Executable
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Reference in New Issue
Block a user