Moved contents of seasoned_api up to root folder
This commit is contained in:
24
src/plex/convertPlexToEpisode.js
Normal file
24
src/plex/convertPlexToEpisode.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const Episode = require("./types/episode");
|
||||
|
||||
function convertPlexToEpisode(plexEpisode) {
|
||||
const episode = new Episode(
|
||||
plexEpisode.title,
|
||||
plexEpisode.grandparentTitle,
|
||||
plexEpisode.year
|
||||
);
|
||||
episode.season = plexEpisode.parentIndex;
|
||||
episode.episode = plexEpisode.index;
|
||||
episode.summary = plexEpisode.summary;
|
||||
episode.rating = plexEpisode.rating;
|
||||
|
||||
if (plexEpisode.viewCount !== undefined) {
|
||||
episode.views = plexEpisode.viewCount;
|
||||
}
|
||||
|
||||
if (plexEpisode.originallyAvailableAt !== undefined) {
|
||||
episode.airdate = new Date(plexEpisode.originallyAvailableAt);
|
||||
}
|
||||
|
||||
return episode;
|
||||
}
|
||||
module.exports = convertPlexToEpisode;
|
||||
15
src/plex/convertPlexToMovie.js
Normal file
15
src/plex/convertPlexToMovie.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const Movie = require("./types/movie");
|
||||
|
||||
function convertPlexToMovie(plexMovie) {
|
||||
const movie = new Movie(plexMovie.title, plexMovie.year);
|
||||
movie.rating = plexMovie.rating;
|
||||
movie.tagline = plexMovie.tagline;
|
||||
|
||||
if (plexMovie.summary !== undefined) {
|
||||
movie.summary = plexMovie.summary;
|
||||
}
|
||||
|
||||
return movie;
|
||||
}
|
||||
|
||||
module.exports = convertPlexToMovie;
|
||||
34
src/plex/convertPlexToSeasoned.js
Normal file
34
src/plex/convertPlexToSeasoned.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const Plex = require("../media_classes/plex");
|
||||
|
||||
function translateAdded(date_string) {
|
||||
return new Date(date_string * 1000);
|
||||
}
|
||||
|
||||
function convertPlexToSeasoned(plex) {
|
||||
const title = plex.title;
|
||||
const year = plex.year;
|
||||
const type = plex.type;
|
||||
const summary = plex.summary;
|
||||
const poster_path = plex.thumb;
|
||||
const background_path = plex.art;
|
||||
const added = translateAdded(plex.addedAt);
|
||||
// const genre = plex.genre;
|
||||
const seasons = plex.childCount;
|
||||
const episodes = plex.leafCount;
|
||||
|
||||
const seasoned = new Plex(
|
||||
title,
|
||||
year,
|
||||
type,
|
||||
summary,
|
||||
poster_path,
|
||||
background_path,
|
||||
added,
|
||||
seasons,
|
||||
episodes
|
||||
);
|
||||
// seasoned.print();
|
||||
return seasoned;
|
||||
}
|
||||
|
||||
module.exports = convertPlexToSeasoned;
|
||||
13
src/plex/convertPlexToShow.js
Normal file
13
src/plex/convertPlexToShow.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const Show = require("./types/show");
|
||||
|
||||
function convertPlexToShow(plexShow) {
|
||||
const show = new Show(plexShow.title, plexShow.year);
|
||||
show.summary = plexShow.summary;
|
||||
show.rating = plexShow.rating;
|
||||
show.seasons = plexShow.childCount;
|
||||
show.episodes = plexShow.leafCount;
|
||||
|
||||
return show;
|
||||
}
|
||||
|
||||
module.exports = convertPlexToShow;
|
||||
19
src/plex/convertPlexToStream.js
Normal file
19
src/plex/convertPlexToStream.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const convertPlexToSeasoned = require("./convertPlexToSeasoned");
|
||||
const convertStreamToMediaInfo = require("./convertStreamToMediaInfo");
|
||||
const convertStreamToPlayer = require("./stream/convertStreamToPlayer");
|
||||
const convertStreamToUser = require("./stream/convertStreamToUser");
|
||||
const ConvertStreamToPlayback = require("./stream/convertStreamToPlayback");
|
||||
|
||||
function convertPlexToStream(plexStream) {
|
||||
const stream = convertPlexToSeasoned(plexStream);
|
||||
const plexStreamMedia = plexStream.Media[0];
|
||||
stream.mediaInfo = convertStreamToMediaInfo(plexStreamMedia);
|
||||
stream.player = convertStreamToPlayer(plexStream.Player);
|
||||
|
||||
stream.user = convertStreamToUser(plexStream.User);
|
||||
stream.playback = new ConvertStreamToPlayback(plexStreamMedia.Part[0]);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
module.exports = convertPlexToStream;
|
||||
22
src/plex/convertStreamToMediaInfo.js
Normal file
22
src/plex/convertStreamToMediaInfo.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const MediaInfo = require("../media_classes/mediaInfo");
|
||||
|
||||
function convertStreamToMediaInfo(plexStream) {
|
||||
const mediaInfo = new MediaInfo();
|
||||
|
||||
mediaInfo.duration = plexStream.duration;
|
||||
mediaInfo.height = plexStream.height;
|
||||
mediaInfo.width = plexStream.width;
|
||||
|
||||
if (plexStream.bitrate) {
|
||||
mediaInfo.bitrate = plexStream.bitrate;
|
||||
}
|
||||
mediaInfo.resolution = plexStream.videoResolution;
|
||||
mediaInfo.framerate = plexStream.videoFrameRate;
|
||||
mediaInfo.protocol = plexStream.protocol;
|
||||
mediaInfo.container = plexStream.container;
|
||||
mediaInfo.audioCodec = plexStream.audioCodec;
|
||||
|
||||
return mediaInfo;
|
||||
}
|
||||
|
||||
module.exports = convertStreamToMediaInfo;
|
||||
7
src/plex/hookDump.js
Normal file
7
src/plex/hookDump.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const configuration = require("../config/configuration").getInstance();
|
||||
|
||||
function hookDumpController(req, res) {
|
||||
console.log(req);
|
||||
}
|
||||
|
||||
module.exports = hookDumpController;
|
||||
25
src/plex/mailTemplate.js
Normal file
25
src/plex/mailTemplate.js
Normal file
@@ -0,0 +1,25 @@
|
||||
class mailTemplate {
|
||||
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
|
||||
}
|
||||
|
||||
toHTML() {
|
||||
const info = {
|
||||
name: this.mediaItem.title,
|
||||
year: `(${this.mediaItem.year})`,
|
||||
poster: this.posterURL + this.mediaItem.poster,
|
||||
};
|
||||
|
||||
return `
|
||||
<h1>${info.name} ${info.year}</h1>
|
||||
<img src="${info.poster}">
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mailTemplate;
|
||||
240
src/plex/plex.js
Normal file
240
src/plex/plex.js
Normal file
@@ -0,0 +1,240 @@
|
||||
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, "");
|
||||
|
||||
function fixedEncodeURIComponent(str) {
|
||||
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
|
||||
return "%" + c.charCodeAt(0).toString(16).toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
const matchingTitleAndYear = (plex, tmdb) => {
|
||||
let matchingTitle, matchingYear;
|
||||
|
||||
if (plex["title"] != null && tmdb["title"] != null) {
|
||||
const plexTitle = sanitize(plex.title);
|
||||
const tmdbTitle = sanitize(tmdb.title);
|
||||
matchingTitle = plexTitle == tmdbTitle;
|
||||
matchingTitle = matchingTitle
|
||||
? matchingTitle
|
||||
: plexTitle.startsWith(tmdbTitle);
|
||||
} else matchingTitle = false;
|
||||
|
||||
if (plex["year"] != null && tmdb["year"] != null)
|
||||
matchingYear = plex.year == tmdb.year;
|
||||
else matchingYear = false;
|
||||
|
||||
return matchingTitle && matchingYear;
|
||||
};
|
||||
|
||||
const successfullResponse = response => {
|
||||
if (response && response["MediaContainer"]) return response;
|
||||
|
||||
if (
|
||||
response == null ||
|
||||
response["status"] == null ||
|
||||
response["statusText"] == null
|
||||
) {
|
||||
throw Error("Unable to decode response");
|
||||
}
|
||||
|
||||
const { status, statusText } = response;
|
||||
|
||||
if (status === 200) {
|
||||
return response.json();
|
||||
} else {
|
||||
throw { message: statusText, status: status };
|
||||
}
|
||||
};
|
||||
|
||||
class Plex {
|
||||
constructor(ip, port = 32400, cache = null) {
|
||||
this.plexIP = ip;
|
||||
this.plexPort = port;
|
||||
|
||||
this.cache = cache || redisCache;
|
||||
this.cacheTags = {
|
||||
machineInfo: "plex/mi",
|
||||
search: "plex/s"
|
||||
};
|
||||
}
|
||||
|
||||
fetchMachineIdentifier() {
|
||||
const cacheKey = `${this.cacheTags.machineInfo}`;
|
||||
const url = `http://${this.plexIP}:${this.plexPort}/`;
|
||||
const options = {
|
||||
timeout: 20000,
|
||||
headers: { Accept: "application/json" }
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.cache
|
||||
.get(cacheKey)
|
||||
.then(machineInfo => resolve(machineInfo["machineIdentifier"]))
|
||||
.catch(() => fetch(url, options))
|
||||
.then(response => response.json())
|
||||
.then(machineInfo =>
|
||||
this.cache.set(cacheKey, machineInfo["MediaContainer"], 2628000)
|
||||
)
|
||||
.then(machineInfo => resolve(machineInfo["machineIdentifier"]))
|
||||
.catch(error => {
|
||||
if (error != undefined && error.type === "request-timeout") {
|
||||
reject({
|
||||
message: "Plex did not respond",
|
||||
status: 408,
|
||||
success: false
|
||||
});
|
||||
}
|
||||
|
||||
reject(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
findPlexItemByTitleAndYear(title, year) {
|
||||
const query = { title, year };
|
||||
|
||||
return this.search(title).then(plexResults => {
|
||||
const matchesInPlex = plexResults.map(plex =>
|
||||
this.matchTmdbAndPlexMedia(plex, query)
|
||||
);
|
||||
const matchesIndex = matchesInPlex.findIndex(el => el === true);
|
||||
return matchesInPlex != -1 ? plexResults[matchesIndex] : null;
|
||||
});
|
||||
}
|
||||
|
||||
getDirectLinkByTitleAndYear(title, year) {
|
||||
const machineIdentifierPromise = this.fetchMachineIdentifier();
|
||||
const matchingObjectInPlexPromise = this.findPlexItemByTitleAndYear(
|
||||
title,
|
||||
year
|
||||
);
|
||||
|
||||
return Promise.all([
|
||||
machineIdentifierPromise,
|
||||
matchingObjectInPlexPromise
|
||||
]).then(([machineIdentifier, matchingObjectInPlex]) => {
|
||||
if (
|
||||
matchingObjectInPlex == false ||
|
||||
matchingObjectInPlex == null ||
|
||||
matchingObjectInPlex["key"] == null ||
|
||||
machineIdentifier == null
|
||||
)
|
||||
return false;
|
||||
|
||||
const keyUriComponent = fixedEncodeURIComponent(matchingObjectInPlex.key);
|
||||
return `https://app.plex.tv/desktop#!/server/${machineIdentifier}/details?key=${keyUriComponent}`;
|
||||
});
|
||||
}
|
||||
|
||||
search(query) {
|
||||
const cacheKey = `${this.cacheTags.search}:${query}`;
|
||||
|
||||
const url = `http://${this.plexIP}:${
|
||||
this.plexPort
|
||||
}/hubs/search?query=${fixedEncodeURIComponent(query)}`;
|
||||
const options = {
|
||||
timeout: 20000,
|
||||
headers: { Accept: "application/json" }
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.cache
|
||||
.get(cacheKey)
|
||||
.catch(() => fetch(url, options)) // else fetch fresh data
|
||||
.then(successfullResponse)
|
||||
.then(results => this.cache.set(cacheKey, results, 21600)) // 6 hours
|
||||
.then(this.mapResults)
|
||||
.then(resolve)
|
||||
.catch(error => {
|
||||
if (error != undefined && error.type === "request-timeout") {
|
||||
reject({
|
||||
message: "Plex did not respond",
|
||||
status: 408,
|
||||
success: false
|
||||
});
|
||||
}
|
||||
|
||||
reject(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// this is not guarenteed to work, but if we see a movie or
|
||||
// show has been imported, this function can be helpfull to call
|
||||
// in order to try bust the cache preventing movieInfo and
|
||||
// showInfo from seeing updates through existsInPlex.
|
||||
bustSearchCacheWithTitle(title) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Plex;
|
||||
110
src/plex/plexRepository.js
Normal file
110
src/plex/plexRepository.js
Normal file
@@ -0,0 +1,110 @@
|
||||
const convertPlexToSeasoned = require("./convertPlexToSeasoned");
|
||||
const convertPlexToStream = require("./convertPlexToStream");
|
||||
const rp = require("request-promise");
|
||||
|
||||
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);
|
||||
tmdbResult.matchedInPlex = false;
|
||||
return tmdbResult;
|
||||
});
|
||||
}
|
||||
|
||||
search(query) {
|
||||
const queryUri = encodeURIComponent(query);
|
||||
const uri = encodeURI(
|
||||
`http://${this.plexIP}:32400/search?query=${queryUri}`
|
||||
);
|
||||
const options = {
|
||||
uri: uri,
|
||||
headers: {
|
||||
Accept: "application/json"
|
||||
},
|
||||
json: true
|
||||
};
|
||||
|
||||
return rp(options)
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
throw new Error("Unable to search plex.");
|
||||
})
|
||||
.then(result => this.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`,
|
||||
headers: {
|
||||
Accept: "application/json"
|
||||
},
|
||||
json: true
|
||||
};
|
||||
|
||||
return rp(options)
|
||||
.then(result => {
|
||||
if (result.MediaContainer.size > 0) {
|
||||
const playing =
|
||||
result.MediaContainer.Metadata.map(convertPlexToStream);
|
||||
return { size: Object.keys(playing).length, video: playing };
|
||||
}
|
||||
return { size: 0, video: [] };
|
||||
})
|
||||
.catch(err => {
|
||||
throw new Error(`Error handling plex playing. Error: ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
// multipleInPlex(tmdbResults) {
|
||||
// const results = tmdbResults.results.map(async (tmdb) => {
|
||||
// return this.inPlex(tmdb)
|
||||
// })
|
||||
// return Promise.all(results)
|
||||
// }
|
||||
}
|
||||
|
||||
module.exports = PlexRepository;
|
||||
130
src/plex/requestRepository.js
Normal file
130
src/plex/requestRepository.js
Normal file
@@ -0,0 +1,130 @@
|
||||
const PlexRepository = require("./plexRepository");
|
||||
const configuration = require("../config/configuration").getInstance();
|
||||
const TMDB = require("../tmdb/tmdb");
|
||||
const establishedDatabase = require("../database/database");
|
||||
|
||||
const plexRepository = new PlexRepository(configuration.get("plex", "ip"));
|
||||
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
|
||||
|
||||
class RequestRepository {
|
||||
constructor(database) {
|
||||
this.database = database || establishedDatabase;
|
||||
this.queries = {
|
||||
insertRequest: `INSERT INTO requests(id,title,year,poster_path,background_path,requested_by,ip,user_agent,type)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
fetchRequestedItems:
|
||||
"SELECT * FROM requests ORDER BY date DESC LIMIT 25 OFFSET ?*25-25",
|
||||
fetchRequestedItemsByStatus:
|
||||
"SELECT * FROM requests WHERE status IS ? AND type LIKE ? ORDER BY date DESC LIMIT 25 OFFSET ?*25-25",
|
||||
updateRequestedById:
|
||||
"UPDATE requests SET status = ? WHERE id is ? AND type is ?",
|
||||
checkIfIdRequested: "SELECT * FROM requests WHERE id IS ? AND type IS ?",
|
||||
userRequests:
|
||||
"SELECT * FROM requests WHERE requested_by IS ? ORDER BY date DESC"
|
||||
};
|
||||
this.cacheTags = {
|
||||
search: "se",
|
||||
lookup: "i"
|
||||
};
|
||||
}
|
||||
|
||||
search(query, type, page) {
|
||||
return Promise.resolve()
|
||||
.then(() => 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))
|
||||
.then(tmdbMovie => this.checkID(tmdbMovie))
|
||||
.then(tmdbMovie => plexRepository.inPlex(tmdbMovie))
|
||||
.catch(error => {
|
||||
throw new Error(error);
|
||||
});
|
||||
}
|
||||
|
||||
checkID(tmdbMovie) {
|
||||
return Promise.resolve()
|
||||
.then(() =>
|
||||
this.database.get(this.queries.checkIfIdRequested, [
|
||||
tmdbMovie.id,
|
||||
tmdbMovie.type
|
||||
])
|
||||
)
|
||||
.then((result, error) => {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
tmdbMovie.requested = result ? true : false;
|
||||
return tmdbMovie;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send request for given media id.
|
||||
* @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);
|
||||
});
|
||||
}
|
||||
|
||||
userRequests(username) {
|
||||
return Promise.resolve()
|
||||
.then(() => this.database.all(this.queries.userRequests, username))
|
||||
.catch(error => {
|
||||
if (String(error).includes("no such column")) {
|
||||
throw new Error("Username not found");
|
||||
}
|
||||
throw new Error("Unable to fetch your requests");
|
||||
})
|
||||
.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;
|
||||
});
|
||||
}
|
||||
|
||||
updateRequestedById(id, type, status) {
|
||||
return this.database.run(this.queries.updateRequestedById, [
|
||||
status,
|
||||
id,
|
||||
type
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RequestRepository;
|
||||
14
src/plex/stream/convertStreamToPlayback.js
Normal file
14
src/plex/stream/convertStreamToPlayback.js
Normal file
@@ -0,0 +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;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = convertStreamToPlayback;
|
||||
13
src/plex/stream/convertStreamToPlayer.js
Normal file
13
src/plex/stream/convertStreamToPlayer.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const Player = require("../../media_classes/player");
|
||||
|
||||
function convertStreamToPlayer(plexStream) {
|
||||
const player = new Player(plexStream.device, plexStream.address);
|
||||
player.platform = plexStream.platform;
|
||||
player.product = plexStream.product;
|
||||
player.title = plexStream.title;
|
||||
player.state = plexStream.state;
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
module.exports = convertStreamToPlayer;
|
||||
7
src/plex/stream/convertStreamToUser.js
Normal file
7
src/plex/stream/convertStreamToUser.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const User = require("../../media_classes/user");
|
||||
|
||||
function convertStreamToUser(plexStream) {
|
||||
return new User(plexStream.id, plexStream.title);
|
||||
}
|
||||
|
||||
module.exports = convertStreamToUser;
|
||||
16
src/plex/types/episode.js
Normal file
16
src/plex/types/episode.js
Normal file
@@ -0,0 +1,16 @@
|
||||
class Episode {
|
||||
constructor(title, show, year) {
|
||||
this.title = title;
|
||||
this.show = show;
|
||||
this.year = year;
|
||||
this.season = null;
|
||||
this.episode = null;
|
||||
this.summary = null;
|
||||
this.rating = null;
|
||||
this.views = null;
|
||||
this.aired = null;
|
||||
this.type = 'episode';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Episode;
|
||||
12
src/plex/types/movie.js
Normal file
12
src/plex/types/movie.js
Normal file
@@ -0,0 +1,12 @@
|
||||
class Movie {
|
||||
constructor(title, year) {
|
||||
this.title = title;
|
||||
this.year = year;
|
||||
this.summary = null;
|
||||
this.rating = null;
|
||||
this.tagline = null;
|
||||
this.type = 'movie';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Movie;
|
||||
12
src/plex/types/show.js
Normal file
12
src/plex/types/show.js
Normal file
@@ -0,0 +1,12 @@
|
||||
class Show {
|
||||
constructor(title, year) {
|
||||
this.title = title;
|
||||
this.year = year;
|
||||
this.summary = null;
|
||||
this.rating = null;
|
||||
this.seasons = null;
|
||||
this.episodes = null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Show;
|
||||
Reference in New Issue
Block a user