Merge pull request #30 from JurajNyiri/add_collections

2.1
2.1.1^2 2.1
Juraj Nyíri 3 years ago committed by GitHub
commit 23cf87f4b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -18674,6 +18674,8 @@ class Plex {
this.clients = []; this.clients = [];
this.requestTimeout = 10000; this.requestTimeout = 10000;
this.sections = []; this.sections = [];
this.collections = false;
this.playlists = [];
this.init = async () => { this.init = async () => {
await Promise.all([this.getSections(), this.getClients(), this.getServerID()]); await Promise.all([this.getSections(), this.getClients(), this.getServerID()]);
}; };
@ -18713,9 +18715,88 @@ class Plex {
} }
return this.sections; return this.sections;
}; };
this.getCollections = async () => {
if (!lodash.isArray(this.collections)) {
const sections = await this.getSections();
const collectionRequests = [];
lodash.forEach(sections, section => {
collectionRequests.push(this.getCollection(section.key));
});
const allResults = await Promise.all(collectionRequests);
const collections = [];
lodash.forEach(allResults, result => {
lodash.forEach(result, collection => {
collections.push(collection);
});
});
this.collections = collections;
}
return this.collections;
};
this.getPlaylists = async () => {
if (lodash.isEmpty(this.playlists)) {
this.playlists = [];
const url = this.authorizeURL(`${this.getBasicURL()}/playlists`);
const playlistsData = await axios.get(url, {
timeout: this.requestTimeout
});
this.playlists = playlistsData.data.MediaContainer.Metadata;
}
return this.playlists;
};
this.getCollection = async (sectionID) => {
const url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/collections`);
const collectionsData = await axios.get(url, {
timeout: this.requestTimeout
});
return lodash.isNil(collectionsData.data.MediaContainer.Metadata) ? [] : collectionsData.data.MediaContainer.Metadata;
};
this.getSectionData = async (sectionID) => { this.getSectionData = async (sectionID) => {
return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID)]); return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID)]);
}; };
this.getChildren = async (childrenURL) => {
const bulkItems = 50;
let url = this.authorizeURL(`${this.getBasicURL()}${childrenURL}`);
url += `&sort=${this.sort}`;
let result = {};
try {
result = await axios.get(url, {
timeout: this.requestTimeout
});
}
catch (err) {
// probably hitting limit of items to return, we need to request in parts
if (lodash.includes(err.message, 'Request failed with status code 500')) {
url += `&X-Plex-Container-Start=0&X-Plex-Container-Size=${bulkItems}`;
result = await axios.get(url, {
timeout: this.requestTimeout
});
const { totalSize } = result.data.MediaContainer;
let startOfItems = bulkItems;
const sectionsRequests = [];
while (startOfItems < totalSize) {
sectionsRequests.push(axios.get(this.authorizeURL(`${this.getBasicURL()}${childrenURL}?sort=${this.sort}&X-Plex-Container-Start=${startOfItems}&X-Plex-Container-Size=${bulkItems}`), {
timeout: this.requestTimeout
}));
startOfItems += bulkItems;
}
const allResults = await Promise.all(sectionsRequests);
lodash.forEach(allResults, multiResult => {
result.data.MediaContainer.Metadata = lodash.concat(result.data.MediaContainer.Metadata, multiResult.data.MediaContainer.Metadata);
});
}
else {
throw err;
}
}
return result.data.MediaContainer.Metadata;
};
this.getCollectionData = async (collectionKey) => {
return this.getChildren(collectionKey);
};
this.getPlaylistData = async (playlistKey) => {
return this.getChildren(playlistKey);
};
this.getSectionDataWithoutProcessing = async (sectionID) => { this.getSectionDataWithoutProcessing = async (sectionID) => {
const bulkItems = 50; const bulkItems = 50;
let url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/all`); let url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/all`);
@ -19505,6 +19586,8 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
this.entities = []; this.entities = [];
this.scriptEntities = []; this.scriptEntities = [];
this.sections = []; this.sections = [];
this.collections = [];
this.playlists = [];
this.clients = {}; this.clients = {};
this.entitiesRegistry = false; this.entitiesRegistry = false;
this.plexValidSection = document.createElement('div'); this.plexValidSection = document.createElement('div');
@ -19590,9 +19673,12 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
} }
}; };
this.render = async () => { this.render = async () => {
const addDropdownItem = (text) => { const addDropdownItem = (text, disabled = false) => {
const libraryItem = document.createElement('paper-item'); const libraryItem = document.createElement('paper-item');
libraryItem.innerHTML = text; libraryItem.innerHTML = text;
if (disabled) {
libraryItem.disabled = true;
}
return libraryItem; return libraryItem;
}; };
const createEntitiesDropdown = (selected, changeHandler) => { const createEntitiesDropdown = (selected, changeHandler) => {
@ -19692,6 +19778,7 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
this.content.appendChild(this.token); this.content.appendChild(this.token);
this.libraryName.innerHTML = ''; this.libraryName.innerHTML = '';
const libraryItems = document.createElement('paper-listbox'); const libraryItems = document.createElement('paper-listbox');
libraryItems.appendChild(addDropdownItem('Smart Libraries', true));
libraryItems.appendChild(addDropdownItem('Continue Watching')); libraryItems.appendChild(addDropdownItem('Continue Watching'));
libraryItems.appendChild(addDropdownItem('Deck')); libraryItems.appendChild(addDropdownItem('Deck'));
libraryItems.appendChild(addDropdownItem('Recently Added')); libraryItems.appendChild(addDropdownItem('Recently Added'));
@ -19706,6 +19793,8 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
this.appendChild(this.content); this.appendChild(this.content);
this.plex = new Plex(this.config.ip, this.plexPort, this.config.token, this.plexProtocol, this.config.sort); this.plex = new Plex(this.config.ip, this.plexPort, this.config.token, this.plexProtocol, this.config.sort);
this.sections = await this.plex.getSections(); this.sections = await this.plex.getSections();
this.collections = await this.plex.getCollections();
this.playlists = await this.plex.getPlaylists();
this.clients = await this.plex.getClients(); this.clients = await this.plex.getClients();
this.plexValidSection.style.display = 'none'; this.plexValidSection.style.display = 'none';
this.plexValidSection.innerHTML = ''; this.plexValidSection.innerHTML = '';
@ -19905,9 +19994,22 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
this.runAfter.value = this.config.runAfter; this.runAfter.value = this.config.runAfter;
this.plexValidSection.appendChild(this.runAfter); this.plexValidSection.appendChild(this.runAfter);
if (!lodash.isEmpty(this.sections)) { if (!lodash.isEmpty(this.sections)) {
libraryItems.appendChild(addDropdownItem('Libraries', true));
lodash.forEach(this.sections, (section) => { lodash.forEach(this.sections, (section) => {
libraryItems.appendChild(addDropdownItem(section.title)); libraryItems.appendChild(addDropdownItem(section.title));
}); });
if (!lodash.isEmpty(this.collections)) {
libraryItems.appendChild(addDropdownItem('Collections', true));
lodash.forEach(this.collections, (collection) => {
libraryItems.appendChild(addDropdownItem(collection.title));
});
}
if (!lodash.isEmpty(this.playlists)) {
libraryItems.appendChild(addDropdownItem('Playlists', true));
lodash.forEach(this.playlists, (playlist) => {
libraryItems.appendChild(addDropdownItem(playlist.title));
});
}
this.libraryName.disabled = false; this.libraryName.disabled = false;
this.libraryName.value = this.config.libraryName; this.libraryName.value = this.config.libraryName;
let libraryType = ''; let libraryType = '';
@ -21062,6 +21164,26 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.data[section.title1] = section.Metadata; this.data[section.title1] = section.Metadata;
}); });
} }
const collections = await this.plex.getCollections();
let collectionToGet = {};
lodash.forEach(collections, collection => {
if (this.plex && lodash.isEqual(collection.title, this.config.libraryName)) {
collectionToGet = collection;
}
});
if (!lodash.isNil(collectionToGet.key)) {
this.data[collectionToGet.title] = await this.plex.getCollectionData(collectionToGet.key);
}
const playlists = await this.plex.getPlaylists();
let playlistToGet = {};
lodash.forEach(playlists, playlist => {
if (this.plex && lodash.isEqual(playlist.title, this.config.libraryName)) {
playlistToGet = playlist;
}
});
if (!lodash.isNil(playlistToGet.key)) {
this.data[playlistToGet.title] = await this.plex.getPlaylistData(playlistToGet.key);
}
if (this.data[this.config.libraryName] === undefined) { if (this.data[this.config.libraryName] === undefined) {
this.error = `Library name ${this.config.libraryName} does not exist.`; this.error = `Library name ${this.config.libraryName} does not exist.`;
} }

@ -56,6 +56,10 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
sections: Array<Record<string, any>> = []; sections: Array<Record<string, any>> = [];
collections: Array<Record<string, any>> = [];
playlists: Array<Record<string, any>> = [];
clients: Record<string, any> = {}; clients: Record<string, any> = {};
entitiesRegistry: false | Array<Record<string, any>> = false; entitiesRegistry: false | Array<Record<string, any>> = false;
@ -148,9 +152,12 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
}; };
render = async (): Promise<void> => { render = async (): Promise<void> => {
const addDropdownItem = (text: string): HTMLElement => { const addDropdownItem = (text: string, disabled = false): HTMLElement => {
const libraryItem: any = document.createElement('paper-item'); const libraryItem: any = document.createElement('paper-item');
libraryItem.innerHTML = text; libraryItem.innerHTML = text;
if (disabled) {
libraryItem.disabled = true;
}
return libraryItem; return libraryItem;
}; };
const createEntitiesDropdown = (selected: string, changeHandler: Function): HTMLElement | false => { const createEntitiesDropdown = (selected: string, changeHandler: Function): HTMLElement | false => {
@ -259,6 +266,8 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
this.libraryName.innerHTML = ''; this.libraryName.innerHTML = '';
const libraryItems: any = document.createElement('paper-listbox'); const libraryItems: any = document.createElement('paper-listbox');
libraryItems.appendChild(addDropdownItem('Smart Libraries', true));
libraryItems.appendChild(addDropdownItem('Continue Watching')); libraryItems.appendChild(addDropdownItem('Continue Watching'));
libraryItems.appendChild(addDropdownItem('Deck')); libraryItems.appendChild(addDropdownItem('Deck'));
libraryItems.appendChild(addDropdownItem('Recently Added')); libraryItems.appendChild(addDropdownItem('Recently Added'));
@ -275,6 +284,8 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
this.plex = new Plex(this.config.ip, this.plexPort, this.config.token, this.plexProtocol, this.config.sort); this.plex = new Plex(this.config.ip, this.plexPort, this.config.token, this.plexProtocol, this.config.sort);
this.sections = await this.plex.getSections(); this.sections = await this.plex.getSections();
this.collections = await this.plex.getCollections();
this.playlists = await this.plex.getPlaylists();
this.clients = await this.plex.getClients(); this.clients = await this.plex.getClients();
this.plexValidSection.style.display = 'none'; this.plexValidSection.style.display = 'none';
@ -482,9 +493,23 @@ class PlexMeetsHomeAssistantEditor extends HTMLElement {
this.plexValidSection.appendChild(this.runAfter); this.plexValidSection.appendChild(this.runAfter);
if (!_.isEmpty(this.sections)) { if (!_.isEmpty(this.sections)) {
libraryItems.appendChild(addDropdownItem('Libraries', true));
_.forEach(this.sections, (section: Record<string, any>) => { _.forEach(this.sections, (section: Record<string, any>) => {
libraryItems.appendChild(addDropdownItem(section.title)); libraryItems.appendChild(addDropdownItem(section.title));
}); });
if (!_.isEmpty(this.collections)) {
libraryItems.appendChild(addDropdownItem('Collections', true));
_.forEach(this.collections, (collection: Record<string, any>) => {
libraryItems.appendChild(addDropdownItem(collection.title));
});
}
if (!_.isEmpty(this.playlists)) {
libraryItems.appendChild(addDropdownItem('Playlists', true));
_.forEach(this.playlists, (playlist: Record<string, any>) => {
libraryItems.appendChild(addDropdownItem(playlist.title));
});
}
this.libraryName.disabled = false; this.libraryName.disabled = false;
this.libraryName.value = this.config.libraryName; this.libraryName.value = this.config.libraryName;

@ -21,6 +21,10 @@ class Plex {
sections: Array<Record<string, any>> = []; sections: Array<Record<string, any>> = [];
collections: Array<Record<string, any>> | false = false;
playlists: Array<Record<string, any>> = [];
constructor( constructor(
ip: string, ip: string,
port: number | false = false, port: number | false = false,
@ -80,10 +84,105 @@ class Plex {
return this.sections; return this.sections;
}; };
getCollections = async (): Promise<Array<Record<string, any>>> => {
if (!_.isArray(this.collections)) {
const sections = await this.getSections();
const collectionRequests: Array<Promise<any>> = [];
_.forEach(sections, section => {
collectionRequests.push(this.getCollection(section.key));
});
const allResults = await Promise.all(collectionRequests);
const collections: Array<Record<string, any>> = [];
_.forEach(allResults, result => {
_.forEach(result, collection => {
collections.push(collection);
});
});
this.collections = collections;
}
return this.collections;
};
getPlaylists = async (): Promise<Array<Record<string, any>>> => {
if (_.isEmpty(this.playlists)) {
this.playlists = [];
const url = this.authorizeURL(`${this.getBasicURL()}/playlists`);
const playlistsData = await axios.get(url, {
timeout: this.requestTimeout
});
this.playlists = playlistsData.data.MediaContainer.Metadata;
}
return this.playlists;
};
getCollection = async (sectionID: number): Promise<Array<Record<string, any>>> => {
const url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/collections`);
const collectionsData = await axios.get(url, {
timeout: this.requestTimeout
});
return _.isNil(collectionsData.data.MediaContainer.Metadata) ? [] : collectionsData.data.MediaContainer.Metadata;
};
getSectionData = async (sectionID: number): Promise<any> => { getSectionData = async (sectionID: number): Promise<any> => {
return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID)]); return this.exportSectionsData([await this.getSectionDataWithoutProcessing(sectionID)]);
}; };
private getChildren = async (childrenURL: string): Promise<any> => {
const bulkItems = 50;
let url = this.authorizeURL(`${this.getBasicURL()}${childrenURL}`);
url += `&sort=${this.sort}`;
let result: Record<string, any> = {};
try {
result = await axios.get(url, {
timeout: this.requestTimeout
});
} catch (err) {
// probably hitting limit of items to return, we need to request in parts
if (_.includes(err.message, 'Request failed with status code 500')) {
url += `&X-Plex-Container-Start=0&X-Plex-Container-Size=${bulkItems}`;
result = await axios.get(url, {
timeout: this.requestTimeout
});
const { totalSize } = result.data.MediaContainer;
let startOfItems = bulkItems;
const sectionsRequests: Array<Promise<any>> = [];
while (startOfItems < totalSize) {
sectionsRequests.push(
axios.get(
this.authorizeURL(
`${this.getBasicURL()}${childrenURL}?sort=${
this.sort
}&X-Plex-Container-Start=${startOfItems}&X-Plex-Container-Size=${bulkItems}`
),
{
timeout: this.requestTimeout
}
)
);
startOfItems += bulkItems;
}
const allResults = await Promise.all(sectionsRequests);
_.forEach(allResults, multiResult => {
result.data.MediaContainer.Metadata = _.concat(
result.data.MediaContainer.Metadata,
multiResult.data.MediaContainer.Metadata
);
});
} else {
throw err;
}
}
return result.data.MediaContainer.Metadata;
};
getCollectionData = async (collectionKey: string): Promise<any> => {
return this.getChildren(collectionKey);
};
getPlaylistData = async (playlistKey: string): Promise<any> => {
return this.getChildren(playlistKey);
};
private getSectionDataWithoutProcessing = async (sectionID: number): Promise<any> => { private getSectionDataWithoutProcessing = async (sectionID: number): Promise<any> => {
const bulkItems = 50; const bulkItems = 50;
let url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/all`); let url = this.authorizeURL(`${this.getBasicURL()}/library/sections/${sectionID}/all`);

@ -426,6 +426,27 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.data[section.title1] = section.Metadata; this.data[section.title1] = section.Metadata;
}); });
} }
const collections = await this.plex.getCollections();
let collectionToGet: Record<string, any> = {};
_.forEach(collections, collection => {
if (this.plex && _.isEqual(collection.title, this.config.libraryName)) {
collectionToGet = collection;
}
});
if (!_.isNil(collectionToGet.key)) {
this.data[collectionToGet.title] = await this.plex.getCollectionData(collectionToGet.key);
}
const playlists = await this.plex.getPlaylists();
let playlistToGet: Record<string, any> = {};
_.forEach(playlists, playlist => {
if (this.plex && _.isEqual(playlist.title, this.config.libraryName)) {
playlistToGet = playlist;
}
});
if (!_.isNil(playlistToGet.key)) {
this.data[playlistToGet.title] = await this.plex.getPlaylistData(playlistToGet.key);
}
if (this.data[this.config.libraryName] === undefined) { if (this.data[this.config.libraryName] === undefined) {
this.error = `Library name ${this.config.libraryName} does not exist.`; this.error = `Library name ${this.config.libraryName} does not exist.`;

Loading…
Cancel
Save