Fix: Linter warnings (#137)
* Automaticly fixable eslint issues, mostly 3 -> 2 space indentation * fix: updated plex_userid to camelcase * Linted and some consistency refactor on middleware * eslint uses ecmaversion 2020 & allow empty catch rule * Started linting source files * Fixed eslint errors & improved a lot of error handling * Set 2 eslint rules as warning temporarly
This commit was merged in pull request #137.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
const Plex = require("../media_classes/plex");
|
||||
|
||||
function translateAdded(date_string) {
|
||||
@@ -5,10 +7,10 @@ function translateAdded(date_string) {
|
||||
}
|
||||
|
||||
function convertPlexToSeasoned(plex) {
|
||||
const title = plex.title;
|
||||
const year = plex.year;
|
||||
const type = plex.type;
|
||||
const summary = plex.summary;
|
||||
const { title } = plex;
|
||||
const { year } = plex;
|
||||
const { type } = plex;
|
||||
const { summary } = plex;
|
||||
const poster_path = plex.thumb;
|
||||
const background_path = plex.art;
|
||||
const added = translateAdded(plex.addedAt);
|
||||
@@ -27,7 +29,6 @@ function convertPlexToSeasoned(plex) {
|
||||
seasons,
|
||||
episodes
|
||||
);
|
||||
// seasoned.print();
|
||||
return seasoned;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
const configuration = require("../config/configuration").getInstance();
|
||||
|
||||
function hookDumpController(req, res) {
|
||||
console.log(req);
|
||||
}
|
||||
|
||||
module.exports = hookDumpController;
|
||||
@@ -1,25 +1,25 @@
|
||||
class mailTemplate {
|
||||
constructor(mediaItem) {
|
||||
this.mediaItem = mediaItem;
|
||||
this.posterURL = 'https://image.tmdb.org/t/p/w600';
|
||||
}
|
||||
constructor(mediaItem) {
|
||||
this.mediaItem = mediaItem;
|
||||
this.posterURL = "https://image.tmdb.org/t/p/w600";
|
||||
}
|
||||
|
||||
toText() {
|
||||
return `${this.mediaItem.title} (${this.mediaItem.year})`; // plain text body
|
||||
}
|
||||
toText() {
|
||||
return `${this.mediaItem.title} (${this.mediaItem.year})`; // plain text body
|
||||
}
|
||||
|
||||
toHTML() {
|
||||
const info = {
|
||||
name: this.mediaItem.title,
|
||||
year: `(${this.mediaItem.year})`,
|
||||
poster: this.posterURL + this.mediaItem.poster,
|
||||
};
|
||||
toHTML() {
|
||||
const info = {
|
||||
name: this.mediaItem.title,
|
||||
year: `(${this.mediaItem.year})`,
|
||||
poster: this.posterURL + this.mediaItem.poster
|
||||
};
|
||||
|
||||
return `
|
||||
return `
|
||||
<h1>${info.name} ${info.year}</h1>
|
||||
<img src="${info.poster}">
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mailTemplate;
|
||||
|
||||
203
src/plex/plex.js
203
src/plex/plex.js
@@ -2,58 +2,101 @@ const fetch = require("node-fetch");
|
||||
const convertPlexToMovie = require("./convertPlexToMovie");
|
||||
const convertPlexToShow = require("./convertPlexToShow");
|
||||
const convertPlexToEpisode = require("./convertPlexToEpisode");
|
||||
|
||||
const { Movie, Show, Person } = require("../tmdb/types");
|
||||
|
||||
const redisCache = require("../cache/redis");
|
||||
|
||||
const sanitize = string => string.toLowerCase().replace(/[^\w]/gi, "");
|
||||
class PlexRequestTimeoutError extends Error {
|
||||
constructor() {
|
||||
const message = "Timeout: Plex did not respond.";
|
||||
|
||||
function fixedEncodeURIComponent(str) {
|
||||
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
|
||||
return "%" + c.charCodeAt(0).toString(16).toUpperCase();
|
||||
});
|
||||
super(message);
|
||||
this.statusCode = 408;
|
||||
}
|
||||
}
|
||||
|
||||
const matchingTitleAndYear = (plex, tmdb) => {
|
||||
let matchingTitle, matchingYear;
|
||||
class PlexUnexpectedError extends Error {
|
||||
constructor(plexError = null) {
|
||||
const message = "Unexpected plex error occured.";
|
||||
|
||||
if (plex["title"] != null && tmdb["title"] != null) {
|
||||
super(message);
|
||||
this.statusCode = 500;
|
||||
this.plexError = plexError;
|
||||
}
|
||||
}
|
||||
|
||||
const sanitize = string => string.toLowerCase().replace(/[^\w]/gi, "");
|
||||
const matchingTitleAndYear = (plex, tmdb) => {
|
||||
let matchingTitle;
|
||||
let matchingYear;
|
||||
|
||||
if (plex?.title && tmdb?.title) {
|
||||
const plexTitle = sanitize(plex.title);
|
||||
const tmdbTitle = sanitize(tmdb.title);
|
||||
matchingTitle = plexTitle == tmdbTitle;
|
||||
matchingTitle = matchingTitle
|
||||
? matchingTitle
|
||||
: plexTitle.startsWith(tmdbTitle);
|
||||
matchingTitle = plexTitle === tmdbTitle;
|
||||
matchingTitle = matchingTitle || plexTitle.startsWith(tmdbTitle);
|
||||
} else matchingTitle = false;
|
||||
|
||||
if (plex["year"] != null && tmdb["year"] != null)
|
||||
matchingYear = plex.year == tmdb.year;
|
||||
if (plex?.year && tmdb?.year) matchingYear = plex.year === tmdb.year;
|
||||
else matchingYear = false;
|
||||
|
||||
return matchingTitle && matchingYear;
|
||||
};
|
||||
|
||||
const successfullResponse = response => {
|
||||
if (response && response["MediaContainer"]) return response;
|
||||
function fixedEncodeURIComponent(str) {
|
||||
return encodeURIComponent(str).replace(/[!'()*]/g, c => {
|
||||
return `%${c.charCodeAt(0).toString(16).toUpperCase()}`;
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
response == null ||
|
||||
response["status"] == null ||
|
||||
response["statusText"] == null
|
||||
) {
|
||||
throw Error("Unable to decode response");
|
||||
}
|
||||
function matchTmdbAndPlexMedia(plex, tmdb) {
|
||||
let match;
|
||||
|
||||
const { status, statusText } = response;
|
||||
if (plex === null || tmdb === null) return false;
|
||||
|
||||
if (status === 200) {
|
||||
return response.json();
|
||||
if (plex instanceof Array) {
|
||||
const possibleMatches = plex.map(plexItem =>
|
||||
matchingTitleAndYear(plexItem, tmdb)
|
||||
);
|
||||
match = possibleMatches.includes(true);
|
||||
} else {
|
||||
throw { message: statusText, status: status };
|
||||
match = matchingTitleAndYear(plex, tmdb);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
const successfullResponse = response => {
|
||||
const { status, statusText } = response;
|
||||
if (status !== 200) {
|
||||
throw new PlexUnexpectedError(statusText);
|
||||
}
|
||||
|
||||
if (response?.MediaContainer) return response;
|
||||
|
||||
return response.json();
|
||||
};
|
||||
|
||||
function mapResults(response) {
|
||||
if (response?.MediaContainer?.Hub === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return response.MediaContainer.Hub.filter(category => category.size > 0)
|
||||
.map(category => {
|
||||
if (category.type === "movie") {
|
||||
return category.Metadata.map(convertPlexToMovie);
|
||||
}
|
||||
if (category.type === "show") {
|
||||
return category.Metadata.map(convertPlexToShow);
|
||||
}
|
||||
if (category.type === "episode") {
|
||||
return category.Metadata.map(convertPlexToEpisode);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.filter(result => result !== null);
|
||||
}
|
||||
|
||||
class Plex {
|
||||
constructor(ip, port = 32400, cache = null) {
|
||||
this.plexIP = ip;
|
||||
@@ -77,50 +120,29 @@ class Plex {
|
||||
return new Promise((resolve, reject) =>
|
||||
this.cache
|
||||
.get(cacheKey)
|
||||
.then(machineInfo => resolve(machineInfo["machineIdentifier"]))
|
||||
.then(machineInfo => resolve(machineInfo?.machineIdentifier))
|
||||
.catch(() => fetch(url, options))
|
||||
.then(response => response.json())
|
||||
.then(machineInfo =>
|
||||
this.cache.set(cacheKey, machineInfo["MediaContainer"], 2628000)
|
||||
this.cache.set(cacheKey, machineInfo.MediaContainer, 2628000)
|
||||
)
|
||||
.then(machineInfo => resolve(machineInfo["machineIdentifier"]))
|
||||
.then(machineInfo => resolve(machineInfo?.machineIdentifier))
|
||||
.catch(error => {
|
||||
if (error != undefined && error.type === "request-timeout") {
|
||||
reject({
|
||||
message: "Plex did not respond",
|
||||
status: 408,
|
||||
success: false
|
||||
});
|
||||
if (error?.type === "request-timeout") {
|
||||
reject(new PlexRequestTimeoutError());
|
||||
}
|
||||
|
||||
reject(error);
|
||||
reject(new PlexUnexpectedError());
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
matchTmdbAndPlexMedia(plex, tmdb) {
|
||||
let match;
|
||||
|
||||
if (plex == null || tmdb == null) return false;
|
||||
|
||||
if (plex instanceof Array) {
|
||||
let possibleMatches = plex.map(plexItem =>
|
||||
matchingTitleAndYear(plexItem, tmdb)
|
||||
);
|
||||
match = possibleMatches.includes(true);
|
||||
} else {
|
||||
match = matchingTitleAndYear(plex, tmdb);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
async existsInPlex(tmdb) {
|
||||
const plexMatch = await this.findPlexItemByTitleAndYear(
|
||||
tmdb.title,
|
||||
tmdb.year
|
||||
);
|
||||
return plexMatch ? true : false;
|
||||
return !!plexMatch;
|
||||
}
|
||||
|
||||
findPlexItemByTitleAndYear(title, year) {
|
||||
@@ -128,10 +150,10 @@ class Plex {
|
||||
|
||||
return this.search(title).then(plexResults => {
|
||||
const matchesInPlex = plexResults.map(plex =>
|
||||
this.matchTmdbAndPlexMedia(plex, query)
|
||||
matchTmdbAndPlexMedia(plex, query)
|
||||
);
|
||||
const matchesIndex = matchesInPlex.findIndex(el => el === true);
|
||||
return matchesInPlex != -1 ? plexResults[matchesIndex] : null;
|
||||
return matchesInPlex !== -1 ? plexResults[matchesIndex] : null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -147,10 +169,10 @@ class Plex {
|
||||
matchingObjectInPlexPromise
|
||||
]).then(([machineIdentifier, matchingObjectInPlex]) => {
|
||||
if (
|
||||
matchingObjectInPlex == false ||
|
||||
matchingObjectInPlex == null ||
|
||||
matchingObjectInPlex["key"] == null ||
|
||||
machineIdentifier == null
|
||||
matchingObjectInPlex === false ||
|
||||
matchingObjectInPlex === null ||
|
||||
matchingObjectInPlex.key === null ||
|
||||
machineIdentifier === null
|
||||
)
|
||||
return false;
|
||||
|
||||
@@ -176,18 +198,14 @@ class Plex {
|
||||
.catch(() => fetch(url, options)) // else fetch fresh data
|
||||
.then(successfullResponse)
|
||||
.then(results => this.cache.set(cacheKey, results, 21600)) // 6 hours
|
||||
.then(this.mapResults)
|
||||
.then(mapResults)
|
||||
.then(resolve)
|
||||
.catch(error => {
|
||||
if (error != undefined && error.type === "request-timeout") {
|
||||
reject({
|
||||
message: "Plex did not respond",
|
||||
status: 408,
|
||||
success: false
|
||||
});
|
||||
if (error?.type === "request-timeout") {
|
||||
reject(new PlexRequestTimeoutError());
|
||||
}
|
||||
|
||||
reject(error);
|
||||
reject(new PlexUnexpectedError());
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -200,40 +218,13 @@ class Plex {
|
||||
const query = title;
|
||||
const cacheKey = `${this.cacheTags.search}/${query}*`;
|
||||
|
||||
this.cache.del(
|
||||
cacheKey,
|
||||
(error,
|
||||
response => {
|
||||
if (response == 1) return true;
|
||||
|
||||
// TODO improve cache key matching by lowercasing it on the backend.
|
||||
// what do we actually need to check for if the key was deleted or not
|
||||
// it might be an error or another response code.
|
||||
console.log("Unable to delete, key might not exists");
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
mapResults(response) {
|
||||
if (
|
||||
response == null ||
|
||||
response.MediaContainer == null ||
|
||||
response.MediaContainer.Hub == null
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return response.MediaContainer.Hub.filter(category => category.size > 0)
|
||||
.map(category => {
|
||||
if (category.type === "movie") {
|
||||
return category.Metadata;
|
||||
} else if (category.type === "show") {
|
||||
return category.Metadata.map(convertPlexToShow);
|
||||
} else if (category.type === "episode") {
|
||||
return category.Metadata.map(convertPlexToEpisode);
|
||||
}
|
||||
})
|
||||
.filter(result => result !== undefined);
|
||||
this.cache.del(cacheKey, (error, response) => {
|
||||
// TODO improve cache key matching by lowercasing it on the backend.
|
||||
// what do we actually need to check for if the key was deleted or not
|
||||
// it might be an error or another response code.
|
||||
console.log("Unable to delete, key might not exists");
|
||||
return response === 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,55 @@
|
||||
const rp = require("request-promise");
|
||||
const convertPlexToSeasoned = require("./convertPlexToSeasoned");
|
||||
const convertPlexToStream = require("./convertPlexToStream");
|
||||
const rp = require("request-promise");
|
||||
|
||||
// eslint-disable-next-line
|
||||
function addAttributeIfTmdbInPlex(_tmdb, plexResult) {
|
||||
const tmdb = { ..._tmdb };
|
||||
|
||||
if (plexResult?.results?.length > 0) {
|
||||
plexResult.results.map(plexItem => {
|
||||
tmdb.matchedInPlex =
|
||||
tmdb.title === plexItem.title && tmdb.year === plexItem.year;
|
||||
return tmdb;
|
||||
});
|
||||
} else {
|
||||
tmdb.matchedInPlex = false;
|
||||
}
|
||||
|
||||
return Promise.resolve(tmdb);
|
||||
}
|
||||
|
||||
function mapResults(response) {
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
if (!response?.MediaContainer?.Metadata) return [[], 0];
|
||||
|
||||
const mappedResults = response.MediaContainer.Metadata.filter(element => {
|
||||
return element.type === "movie" || element.type === "show";
|
||||
}).map(element => convertPlexToSeasoned(element));
|
||||
return [mappedResults, mappedResults.length];
|
||||
})
|
||||
.catch(error => {
|
||||
throw new Error(error);
|
||||
});
|
||||
}
|
||||
|
||||
class PlexRepository {
|
||||
constructor(plexIP) {
|
||||
this.plexIP = plexIP;
|
||||
}
|
||||
|
||||
inPlex(tmdbResult) {
|
||||
return Promise.resolve()
|
||||
.then(() => this.search(tmdbResult.title))
|
||||
.then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult))
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
inPlex(_tmdbResult) {
|
||||
const tmdbResult = { ..._tmdbResult };
|
||||
this.search(tmdbResult.title)
|
||||
.then(plexResult => addAttributeIfTmdbInPlex(tmdbResult, plexResult))
|
||||
.catch(() => {
|
||||
/**
|
||||
* If something crashes with search from this function it probably
|
||||
* fine to set the `matchedInPlex` attribute to false and return
|
||||
* original tmdb object
|
||||
* */
|
||||
|
||||
tmdbResult.matchedInPlex = false;
|
||||
return tmdbResult;
|
||||
});
|
||||
@@ -24,7 +61,7 @@ class PlexRepository {
|
||||
`http://${this.plexIP}:32400/search?query=${queryUri}`
|
||||
);
|
||||
const options = {
|
||||
uri: uri,
|
||||
uri,
|
||||
headers: {
|
||||
Accept: "application/json"
|
||||
},
|
||||
@@ -32,50 +69,13 @@ class PlexRepository {
|
||||
};
|
||||
|
||||
return rp(options)
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
throw new Error("Unable to search plex.");
|
||||
})
|
||||
.then(result => this.mapResults(result))
|
||||
.then(result => mapResults(result))
|
||||
.then(([mappedResults, resultCount]) => ({
|
||||
results: mappedResults,
|
||||
total_results: resultCount
|
||||
}));
|
||||
}
|
||||
|
||||
compareTmdbToPlex(tmdb, plexResult) {
|
||||
return Promise.resolve().then(() => {
|
||||
if (plexResult.results.length === 0) {
|
||||
tmdb.matchedInPlex = false;
|
||||
} else {
|
||||
// console.log('plex and tmdb:', plexResult, '\n', tmdb)
|
||||
plexResult.results.map(plexItem => {
|
||||
if (tmdb.title === plexItem.title && tmdb.year === plexItem.year)
|
||||
tmdb.matchedInPlex = true;
|
||||
return tmdb;
|
||||
});
|
||||
}
|
||||
return tmdb;
|
||||
});
|
||||
}
|
||||
|
||||
mapResults(response) {
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
if (!response.MediaContainer.hasOwnProperty("Metadata")) return [[], 0];
|
||||
|
||||
const mappedResults = response.MediaContainer.Metadata.filter(
|
||||
element => {
|
||||
return element.type === "movie" || element.type === "show";
|
||||
}
|
||||
).map(element => convertPlexToSeasoned(element));
|
||||
return [mappedResults, mappedResults.length];
|
||||
})
|
||||
.catch(error => {
|
||||
throw new Error(error);
|
||||
});
|
||||
}
|
||||
|
||||
nowPlaying() {
|
||||
const options = {
|
||||
uri: `http://${this.plexIP}:32400/status/sessions`,
|
||||
|
||||
@@ -28,15 +28,15 @@ class RequestRepository {
|
||||
};
|
||||
}
|
||||
|
||||
search(query, type, page) {
|
||||
return Promise.resolve()
|
||||
.then(() => tmdb.search(query, type, page))
|
||||
static search(query, type, page) {
|
||||
return tmdb
|
||||
.search(query, type, page)
|
||||
.catch(error => Error(`error in the house${error}`));
|
||||
}
|
||||
|
||||
lookup(identifier, type = "movie") {
|
||||
return Promise.resolve()
|
||||
.then(() => tmdb.lookup(identifier, type))
|
||||
return tmdb
|
||||
.lookup(identifier, type)
|
||||
.then(tmdbMovie => this.checkID(tmdbMovie))
|
||||
.then(tmdbMovie => plexRepository.inPlex(tmdbMovie))
|
||||
.catch(error => {
|
||||
@@ -44,19 +44,17 @@ class RequestRepository {
|
||||
});
|
||||
}
|
||||
|
||||
checkID(tmdbMovie) {
|
||||
return Promise.resolve()
|
||||
.then(() =>
|
||||
this.database.get(this.queries.checkIfIdRequested, [
|
||||
tmdbMovie.id,
|
||||
tmdbMovie.type
|
||||
])
|
||||
)
|
||||
checkID(_tmdbMovie) {
|
||||
const tmdbMovie = _tmdbMovie;
|
||||
|
||||
return this.database
|
||||
.get(this.queries.checkIfIdRequested, [tmdbMovie.id, tmdbMovie.type])
|
||||
.then((result, error) => {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
tmdbMovie.requested = result ? true : false;
|
||||
|
||||
tmdbMovie.requested = !!result;
|
||||
return tmdbMovie;
|
||||
});
|
||||
}
|
||||
@@ -66,45 +64,42 @@ class RequestRepository {
|
||||
* @param {identifier, type} the id of the media object and type of media must be defined
|
||||
* @returns {Promise} If nothing has gone wrong.
|
||||
*/
|
||||
sendRequest(identifier, type, ip, user_agent, user) {
|
||||
return Promise.resolve()
|
||||
.then(() => tmdb.lookup(identifier, type))
|
||||
.then(movie => {
|
||||
const username = user === undefined ? undefined : user.username;
|
||||
// Add request to database
|
||||
return this.database.run(this.queries.insertRequest, [
|
||||
movie.id,
|
||||
movie.title,
|
||||
movie.year,
|
||||
movie.poster_path,
|
||||
movie.background_path,
|
||||
username,
|
||||
ip,
|
||||
user_agent,
|
||||
movie.type
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
fetchRequested(status, page = "1", type = "%") {
|
||||
return Promise.resolve().then(() => {
|
||||
if (
|
||||
status === "requested" ||
|
||||
status === "downloading" ||
|
||||
status === "downloaded"
|
||||
)
|
||||
return this.database.all(this.queries.fetchRequestedItemsByStatus, [
|
||||
status,
|
||||
type,
|
||||
page
|
||||
]);
|
||||
else return this.database.all(this.queries.fetchRequestedItems, page);
|
||||
sendRequest(identifier, type, ip, userAgent, user) {
|
||||
return tmdb.lookup(identifier, type).then(movie => {
|
||||
const username = user === undefined ? undefined : user.username;
|
||||
// Add request to database
|
||||
return this.database.run(this.queries.insertRequest, [
|
||||
movie.id,
|
||||
movie.title,
|
||||
movie.year,
|
||||
movie.poster_path,
|
||||
movie.background_path,
|
||||
username,
|
||||
ip,
|
||||
userAgent,
|
||||
movie.type
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
fetchRequested(status, page = "1", type = "%") {
|
||||
if (
|
||||
status === "requested" ||
|
||||
status === "downloading" ||
|
||||
status === "downloaded"
|
||||
)
|
||||
return this.database.all(this.queries.fetchRequestedItemsByStatus, [
|
||||
status,
|
||||
type,
|
||||
page
|
||||
]);
|
||||
|
||||
return this.database.all(this.queries.fetchRequestedItems, page);
|
||||
}
|
||||
|
||||
userRequests(username) {
|
||||
return Promise.resolve()
|
||||
.then(() => this.database.all(this.queries.userRequests, username))
|
||||
return this.database
|
||||
.all(this.queries.userRequests, username)
|
||||
.catch(error => {
|
||||
if (String(error).includes("no such column")) {
|
||||
throw new Error("Username not found");
|
||||
@@ -113,8 +108,11 @@ class RequestRepository {
|
||||
})
|
||||
.then(result => {
|
||||
// TODO do a correct mapping before sending, not just a dump of the database
|
||||
result.map(item => (item.poster = item.poster_path));
|
||||
return result;
|
||||
return result.map(_item => {
|
||||
const item = { ..._item };
|
||||
item.poster = item.poster_path;
|
||||
return item;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
class convertStreamToPlayback {
|
||||
constructor(plexStream) {
|
||||
this.bitrate = plexStream.bitrate;
|
||||
this.width = plexStream.width;
|
||||
this.height = plexStream.height;
|
||||
this.decision = plexStream.decision;
|
||||
this.audioProfile = plexStream.audioProfile;
|
||||
this.videoProfile = plexStream.videoProfile;
|
||||
this.duration = plexStream.duration;
|
||||
this.container = plexStream.container;
|
||||
}
|
||||
constructor(plexStream) {
|
||||
this.bitrate = plexStream.bitrate;
|
||||
this.width = plexStream.width;
|
||||
this.height = plexStream.height;
|
||||
this.decision = plexStream.decision;
|
||||
this.audioProfile = plexStream.audioProfile;
|
||||
this.videoProfile = plexStream.videoProfile;
|
||||
this.duration = plexStream.duration;
|
||||
this.container = plexStream.container;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = convertStreamToPlayback;
|
||||
|
||||
@@ -8,9 +8,9 @@ class Episode {
|
||||
this.summary = null;
|
||||
this.rating = null;
|
||||
this.views = null;
|
||||
this.aired = null;
|
||||
this.type = 'episode';
|
||||
this.aired = null;
|
||||
this.type = "episode";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Episode;
|
||||
module.exports = Episode;
|
||||
|
||||
@@ -5,8 +5,8 @@ class Movie {
|
||||
this.summary = null;
|
||||
this.rating = null;
|
||||
this.tagline = null;
|
||||
this.type = 'movie';
|
||||
this.type = "movie";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Movie;
|
||||
module.exports = Movie;
|
||||
|
||||
@@ -9,4 +9,4 @@ class Show {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Show;
|
||||
module.exports = Show;
|
||||
|
||||
Reference in New Issue
Block a user