Add: Deck, Continue Watching, Watch Next and Recently Added special libraries with support for older plex servers

pull/16/head
Juraj Nyíri 4 years ago
parent f245283f59
commit 7e0967267d

@ -33,11 +33,14 @@ More images [at the end of the readme](https://github.com/JurajNyiri/PlexMeetsHo
**libraryName**: Name of the library you wish to render. **libraryName**: Name of the library you wish to render.
Available special libraries: _Available special libraries:_
_Deck_: Shows Continue Watching | Special Library | Description |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
_Recently Added_: Shows recently added episodes of TV Shows. Tip: For movies, just put in your library name and use sort. | Watch Next | Shows Continue Watching feed just like in your new plex interface. **Does not work with old servers.** |
| Recently Added | Shows recently added tv show episodes, might use old Plex API. For recently added movies use sort with your movies library. |
| Continue Watching | Shows movies and tv shows in progress, uses old Plex API. |
| Deck | Shows tv shows on deck, uses old Plex API. |
**protocol**: _Optional_ Protocol to use for Plex. Defaults to "http". **protocol**: _Optional_ Protocol to use for Plex. Defaults to "http".

@ -18729,13 +18729,31 @@ class Plex {
}); });
return this.exportSectionsData(await Promise.all(sectionsRequests)); return this.exportSectionsData(await Promise.all(sectionsRequests));
}; };
this.getRecentyAdded = async () => { this.getRecentyAdded = async (useHub = false) => {
if (useHub) {
const hubs = await this.getHubs();
let recentlyAddedData = {};
// eslint-disable-next-line consistent-return
lodash.forEach(hubs.Hub, hub => {
if (lodash.isEqual(hub.key, '/hubs/home/recentlyAdded?type=2')) {
recentlyAddedData = hub;
return false;
}
});
return recentlyAddedData;
}
const url = this.authorizeURL(`${this.getBasicURL()}/hubs/home/recentlyAdded?type=2&X-Plex-Container-Start=0&X-Plex-Container-Size=50`); const url = this.authorizeURL(`${this.getBasicURL()}/hubs/home/recentlyAdded?type=2&X-Plex-Container-Start=0&X-Plex-Container-Size=50`);
return (await axios.get(url, { return (await axios.get(url, {
timeout: this.requestTimeout timeout: this.requestTimeout
})).data.MediaContainer; })).data.MediaContainer;
}; };
this.getContinueWatching = async () => { this.getHubs = async () => {
const url = this.authorizeURL(`${this.getBasicURL()}/hubs?includeEmpty=1&count=50&includeFeaturedTags=1&includeTypeFirst=1&includeStations=1&includeExternalMetadata=1&excludePlaylists=1`);
return (await axios.get(url, {
timeout: this.requestTimeout
})).data.MediaContainer;
};
this.getWatchNext = async () => {
const sections = await this.getSections(); const sections = await this.getSections();
let sectionsString = ''; let sectionsString = '';
lodash.forEach(sections, section => { lodash.forEach(sections, section => {
@ -18747,6 +18765,30 @@ class Plex {
timeout: this.requestTimeout timeout: this.requestTimeout
})).data.MediaContainer; })).data.MediaContainer;
}; };
this.getContinueWatching = async () => {
const hubs = await this.getHubs();
let continueWatchingData = {};
// eslint-disable-next-line consistent-return
lodash.forEach(hubs.Hub, hub => {
if (lodash.isEqual(hub.key, '/hubs/home/continueWatching')) {
continueWatchingData = hub;
return false;
}
});
return continueWatchingData;
};
this.getOnDeck = async () => {
const hubs = await this.getHubs();
let onDeckData = {};
// eslint-disable-next-line consistent-return
lodash.forEach(hubs.Hub, hub => {
if (lodash.isEqual(hub.key, '/hubs/home/onDeck')) {
onDeckData = hub;
return false;
}
});
return onDeckData;
};
this.getBasicURL = () => { this.getBasicURL = () => {
return `${this.protocol}://${this.ip}:${this.port}`; return `${this.protocol}://${this.ip}:${this.port}`;
}; };
@ -19094,6 +19136,9 @@ const isVideoFullScreen = (_this) => {
return ((video.offsetWidth === body.offsetHeight && video.offsetHeight === body.offsetHeight) || return ((video.offsetWidth === body.offsetHeight && video.offsetHeight === body.offsetHeight) ||
(_this.videoElem && _this.videoElem.classList.contains('simulatedFullScreen'))); (_this.videoElem && _this.videoElem.classList.contains('simulatedFullScreen')));
}; };
const getOldPlexServerErrorMessage = (libraryName) => {
return `PlexMeetsHomeAssistant: 404 Error requesting library feed for ${libraryName}. Plex API might have changed or using outdated server. Library ${libraryName} will not work.`;
};
const findTrailerURL = (movieData) => { const findTrailerURL = (movieData) => {
let foundURL = ''; let foundURL = '';
if (movieData.Extras && movieData.Extras.Metadata && movieData.Extras.Metadata.length > 0) { if (movieData.Extras && movieData.Extras.Metadata && movieData.Extras.Metadata.length > 0) {
@ -19874,15 +19919,62 @@ class PlexMeetsHomeAssistant extends HTMLElement {
try { try {
if (this.plex) { if (this.plex) {
await this.plex.init(); await this.plex.init();
try {
const onDeck = await this.plex.getOnDeck();
this.data.Deck = onDeck.Metadata;
}
catch (err) {
if (lodash.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Deck'));
}
else {
throw err;
}
}
try { try {
const continueWatching = await this.plex.getContinueWatching(); const continueWatching = await this.plex.getContinueWatching();
this.data['Continue Watching'] = continueWatching.Metadata;
}
catch (err) {
if (lodash.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Continue Watching'));
}
else {
throw err;
}
}
try {
const watchNext = await this.plex.getWatchNext();
this.data['Watch Next'] = watchNext.Metadata;
}
catch (err) {
if (lodash.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Watch Next'));
}
else {
throw err;
}
}
try {
const recentlyAdded = await this.plex.getRecentyAdded(); const recentlyAdded = await this.plex.getRecentyAdded();
this.data.Deck = continueWatching.Metadata;
this.data['Recently Added'] = recentlyAdded.Metadata; this.data['Recently Added'] = recentlyAdded.Metadata;
} }
catch (err) { catch (err) {
if (lodash.includes(err.message, 'Request failed with status code 404')) { if (lodash.includes(err.message, 'Request failed with status code 404')) {
console.warn('PlexMeetsHomeAssistant: You are using outdated Plex server. Recently added and continue watching is not available.'); try {
console.warn('PlexMeetsHomeAssistant: Using old endpoint for recently added tv shows. Consider updating your Plex server.');
const recentlyAdded = await this.plex.getRecentyAdded(true);
this.data['Recently Added'] = recentlyAdded.Metadata;
// eslint-disable-next-line no-shadow
}
catch (err) {
if (lodash.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Recently Added'));
}
else {
throw err;
}
}
} }
else { else {
throw err; throw err;

@ -94,7 +94,19 @@ class Plex {
return this.exportSectionsData(await Promise.all(sectionsRequests)); return this.exportSectionsData(await Promise.all(sectionsRequests));
}; };
getRecentyAdded = async (): Promise<any> => { getRecentyAdded = async (useHub = false): Promise<any> => {
if (useHub) {
const hubs = await this.getHubs();
let recentlyAddedData: Record<string, any> = {};
// eslint-disable-next-line consistent-return
_.forEach(hubs.Hub, hub => {
if (_.isEqual(hub.key, '/hubs/home/recentlyAdded?type=2')) {
recentlyAddedData = hub;
return false;
}
});
return recentlyAddedData;
}
const url = this.authorizeURL( const url = this.authorizeURL(
`${this.getBasicURL()}/hubs/home/recentlyAdded?type=2&X-Plex-Container-Start=0&X-Plex-Container-Size=50` `${this.getBasicURL()}/hubs/home/recentlyAdded?type=2&X-Plex-Container-Start=0&X-Plex-Container-Size=50`
); );
@ -105,7 +117,18 @@ class Plex {
).data.MediaContainer; ).data.MediaContainer;
}; };
getContinueWatching = async (): Promise<any> => { private getHubs = async (): Promise<any> => {
const url = this.authorizeURL(
`${this.getBasicURL()}/hubs?includeEmpty=1&count=50&includeFeaturedTags=1&includeTypeFirst=1&includeStations=1&includeExternalMetadata=1&excludePlaylists=1`
);
return (
await axios.get(url, {
timeout: this.requestTimeout
})
).data.MediaContainer;
};
getWatchNext = async (): Promise<any> => {
const sections = await this.getSections(); const sections = await this.getSections();
let sectionsString = ''; let sectionsString = '';
_.forEach(sections, section => { _.forEach(sections, section => {
@ -122,6 +145,32 @@ class Plex {
).data.MediaContainer; ).data.MediaContainer;
}; };
getContinueWatching = async (): Promise<any> => {
const hubs = await this.getHubs();
let continueWatchingData: Record<string, any> = {};
// eslint-disable-next-line consistent-return
_.forEach(hubs.Hub, hub => {
if (_.isEqual(hub.key, '/hubs/home/continueWatching')) {
continueWatchingData = hub;
return false;
}
});
return continueWatchingData;
};
getOnDeck = async (): Promise<any> => {
const hubs = await this.getHubs();
let onDeckData: Record<string, any> = {};
// eslint-disable-next-line consistent-return
_.forEach(hubs.Hub, hub => {
if (_.isEqual(hub.key, '/hubs/home/onDeck')) {
onDeckData = hub;
return false;
}
});
return onDeckData;
};
getBasicURL = (): string => { getBasicURL = (): string => {
return `${this.protocol}://${this.ip}:${this.port}`; return `${this.protocol}://${this.ip}:${this.port}`;
}; };

@ -65,6 +65,10 @@ const isVideoFullScreen = (_this: any): boolean => {
); );
}; };
const getOldPlexServerErrorMessage = (libraryName: string): string => {
return `PlexMeetsHomeAssistant: 404 Error requesting library feed for ${libraryName}. Plex API might have changed or using outdated server. Library ${libraryName} will not work.`;
};
const findTrailerURL = (movieData: Record<string, any>): string => { const findTrailerURL = (movieData: Record<string, any>): string => {
let foundURL = ''; let foundURL = '';
if (movieData.Extras && movieData.Extras.Metadata && movieData.Extras.Metadata.length > 0) { if (movieData.Extras && movieData.Extras.Metadata && movieData.Extras.Metadata.length > 0) {
@ -180,5 +184,6 @@ export {
createEpisodesView, createEpisodesView,
findTrailerURL, findTrailerURL,
isVideoFullScreen, isVideoFullScreen,
hasEpisodes hasEpisodes,
getOldPlexServerErrorMessage
}; };

@ -13,7 +13,8 @@ import {
createEpisodesView, createEpisodesView,
findTrailerURL, findTrailerURL,
isVideoFullScreen, isVideoFullScreen,
hasEpisodes hasEpisodes,
getOldPlexServerErrorMessage
} from './modules/utils'; } from './modules/utils';
import style from './modules/style'; import style from './modules/style';
@ -143,16 +144,59 @@ class PlexMeetsHomeAssistant extends HTMLElement {
try { try {
if (this.plex) { if (this.plex) {
await this.plex.init(); await this.plex.init();
try {
const onDeck = await this.plex.getOnDeck();
this.data.Deck = onDeck.Metadata;
} catch (err) {
if (_.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Deck'));
} else {
throw err;
}
}
try { try {
const continueWatching = await this.plex.getContinueWatching(); const continueWatching = await this.plex.getContinueWatching();
this.data['Continue Watching'] = continueWatching.Metadata;
} catch (err) {
if (_.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Continue Watching'));
} else {
throw err;
}
}
try {
const watchNext = await this.plex.getWatchNext();
this.data['Watch Next'] = watchNext.Metadata;
} catch (err) {
if (_.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Watch Next'));
} else {
throw err;
}
}
try {
const recentlyAdded = await this.plex.getRecentyAdded(); const recentlyAdded = await this.plex.getRecentyAdded();
this.data.Deck = continueWatching.Metadata;
this.data['Recently Added'] = recentlyAdded.Metadata; this.data['Recently Added'] = recentlyAdded.Metadata;
} catch (err) { } catch (err) {
if (_.includes(err.message, 'Request failed with status code 404')) { if (_.includes(err.message, 'Request failed with status code 404')) {
try {
console.warn( console.warn(
'PlexMeetsHomeAssistant: You are using outdated Plex server. Recently added and continue watching is not available.' 'PlexMeetsHomeAssistant: Using old endpoint for recently added tv shows. Consider updating your Plex server.'
); );
const recentlyAdded = await this.plex.getRecentyAdded(true);
this.data['Recently Added'] = recentlyAdded.Metadata;
// eslint-disable-next-line no-shadow
} catch (err) {
if (_.includes(err.message, 'Request failed with status code 404')) {
console.warn(getOldPlexServerErrorMessage('Recently Added'));
} else {
throw err;
}
}
} else { } else {
throw err; throw err;
} }

Loading…
Cancel
Save