Merge pull request #590 from WebTools-NG/#573-Add-tvdb-to-find-missing-episodes

#573 add tvdb to find missing episodes
This commit is contained in:
Tommy Mikkelsen 2022-09-15 22:37:51 +02:00 committed by GitHub
commit 5cc3facaae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 586 additions and 352 deletions

View file

@ -1,5 +1,16 @@
# ![Logo](https://github.com/WebTools-NG/WebTools-NG/blob/master/src/assets/WebTools-48x48.png) WebTools-ng Change log # ![Logo](https://github.com/WebTools-NG/WebTools-NG/blob/master/src/assets/WebTools-48x48.png) WebTools-ng Change log
## V1.1.1 ( Not released yet )
**Note**: In this version, the following is disabled:
* Export to xlsx format ([See #331](https://github.com/WebTools-NG/WebTools-NG/issues/331))
* Photo export
**Changes**:
* [#573 Add tvdb to find missing episodes](https://github.com/WebTools-NG/WebTools-NG/issues/573) (Enhancement)
## V1.1.0 ( 20220913 ) ## V1.1.0 ( 20220913 )
**Note**: In this version, the following is disabled: **Note**: In this version, the following is disabled:

2
package-lock.json generated
View file

@ -1,6 +1,6 @@
{ {
"name": "webtools-ng", "name": "webtools-ng",
"version": "1.1.0", "version": "1.1.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {

View file

@ -1,7 +1,7 @@
{ {
"name": "webtools-ng", "name": "webtools-ng",
"productName": "WebTools-NG", "productName": "WebTools-NG",
"version": "1.1.0", "version": "1.1.1",
"description": "WebTools Next Generation 4 Plex", "description": "WebTools Next Generation 4 Plex",
"author": "dane22 & CPSO", "author": "dane22 & CPSO",
"license": "MPL-2.0", "license": "MPL-2.0",

View file

@ -31,7 +31,6 @@
@change="selExpTypeMainChanged" @change="selExpTypeMainChanged"
name="selExpTypeMain"> name="selExpTypeMain">
</b-form-select> </b-form-select>
<WTNGtt tt="Modules.ET.optExpType.ttExpType" size="20px"></WTNGtt>
</b-form-group> </b-form-group>
</div> </div>
</b-col> </b-col>

File diff suppressed because it is too large Load diff

View file

@ -75,12 +75,14 @@
"findmissingEp": [ "findmissingEp": [
"Key", "Key",
"Title", "Title",
"TMDB Link", "Sort Season by",
"Show Episode Count (PMS)", "Link (Cloud)",
"Show Episode Count (TMDB)", "Status (Cloud)",
"Show Season Count (PMS)", "Episode Count (PMS)",
"Show Season Count (TMDB)", "Season Count (PMS)",
"TMDB Status", "Episode Count (Cloud)",
"Season Count (Cloud)",
"Seasons (Cloud)",
"Missing" "Missing"
] ]
} }

View file

@ -10,6 +10,7 @@ import Excel from 'exceljs';
import { status } from '../../General/status'; import { status } from '../../General/status';
import { time } from '../../General/time'; import { time } from '../../General/time';
import { tmdb } from '../../General/tmdb'; import { tmdb } from '../../General/tmdb';
import { tvdb } from '../../General/tvdb';
var path = require("path"); var path = require("path");
var sanitize = require("sanitize-filename"); var sanitize = require("sanitize-filename");
@ -308,7 +309,9 @@ const etHelper = new class ETHELPER {
element: null, element: null,
SelectedMoviesID: null, SelectedMoviesID: null,
SelectedShowsID: wtconfig.get("ET.SelectedShowsID", "tmdb"), SelectedShowsID: wtconfig.get("ET.SelectedShowsID", "tmdb"),
tmdbShowInfo: null showInfo: null,
SelectedLibShowOrdering: null,
tvdbBearer: null
}; };
this.PMSHeader = wtutils.PMSHeader; this.PMSHeader = wtutils.PMSHeader;
@ -428,6 +431,8 @@ const etHelper = new class ETHELPER {
this.Settings.fields = null; this.Settings.fields = null;
this.Settings.currentItem = 0; this.Settings.currentItem = 0;
this.Settings.totalItems = null; this.Settings.totalItems = null;
this.Settings.SelectedLibShowOrdering = null;
this.Settings.showInfo = null;
} }
isEmpty( {val} ) isEmpty( {val} )
@ -543,13 +548,23 @@ const etHelper = new class ETHELPER {
case "Audience Rating": case "Audience Rating":
retVal = val.substring(0, 3); retVal = val.substring(0, 3);
break; break;
case "Episode Count (Cloud)":
retVal = wtconfig.get('ET.NotAvail');
if ( this.Settings.showInfo['Episode Count (Cloud)']){
retVal = this.Settings.showInfo['Episode Count (Cloud)'];
}
break;
case "Episode Count (PMS)":
this.Settings.showInfo['PMSEPCount'] = parseInt(val);
retVal = val;
break;
case "Missing": case "Missing":
retVal = i18n.t('Common.Ok'); retVal = i18n.t('Common.Ok');
if ( this.Settings.tmdbShowInfo['TMDBEPCount'] != this.Settings.tmdbShowInfo['PMSEPCount']){ if ( this.Settings.showInfo['Episode Count (Cloud)'] != this.Settings.showInfo['PMSEPCount']){
retVal = "Episode mismatch" retVal = "Episode mismatch"
} }
if (!this.Settings.tmdbShowInfo['TMDBEPCount']){ if (!this.Settings.showInfo['Episode Count (Cloud)']){
retVal = "No tmdb Guid found" retVal = "No Guid found, please refresh metadata, or sort order not avail at cloud provider"
} }
break; break;
case "Rating": case "Rating":
@ -720,6 +735,12 @@ const etHelper = new class ETHELPER {
retVal = retVal.split('?')[0]; retVal = retVal.split('?')[0];
} }
break; break;
case "Link (Cloud)":
retVal = wtconfig.get('ET.NotAvail');
if ( this.Settings.showInfo['Link (Cloud)']){
retVal = this.Settings.showInfo['Link (Cloud)'];
}
break;
case "TVDB ID": case "TVDB ID":
retVal = wtconfig.get('ET.NotAvail'); retVal = wtconfig.get('ET.NotAvail');
guidArr = val.split(wtconfig.get('ET.ArraySep')); guidArr = val.split(wtconfig.get('ET.ArraySep'));
@ -797,12 +818,6 @@ const etHelper = new class ETHELPER {
} }
} }
break; break;
case "TMDB Status":
retVal = wtconfig.get('ET.NotAvail');
if ( this.Settings.tmdbShowInfo['TMDBStatus']){
retVal = this.Settings.tmdbShowInfo['TMDBStatus'];
}
break;
case "PMS Media Path": case "PMS Media Path":
retVal = wtconfig.get('ET.NotAvail'); retVal = wtconfig.get('ET.NotAvail');
var hashes = await this.getHash(data); var hashes = await this.getHash(data);
@ -841,16 +856,25 @@ const etHelper = new class ETHELPER {
//var path = require('path'); //var path = require('path');
retVal = path.join('Metadata', libTypeName, sha1[0], sha1.slice(1) + '.bundle'); retVal = path.join('Metadata', libTypeName, sha1[0], sha1.slice(1) + '.bundle');
break; break;
case "Show Episode Count (PMS)": case "Season Count (Cloud)":
this.Settings.tmdbShowInfo['PMSEPCount'] = parseInt(val); retVal = wtconfig.get('ET.NotAvail');
if ( this.Settings.showInfo['Season Count (Cloud)']){
retVal = this.Settings.showInfo['Season Count (Cloud)'];
}
break;
case "Season Count (PMS)":
this.Settings.showInfo['PMSSCount'] = parseInt(val);
retVal = val; retVal = val;
break; break;
case "Show Episode Count (TMDB)": case "Seasons (Cloud)":
retVal = wtconfig.get('ET.NotAvail'); retVal = wtconfig.get('ET.NotAvail');
if ( this.Settings.tmdbShowInfo['TMDBEPCount']){ if ( this.Settings.showInfo['Seasons (Cloud)']){
retVal = String(this.Settings.tmdbShowInfo['TMDBEPCount']); retVal = JSON.stringify(this.Settings.showInfo['Seasons (Cloud)']);
} }
break; break;
case "Sort Season by":
retVal = this.Settings.showInfo['showOrdering'];
break;
case "Show Prefs Episode sorting": case "Show Prefs Episode sorting":
switch (val){ switch (val){
case "-1": case "-1":
@ -971,14 +995,10 @@ const etHelper = new class ETHELPER {
break; break;
} }
break; break;
case "Show Season Count (PMS)": case "Status (Cloud)":
this.Settings.tmdbShowInfo['PMSSCount'] = parseInt(val);
retVal = val;
break;
case "Show Season Count (TMDB)":
retVal = wtconfig.get('ET.NotAvail'); retVal = wtconfig.get('ET.NotAvail');
if ( this.Settings.tmdbShowInfo['TMDBSCount']){ if ( this.Settings.showInfo['Status (Cloud)']){
retVal = String(this.Settings.tmdbShowInfo['TMDBSCount']); retVal = this.Settings.showInfo['Status (Cloud)'];
} }
break; break;
default: default:
@ -992,17 +1012,123 @@ const etHelper = new class ETHELPER {
return await retVal; return await retVal;
} }
// Get library default show ordering
async SelectedLibShowOrdering(){
console.log('Ged 44-3', this.Settings.SelectedLibShowOrdering)
if (!this.Settings.SelectedLibShowOrdering){
// We need to get the default for this library
log.info(`[ethelper.js] (SelectedLibShowOrdering) - Getting default show ordering for library ${this.Settings.LibName}`);
let url = `${this.Settings.baseURL}/library/sections/all?includePreferences=1`;
this.PMSHeader["X-Plex-Token"] = this.Settings.accessToken;
log.verbose(`[ethelper.js] (SelectedLibShowOrdering) Calling url: ${url}`);
let response = await fetch(url, { method: 'GET', headers: this.PMSHeader});
let resp = await response.json();
this.Settings.SelectedLibShowOrdering = JSONPath({path: `$..Directory[?(@.key==${this.Settings.selLibKey})].Preferences.Setting[?(@.id=="showOrdering")].value`, json: resp})[0];
log.info(`[ethelper.js] (SelectedLibShowOrdering) - Default show ordering for library is: ${this.Settings.SelectedLibShowOrdering}`);
}
return this.Settings.SelectedLibShowOrdering
}
// Get specific show ordering
async getShowOrdering( { ratingKey } ){
let url = `${this.Settings.baseURL}/library/metadata/${ratingKey}?includeGuids=0&includePreferences=1&checkFiles=0&includeRelated=0&includeExtras=0&includeBandwidths=0&includeChapters=0&excludeElements=Actor,Collection,Country,Director,Genre,Label,Mood,Producer,Similar,Writer,Role&excludeFields=summary,tagline`;
this.PMSHeader["X-Plex-Token"] = this.Settings.accessToken;
log.verbose(`[ethelper.js] (getShowOrdering) Calling url: ${url}`);
let response = await fetch(url, { method: 'GET', headers: this.PMSHeader});
let resp = await response.json();
console.log('Ged 54-3', this.Settings.SelectedLibShowOrdering)
var showOrder = JSONPath({path: `$..Preferences.Setting[?(@.id=="showOrdering")].value`, json: resp})[0];
if (showOrder != ""){
this.Settings.showInfo['showOrdering'] = showOrder;
} else {
this.Settings.showInfo['showOrdering'] = await this.SelectedLibShowOrdering();
}
}
async addRowToTmp( { data }) { async addRowToTmp( { data }) {
if ( this.Settings.levelName == 'Find Missing Episodes'){ if ( this.Settings.levelName == 'Find Missing Episodes'){
// Special level, so we need to get info from tmdb this.Settings.showInfo = {};
log.info(`[ethelper.js] (addRowToTmp) - Level "Find Missing Episodes" selected, so we must contact tmdb`); let id, attributename;
this.Settings.tmdbShowInfo = {}; await this.getShowOrdering( { "ratingKey": data["ratingKey"] } );
const tmdbId = String(JSONPath({ path: "$.Guid[?(@.id.startsWith('tmdb'))].id", json: data })).substring(7,); switch ( this.Settings.showInfo["showOrdering"] ) {
if ( tmdbId){ case "tmdbAiring":
this.Settings.tmdbShowInfo = await tmdb.getTMDBShowInfo(tmdbId); // Special level, so we need to get info from tmdb
} else { log.info(`[ethelper.js] (addRowToTmp) - Level "Find Missing Episodes" selected, so we must contact tmdb`);
const title = JSONPath({ path: "$.title", json: data }); id = String(JSONPath({ path: "$.Guid[?(@.id.startsWith('tmdb'))].id", json: data })).substring(7,);
log.error(`[ethelper.js] (addRowToTmp) - No tmdb guid found for ${title}`); if ( id ){
this.Settings.showInfo["Link (Cloud)"] = `https://www.themoviedb.org/tv/${id}`;
const TMDBInfo = await tmdb.getTMDBShowInfo(id);
for( attributename in TMDBInfo){
this.Settings.showInfo[attributename] = TMDBInfo[attributename];
}
} else {
const title = JSONPath({ path: "$.title", json: data });
log.error(`[ethelper.js] (addRowToTmp) - No tmdb guid found for ${title}`);
}
this.Settings.showInfo["showOrdering"] = "TMDB Airing";
this.Settings.showInfo["Status"] = this.Settings.showInfo["TMDBStatus"];
break;
case "aired":
// Special level, so we need to get info from tvdb
log.info(`[ethelper.js] (addRowToTmp) - Level "Find Missing Episodes" selected, so we must contact tvdb`);
id = String(JSONPath({ path: "$.Guid[?(@.id.startsWith('tvdb'))].id", json: data })).substring(7,);
// Get TVDB Access Token
if (!this.Settings.tvdbBearer){
this.Settings.tvdbBearer = await tvdb.login();
}
if ( id ){
const showInfo = await tvdb.getTVDBShowAired( {tvdbId: id, bearer: this.Settings.tvdbBearer} );
for( attributename in showInfo){
this.Settings.showInfo[attributename] = showInfo[attributename];
}
} else {
const title = JSONPath({ path: "$.title", json: data });
log.error(`[ethelper.js] (addRowToTmp) - No tmdb guid found for ${title}`);
}
this.Settings.showInfo["showOrdering"] = "TVDB Airing";
break;
case "dvd":
// Special level, so we need to get info from tvdb
log.info(`[ethelper.js] (addRowToTmp) - Level "Find Missing Episodes" selected, so we must contact tvdb for DVD order`);
id = String(JSONPath({ path: "$.Guid[?(@.id.startsWith('tvdb'))].id", json: data })).substring(7,);
// Get TVDB Access Token
if (!this.Settings.tvdbBearer){
this.Settings.tvdbBearer = await tvdb.login();
}
if ( id ){
const showInfo = await tvdb.getTVDBShowDVD( {tvdbId: id, bearer: this.Settings.tvdbBearer} );
for( attributename in showInfo){
this.Settings.showInfo[attributename] = showInfo[attributename];
}
} else {
const title = JSONPath({ path: "$.title", json: data });
log.error(`[ethelper.js] (addRowToTmp) - No tmdb guid found for ${title}`);
}
this.Settings.showInfo["showOrdering"] = "TVDB DVD";
this.Settings.showInfo["Status"] = this.Settings.showInfo["TVDBStatus"];
break;
case "absolute":
// Special level, so we need to get info from tvdb
log.info(`[ethelper.js] (addRowToTmp) - Level "Find Missing Episodes" selected, so we must contact tvdb`);
id = String(JSONPath({ path: "$.Guid[?(@.id.startsWith('tvdb'))].id", json: data })).substring(7,);
// Get TVDB Access Token
if (!this.Settings.tvdbBearer){
this.Settings.tvdbBearer = await tvdb.login();
}
if ( id ){
const showInfo = await tvdb.getTVDBShowAbsolute( {tvdbId: id, bearer: this.Settings.tvdbBearer} );
for( attributename in showInfo){
this.Settings.showInfo[attributename] = showInfo[attributename];
}
} else {
const title = JSONPath({ path: "$.title", json: data });
log.error(`[ethelper.js] (addRowToTmp) - No tmdb guid found for ${title}`);
}
this.Settings.showInfo["showOrdering"] = "TVDB Absolute";
this.Settings.showInfo["Status"] = this.Settings.showInfo["TVDBStatus"];
break;
} }
} }
this.Settings.currentItem +=1; this.Settings.currentItem +=1;
@ -1132,8 +1258,8 @@ const etHelper = new class ETHELPER {
} }
catch (error) catch (error)
{ {
log.error(`We had an exception in ethelper addRowToTmp as ${error}`); log.error(`[ethelper.js] (addRowToTmp) - We had an exception as ${error}`);
log.error(`Fields are name: ${name}, key: ${key}, type: ${type}, subType: ${subType}, subKey: ${subKey}`); log.error(`[ethelper.js] (addRowToTmp) - Fields are name: ${name}, key: ${key}, type: ${type}, subType: ${subType}, subKey: ${subKey}`);
} }
// Remove last internal separator // Remove last internal separator
str = str.substring(0,str.length-etHelper.intSep.length); str = str.substring(0,str.length-etHelper.intSep.length);

View file

@ -42,26 +42,28 @@ const tmdb = new class TMDB {
}) })
.then((response) => { .then((response) => {
log.debug('[tmdb.js] (getTMDBShowInfo) - Response from getTMDBShowInfo recieved'); log.debug('[tmdb.js] (getTMDBShowInfo) - Response from getTMDBShowInfo recieved');
result['TMDBStatus'] = JSONPath({ path: "$.status", json: response.data })[0]; result['Status (Cloud)'] = JSONPath({ path: "$.status", json: response.data })[0];
result['TMDBEPCount'] = JSONPath({ path: "$.number_of_episodes", json: response.data })[0]; result['Episode Count (Cloud)'] = JSONPath({ path: "$.number_of_episodes", json: response.data })[0];
result['TMDBSCount'] = JSONPath({ path: "$.number_of_seasons", json: response.data })[0]; result['Season Count (Cloud)'] = JSONPath({ path: "$.number_of_seasons", json: response.data })[0];
result['seasons'] = {}; // Now get season/episode
const arrSeasons = JSONPath({ path: "$.seasons", json: response.data })[0]; const seasons = JSONPath({ path: "$..seasons[*]", json: response.data })
for (const season of arrSeasons) { let Seasons_Cloud = {};
const season_number = JSONPath({ path: "$.season_number", json: season })[0]; for ( var idx in seasons ){
result['seasons'][season_number] = JSONPath({ path: "$.episode_count", json: season }); Seasons_Cloud[JSONPath({ path: "$..season_number", json: seasons[idx]})] = JSONPath({ path: "$..episode_count", json: seasons[idx]})[0];
} }
result['Seasons (Cloud)'] = Seasons_Cloud;
}) })
.catch(function (error) { .catch(function (error) {
if (error.response) { if (error.response) {
log.error('getTMDBShowInfo: ' + error.response.data); log.error(`[tmdb.js] (getTMDBShowInfo) - Response error: ${error.response.data}`);
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message); alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
} else if (error.request) { } else if (error.request) {
log.error('getTMDBShowInfo: ' + error.request); log.error(`[tmdb.js] (getTMDBShowInfo) - Request Error: ${error.request}`);
} else { } else {
log.error('getTMDBShowInfo: ' + error.message); log.error(`[tmdb.js] (getTMDBShowInfo) - ${error.message}`);
} }
}) })
log.silly(`[tmdb.js] (getTMDBShowInfo) - Returning: ${JSON.stringify(result)}`)
return result; return result;
} }
} }

View file

@ -0,0 +1,199 @@
// TVDB stuff used
//import store from '../../../store';
//import { wtconfig } from './wtutils';
import axios from 'axios';
import { wtutils } from './wtutils';
const log = require('electron-log');
const {JSONPath} = require('jsonpath-plus');
const tvdb = new class TVDB {
constructor() {
this.baseUrl = 'https://thetvdb.com/';
this.baseAPIUrl = 'https://api4.thetvdb.com/v4/';
this.headers = {
"Accept": "application/json"
}
}
async login(){
log.info(`[tvdb.js] (login) - Logging in to theTVDB`);
const apiKey = wtutils.envVarLocal( 'Key_tvdb' );
let payload = { apikey: apiKey };
let url = `${this.baseAPIUrl}login`;
let bearer;
await axios.post( url, payload, {headers: this.headers})
.then((response) => {
log.debug('[tvdb.js] (login) - Response recieved');
bearer = JSONPath({ path: "$..token", json: response })[0];
})
.catch(function (error) {
if (error.response) {
log.error(`[tvdb.js] (login) - Response error: ${error.response.data}`);
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
} else if (error.request) {
log.error(`[tvdb.js] (login) - Request Error: ${error.request}`);
} else {
log.error(`[tvdb.js] (login) - ${error.message}`);
}
})
return bearer;
}
async getTVDBShowAired( {tvdbId: tvdbId, bearer: bearer} ){
log.info(`[tvdb.js] (getTVDBShowAired) - Getting tmdb aired info for ${tvdbId}`);
let url = `${this.baseAPIUrl}series/${tvdbId}/episodes/official?page=0`;
let headers = this.headers;
let seasons = {};
headers["Authorization"] = `Bearer ${bearer}`;
let result = {};
await axios({
method: 'get',
url: url,
headers: headers
})
.then((response) => {
log.debug('[tvdb.js] (getTVDBShowAired) - Response from getTVDBShowAired recieved');
result['Link (Cloud)'] = `https://thetvdb.com/series/${JSONPath({ path: "$..slug", json: response.data })[0]}`;
result['Status (Cloud)'] = JSONPath({ path: "$..status.name", json: response.data })[0];
// Sadly, the tvdb doesn't have a count field for seasons and episodes, so we need to count each :-(
let episodes = JSONPath({ path: "$..episodes[*]", json: response.data });
// Gather season/episode info
for ( var idx in episodes ){
const season = JSONPath({ path: "$..seasonNumber", json: episodes[idx] })[0];
if( Object.prototype.hasOwnProperty.call(seasons, season) ){
seasons[season] = seasons[season] + 1;
} else {
seasons[season] = 1;
}
}
// Get Season Count
result['Season Count (Cloud)'] = Object.keys(seasons).length;
// Get episode count
let episodeCount = 0;
Object.entries(seasons).forEach(([key, value]) => {
episodeCount = episodeCount + parseInt(value);
key;
})
result['Episode Count (Cloud)'] = episodeCount;
result['Seasons (Cloud)'] = seasons;
})
.catch(function (error) {
if (error.response) {
log.error(`[tvdb.js] (getTVDBShowAired) - Response error: ${error.response.data}`);
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
} else if (error.request) {
log.error(`[tvdb.js] (getTVDBShowAired) - Request Error: ${error.request}`);
} else {
log.error(`[tvdb.js] (getTVDBShowAired) - ${error.message}`);
}
})
return result;
}
async getTVDBShowDVD( {tvdbId: tvdbId, bearer: bearer} ){
log.info(`[tvdb.js] (getTVDBShowDVD) - Getting tmdb DVD info for ${tvdbId}`);
let url = `${this.baseAPIUrl}series/${tvdbId}/episodes/dvd?page=0`;
let headers = this.headers;
let seasons = {};
headers["Authorization"] = `Bearer ${bearer}`;
let result = {};
await axios({
method: 'get',
url: url,
headers: headers
})
.then((response) => {
log.debug('[tvdb.js] (getTVDBShowDVD) - Response from getTVDBShowDVD recieved');
result['Link (Cloud)'] = `https://thetvdb.com/series/${JSONPath({ path: "$..slug", json: response.data })[0]}`;
result['Status (Cloud)'] = JSONPath({ path: "$..status.name", json: response.data })[0];
// Sadly, the tvdb doesn't have a count field for seasons and episodes, so we need to count each :-(
let episodes = JSONPath({ path: "$..episodes[*]", json: response.data });
// Gather season/episode info
for ( var idx in episodes ){
const season = JSONPath({ path: "$..seasonNumber", json: episodes[idx] })[0];
if( Object.prototype.hasOwnProperty.call(seasons, season) ){
seasons[season] = seasons[season] + 1;
} else {
seasons[season] = 1;
}
}
// Get Season Count
result['Season Count (Cloud)'] = Object.keys(seasons).length;
// Get episode count
let episodeCount = 0;
Object.entries(seasons).forEach(([key, value]) => {
episodeCount = episodeCount + parseInt(value);
key;
})
result['Episode Count (Cloud)'] = episodeCount;
result['Seasons (Cloud)'] = seasons;
})
.catch(function (error) {
if (error.response) {
log.error(`[tvdb.js] (getTVDBShowDVD) - Response error: ${error.response.data}`);
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
} else if (error.request) {
log.error(`[tvdb.js] (getTVDBShowDVD) - Request Error: ${error.request}`);
} else {
log.error(`[tvdb.js] (getTVDBShowDVD) - ${error.message}`);
}
})
return result;
}
async getTVDBShowAbsolute( {tvdbId: tvdbId, bearer: bearer} ){
log.info(`[tvdb.js] (getTVDBShowAbsolute) - Getting tmdb Absolute info for ${tvdbId}`);
let url = `${this.baseAPIUrl}series/${tvdbId}/episodes/absolute?page=0`;
let headers = this.headers;
let seasons = {};
headers["Authorization"] = `Bearer ${bearer}`;
let result = {};
await axios({
method: 'get',
url: url,
headers: headers
})
.then((response) => {
log.debug('[tvdb.js] (getTVDBShowAbsolute) - Response from getTVDBShowAbsolute recieved');
result['Link (Cloud)'] = `https://thetvdb.com/series/${JSONPath({ path: "$..slug", json: response.data })[0]}`;
result['Status (Cloud)'] = JSONPath({ path: "$..status.name", json: response.data })[0];
// Sadly, the tvdb doesn't have a count field for seasons and episodes, so we need to count each :-(
let episodes = JSONPath({ path: "$..episodes[*]", json: response.data });
// Gather season/episode info
for ( var idx in episodes ){
const season = JSONPath({ path: "$..seasonNumber", json: episodes[idx] })[0];
if( Object.prototype.hasOwnProperty.call(seasons, season) ){
seasons[season] = seasons[season] + 1;
} else {
seasons[season] = 1;
}
}
// Get Season Count
result['Season Count (Cloud)'] = Object.keys(seasons).length;
// Get episode count
let episodeCount = 0;
Object.entries(seasons).forEach(([key, value]) => {
episodeCount = episodeCount + parseInt(value);
key;
})
result['Episode Count (Cloud)'] = episodeCount;
result['Seasons (Cloud)'] = seasons;
})
.catch(function (error) {
if (error.response) {
log.error(`[tvdb.js] (getTVDBShowAbsolute) - Response error: ${error.response.data}`);
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
} else if (error.request) {
log.error(`[tvdb.js] (getTVDBShowAbsolute) - Request Error: ${error.request}`);
} else {
log.error(`[tvdb.js] (getTVDBShowAbsolute) - ${error.message}`);
}
})
return result;
}
}
export { tvdb };