Organization, formatting, and standardizing responses

This commit is contained in:
luke-hagar-sp
2022-08-03 20:10:46 -05:00
parent e8e2377d59
commit 62bab9e3f4
2 changed files with 208 additions and 120 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "plex-api-oauth", "name": "plex-api-oauth",
"version": "1.1.126", "version": "1.2.4",
"description": "An NPM Module designed to make Plex Media Server and plex.tv API calls easier to implement in JavaScript and React projects", "description": "An NPM Module designed to make Plex Media Server and plex.tv API calls easier to implement in JavaScript and React projects",
"main": "./src/index.js", "main": "./src/index.js",
"type": "module", "type": "module",

View File

@@ -3,6 +3,26 @@ import { v4 } from "uuid";
import axios from "axios"; import axios from "axios";
import qs from "qs"; import qs from "qs";
export function CreatePlexClientInformation(
clientIdentifier = v4(),
product = FnBrowserDetect(),
device = navigator.userAgentData.platform,
version = navigator.userAgentData.brands[0].version,
forwardUrl = "",
platform = "Plex-API-OAuth"
) {
let plexClientInformation = {
clientIdentifier: clientIdentifier,
product: product,
device: device,
version: version,
forwardUrl: forwardUrl,
platform: platform,
};
console.debug("Client Information generated successfully");
return plexClientInformation;
}
export async function PlexLogin(plexClientInformation) { export async function PlexLogin(plexClientInformation) {
var plexOauth = new PlexOauth(plexClientInformation); var plexOauth = new PlexOauth(plexClientInformation);
let data = await plexOauth.requestHostedLoginURL().catch((err) => { let data = await plexOauth.requestHostedLoginURL().catch((err) => {
@@ -84,7 +104,75 @@ export async function GetPlexDevices(plexClientInformation, plexTVAuthToken) {
}).catch((err) => { }).catch((err) => {
throw err; throw err;
}); });
return response.data; console.debug("Plex Devices Reponse Query:");
console.debug(response.data);
for (const server of response.data) {
let localConnection = {};
let serverCapabilities = {};
let preferredConnection = {};
let relayConnection = {};
if (server.connections) {
if (server.connections.length > 0) {
relayConnection = server.connections.filter(
(connection) => connection.relay === true
)[0];
preferredConnection = server.connections.filter(
(connection) => connection.relay === true
)[0];
for (const connection of server.connections.filter(
(entry) => entry.local === true
)) {
if (localConnection === null && serverCapabilities === null) {
try {
let capabilitiesresponse = await axios({
method: "GET",
url:
connection.uri +
"/?" +
qs.stringify({ "X-Plex-Token": server.accessToken }),
timeout: 1000,
});
localConnection = connection;
serverCapabilities = capabilitiesresponse.data.MediaContainer;
preferredConnection = connection;
} catch {}
}
}
}
}
serverArray.push({
name: server.name,
product: server.product,
productVersion: server.productVersion,
platform: server.platform,
platformVersion: server.platformVersion,
device: server.device,
clientIdentifier: server.clientIdentifier,
createdAt: server.createdAt,
lastSeenAt: server.lastSeenAt,
localConnection: localConnection,
preferredConnection: preferredConnection,
provides: server.provides,
ownerId: server.ownerId,
sourceTitle: server.sourceTitle,
publicAddress: server.publicAddress,
accessToken: server.accessToken,
owned: server.owned,
home: server.home,
synced: server.synced,
relay: server.relay,
relayConnection: relayConnection,
serverCapabilities: serverCapabilities,
presence: server.presence,
httpsRequired: server.httpsRequired,
publicAddressMatches: server.publicAddressMatches,
dnsRebindingProtection: server.dnsRebindingProtection,
natLoopbackSupported: server.natLoopbackSupported,
connections: server.connections,
});
}
return serverArray;
} }
export async function GetPlexServers(plexClientInformation, plexTVAuthToken) { export async function GetPlexServers(plexClientInformation, plexTVAuthToken) {
@@ -105,6 +193,8 @@ export async function GetPlexServers(plexClientInformation, plexTVAuthToken) {
}).catch((err) => { }).catch((err) => {
throw err; throw err;
}); });
console.debug("Plex Servers Reponse Query:");
console.debug(response.data);
for (const server of response.data.filter( for (const server of response.data.filter(
(Obj) => Obj.product === "Plex Media Server" (Obj) => Obj.product === "Plex Media Server"
)) { )) {
@@ -118,7 +208,7 @@ export async function GetPlexServers(plexClientInformation, plexTVAuthToken) {
)) { )) {
if (localConnection === null && serverCapabilities === null) { if (localConnection === null && serverCapabilities === null) {
try { try {
let response = await axios({ let capabilitiesresponse = await axios({
method: "GET", method: "GET",
url: url:
connection.uri + connection.uri +
@@ -127,7 +217,7 @@ export async function GetPlexServers(plexClientInformation, plexTVAuthToken) {
timeout: 1000, timeout: 1000,
}); });
localConnection = connection; localConnection = connection;
serverCapabilities = response.data.MediaContainer; serverCapabilities = capabilitiesresponse.data.MediaContainer;
preferredConnection = connection; preferredConnection = connection;
} catch {} } catch {}
} }
@@ -168,7 +258,7 @@ export async function GetPlexServers(plexClientInformation, plexTVAuthToken) {
return serverArray; return serverArray;
} }
export async function GetPlexLibraries(plexServers, plexLibraries) { export async function GetPlexLibraries(plexServers) {
let libraryArray = []; let libraryArray = [];
for (const server of plexServers) { for (const server of plexServers) {
let response = await axios({ let response = await axios({
@@ -864,26 +954,6 @@ export function LoadPlexSession() {
); );
} }
export function CreatePlexClientInformation(
clientIdentifier = v4(),
product = FnBrowserDetect(),
device = navigator.userAgentData.platform,
version = navigator.userAgentData.brands[0].version,
forwardUrl = "",
platform = "Plex-API-OAuth"
) {
let plexClientInformation = {
clientIdentifier: clientIdentifier,
product: product,
device: device,
version: version,
forwardUrl: forwardUrl,
platform: platform,
};
console.debug("Client Information generated successfully");
return plexClientInformation;
}
export async function GetLibraryPages( export async function GetLibraryPages(
plexServers, plexServers,
plexLibraries, plexLibraries,
@@ -1076,15 +1146,12 @@ export async function GetArtistPage(
let albums = []; let albums = [];
let response = {}; let response = {};
let songs = []; let songs = [];
let relatedAlbums = []; let relatedArtists = [];
for (const server of plexServers.filter( //.filter((Obj) => Obj.clientIdentifier === artistObject.server)
(Obj) => Obj.clientIdentifier === artistObject.server //&& Obj.uuid === artistObject.library;
)) { for (const server of plexServers) {
for (const musicLibrary of plexLibraries.filter( for (const musicLibrary of plexLibraries.filter(
(Obj) => (Obj) => Obj.server === server.clientIdentifier && Obj.type === "artist"
Obj.server === server.clientIdentifier &&
Obj.type === "artist" &&
Obj.uuid === artistObject.library
)) { )) {
response = await axios({ response = await axios({
method: "GET", method: "GET",
@@ -1105,7 +1172,7 @@ export async function GetArtistPage(
}).catch((err) => { }).catch((err) => {
throw err; throw err;
}); });
console.debug(response.data); console.warn(response.data);
if (response.data.MediaContainer.size > 0) { if (response.data.MediaContainer.size > 0) {
for (const album of response.data.MediaContainer.Metadata) { for (const album of response.data.MediaContainer.Metadata) {
albums.push({ albums.push({
@@ -1218,7 +1285,7 @@ export async function GetArtistPage(
} }
} }
let relatedAlbumsResponse = await axios({ let relatedArtistsResponse = await axios({
method: "GET", method: "GET",
url: url:
server.preferredConnection.uri + server.preferredConnection.uri +
@@ -1238,49 +1305,59 @@ export async function GetArtistPage(
}).catch((err) => { }).catch((err) => {
throw err; throw err;
}); });
console.debug(relatedAlbumsResponse.data); console.debug(relatedArtistsResponse.data);
if (relatedAlbumsResponse.data.MediaContainer.size > 0) { if (
for (const album of relatedAlbumsResponse.data.MediaContainer.Hub[6] relatedArtistsResponse.data.MediaContainer.Hub.some(function (Object) {
.Metadata) { return Object.title === "Similar Artists";
relatedAlbums.push({ })
server: server.clientIdentifier, ) {
library: musicLibrary.uuid, let relatedArtistHub =
Director: album.Director, relatedArtistsResponse.data.MediaContainer.Hub.filter(
Genre: album.Genre, (Obj) => Obj.title === "Similar Artists"
addedAt: album.addedAt, );
guid: album.guid, console.warn(relatedArtistHub);
index: album.index, for (const hubAlbum of relatedArtistHub) {
key: album.key, for (const album of hubAlbum.Metadata) {
lastViewedAt: album.lastViewedAt, relatedArtists.push({
loudnessAnalysisVersion: album.loudnessAnalysisVersion, server: server.clientIdentifier,
musicAnalysisVersion: album.musicAnalysisVersion, library: musicLibrary.uuid,
originallyAvailableAt: album.originallyAvailableAt, Director: album.Director,
parentGuid: album.parentGuid, Genre: album.Genre,
parentKey: album.parentKey, addedAt: album.addedAt,
parentRatingKey: album.parentRatingKey, guid: album.guid,
parentThumb: album.parentThumb, index: album.index,
parentTitle: album.parentTitle, key: album.key,
rating: album.rating, lastViewedAt: album.lastViewedAt,
ratingKey: album.ratingKey, loudnessAnalysisVersion: album.loudnessAnalysisVersion,
studio: album.studio, musicAnalysisVersion: album.musicAnalysisVersion,
summary: album.summary, originallyAvailableAt: album.originallyAvailableAt,
thumb: parentGuid: album.parentGuid,
server.preferredConnection.uri + parentKey: album.parentKey,
"/photo/:/transcode?" + parentRatingKey: album.parentRatingKey,
qs.stringify({ parentThumb: album.parentThumb,
width: 240, parentTitle: album.parentTitle,
height: 240, rating: album.rating,
minSize: 1, ratingKey: album.ratingKey,
upscale: 1, studio: album.studio,
url: album.thumb + "?X-Plex-Token=" + server.accessToken, summary: album.summary,
"X-Plex-Token": server.accessToken, thumb:
}), server.preferredConnection.uri +
title: album.title, "/photo/:/transcode?" +
type: album.type, qs.stringify({
updatedAt: album.updatedAt, width: 240,
viewCount: album.viewCount, height: 240,
year: album.year, minSize: 1,
}); upscale: 1,
url: album.thumb + "?X-Plex-Token=" + server.accessToken,
"X-Plex-Token": server.accessToken,
}),
title: album.title,
type: album.type,
updatedAt: album.updatedAt,
viewCount: album.viewCount,
year: album.year,
});
}
} }
} }
@@ -1302,6 +1379,8 @@ export async function GetArtistPage(
sort: "ratingCount:desc", sort: "ratingCount:desc",
type: 10, type: 10,
includeUserState: 1, includeUserState: 1,
includeCollections: 1,
includeExternalMedia: 1,
"X-Plex-Container-Start": 0, "X-Plex-Container-Start": 0,
"X-Plex-Container-Size": 20, "X-Plex-Container-Size": 20,
"X-Plex-Product": plexClientInformation.product, "X-Plex-Product": plexClientInformation.product,
@@ -1313,55 +1392,64 @@ export async function GetArtistPage(
throw err; throw err;
}); });
console.debug(songResponse.data); console.debug(songResponse.data);
for (const song of songResponse.data.MediaContainer.Metadata) { if (songResponse.data.MediaContainer.size > 0) {
songs.push({ for (const song of songResponse.data.MediaContainer.Metadata) {
server: server.clientIdentifier, songs.push({
library: musicLibrary.uuid, server: server.clientIdentifier,
ratingKey: song.ratingKey, library: musicLibrary.uuid,
key: song.key, ratingKey: song.ratingKey,
parentRatingKey: song.parentRatingKey, key: song.key,
grandparentRatingKey: song.grandparentRatingKey, parentRatingKey: song.parentRatingKey,
guid: song.guid, grandparentRatingKey: song.grandparentRatingKey,
parentGuid: song.parentGuid, guid: song.guid,
grandparentGuid: song.grandparentGuid, parentGuid: song.parentGuid,
type: song.type, grandparentGuid: song.grandparentGuid,
title: song.title, type: song.type,
grandparentKey: song.grandparentKey, title: song.title,
parentKey: song.parentKey, grandparentKey: song.grandparentKey,
grandparentTitle: song.grandparentTitle, parentKey: song.parentKey,
parentTitle: song.parentTitle, grandparentTitle: song.grandparentTitle,
originalTitle: song.originalTitle, parentTitle: song.parentTitle,
summary: song.summary, originalTitle: song.originalTitle,
index: song.index, summary: song.summary,
parentIndex: song.parentIndex, index: song.index,
thumb: parentIndex: song.parentIndex,
server.preferredConnection.uri + thumb:
"/photo/:/transcode?" + server.preferredConnection.uri +
qs.stringify({ "/photo/:/transcode?" +
width: 240, qs.stringify({
height: 240, width: 240,
minSize: 1, height: 240,
upscale: 1, minSize: 1,
url: song.thumb + "?X-Plex-Token=" + server.accessToken, upscale: 1,
"X-Plex-Token": server.accessToken, url: song.thumb + "?X-Plex-Token=" + server.accessToken,
}), "X-Plex-Token": server.accessToken,
parentThumb: song.parentThumb, }),
grandparentThumb: song.grandparentThumb, parentThumb: song.parentThumb,
duration: song.duration, grandparentThumb: song.grandparentThumb,
addedAt: song.addedAt, duration: song.duration,
updatedAt: song.updatedAt, addedAt: song.addedAt,
musicAnalysisVersion: song.musicAnalysisVersion, updatedAt: song.updatedAt,
Media: song.Media, musicAnalysisVersion: song.musicAnalysisVersion,
}); Media: song.Media,
});
}
} }
} }
} }
const albumArray = albums
.map((item) => {
return Object.fromEntries(Object.entries(item).sort());
})
.map(JSON.stringify);
return { return {
inputObject: artistObject, inputObject: artistObject,
response: response.data, response: response.data,
albums, albums: [...new Set(albumArray)].map(JSON.parse),
songs, songs,
relatedAlbums, relatedArtists,
}; };
} }