Skip to content

Commit

Permalink
remove half the syncing
Browse files Browse the repository at this point in the history
  • Loading branch information
Sylvain Blanc committed Oct 26, 2023
1 parent 6638f01 commit 1ab1064
Show file tree
Hide file tree
Showing 5 changed files with 394 additions and 782 deletions.
223 changes: 223 additions & 0 deletions backend/jellyfin/jellyfin-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
const https = require("https");
const axios = require("axios");
const db = require("../db");

class JellyfinClient {
constructor(hostUrl, apiKey) {
if (!hostUrl || !apiKey) {
throw new Error(
"Misconfigured Jellyfin CLient, missing hostUrl or apiKey",
);
}
this.hostUrl = hostUrl;
this.apiKey = apiKey;
const agent = new https.Agent({
rejectUnauthorized:
(
process.env.REJECT_SELF_SIGNED_CERTIFICATES || "true"
).toLowerCase() === "true",
});

this.axios_instance = axios.create({
httpsAgent: agent,
});
}

async getUsers() {
try {
const url = `${this.hostUrl}/Users`;
const response = await this.axios_instance.get(url, {
headers: {
"X-MediaBrowser-Token": this.apiKey,
},
});
return response.data;
} catch (error) {
console.log(error);
return [];
}
}

async getAdminUser() {
try {
const url = `${this.hostUrl}/Users`;
const response = await this.axios_instance.get(url, {
headers: {
"X-MediaBrowser-Token": this.apiKey,
},
});

if (
!response ||
typeof response.data !== "object" ||
!Array.isArray(response.data)
) {
res.status(503);
res.send({
error: "Invalid Response from Users API Call.",
user_response: response,
});
return;
}

const adminUser = response.data.filter(
(user) => user.Policy.IsAdministrator === true,
);
return adminUser || null;
} catch (error) {
console.log(error);
syncTask.loggedData.push({ Message: "Error Getting AdminId: " + error });
return [];
}
}

async getItem(ids, params) {
try {
let url = `${this.hostUrl}/Items?ids=${ids}`;
let startIndex = params && params.startIndex ? params.startIndex : 0;
let increment = params && params.increment ? params.startIndex : 200;
let recursive =
params && params.recursive !== undefined ? params.recursive : true;
let total = 200;

let final_response = [];
while (startIndex < total && total !== undefined) {
const response = await this.axios_instance.get(url, {
headers: {
"X-MediaBrowser-Token": this.apiKey,
},
params: {
startIndex: startIndex,
recursive: recursive,
limit: increment,
},
});

total = response.data.TotalRecordCount;
startIndex += increment;

final_response = [...final_response, ...response.data.Items];
}

return final_response;
} catch (error) {
console.log(error);
return [];
}
}

async getLibrariesFromApi() {
try {
let url = `${this.hostUrl}/Library/MediaFolders`;

const response_data = await this.axios_instance.get(url, {
headers: {
"X-MediaBrowser-Token": this.apiKey,
},
});

return response_data.data.Items.filter(
(type) => !["boxsets", "playlists"].includes(type.CollectionType),
);
} catch (error) {
// console.log(error);
return [];
}
}

async getItems(key, id, types) {
try {
let url = `${
this.hostUrl
}/Items?${key}=${id}&includeItemTypes=${types.join(",")}`;
let startIndex = 0;
let increment = 200;
let recursive = true;
let total = 200;

let final_response = [];
while (startIndex < total && total !== undefined) {
const response = await this.axios_instance.get(url, {
headers: {
"X-MediaBrowser-Token": this.apiKey,
},
params: {
startIndex: startIndex,
recursive: recursive,
limit: increment,
},
});

total = response.data.TotalRecordCount;
startIndex += increment;

final_response.push(...response.data.Items);
}

// const results = response.data.Items;
if (key === "userid") {
return final_response.filter(
(type) => !["boxsets", "playlists"].includes(type.CollectionType),
);
} else {
// return final_response.filter((item) => item.ImageTags.Primary);
return final_response;
}
} catch (error) {
console.log(error);
return [];
}
}

async getItemPlaybackInfo(itemID, userid) {
try {
let url = `${this.hostUrl}/Items/${itemID}/playbackinfo?userId=${userid}`;

const response = await this.axios_instance.get(url, {
headers: {
"X-MediaBrowser-Token": this.apiKey,
},
});

return response.data.MediaSources;
} catch (error) {
console.log(error);
return [];
}
}

async getItemsOfType(filtered_libraries, types) {
const data = [];
//for each item in library run get item using that id as the ParentId (This gets the children of the parent id)
for (let i = 0; i < filtered_libraries.length; i++) {
const library = filtered_libraries[i];
let libraryItems = (await this.getItems("parentId", library.Id, types))
// Strange mapping needed, removing it breaks things further down the line
.map(item => { item.ParentId = library.Id; return item})
data
.push(...libraryItems);
}
return data;
}

async getPlugins() {
//Playback Reporting Plugin Check
const pluginURL = `${this.hostUrl}/plugins`;

const pluginResponse = await this.axios_instance.get(pluginURL, {
headers: {
"X-MediaBrowser-Token": this.apiKey,
},
});
return pluginResponse.data;
}
}
async function getJellyfinClient() {
const { rows: config } = await db.query(
'SELECT * FROM app_config where "ID"=1',
);

return new JellyfinClient(config[0]?.JF_HOST, config[0]?.JF_API_KEY);
}

module.exports = getJellyfinClient;
33 changes: 17 additions & 16 deletions backend/routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const axios = require("axios");
const db = require("../db");
const https = require("https");
const { randomUUID } = require("crypto");
const getJellyfinClient = require("../jellyfin/jellyfin-client");
const { fetchItem } = require("./sync");

const agent = new https.Agent({
rejectUnauthorized:
Expand Down Expand Up @@ -76,7 +78,7 @@ router.post("/setPreferredAdmin", async (req, res) => {

let query = 'UPDATE app_config SET settings=$1 where "ID"=1';

const { rows } = await db.query(query, [settings]);
await db.query(query, [settings]);

res.send("Settings updated succesfully");
} else {
Expand Down Expand Up @@ -242,13 +244,8 @@ router.get("/keys", async (req, res) => {
.query('SELECT api_keys FROM app_config where "ID"=1')
.then((res) => res.rows[0].api_keys);

if (keysjson) {
const keys = keysjson || [];
res.send(keys);
} else {
res.status(404);
res.send("Settings not found");
}
const keys = keysjson || [];
res.send(keys);
});

router.delete("/keys", async (req, res) => {
Expand Down Expand Up @@ -485,9 +482,7 @@ router.get("/dataValidator", async (req, res) => {
});

let libraries = response_data.data.Items;
let raw_library_data = response_data.data;

payload.raw_library_data = raw_library_data;
payload.raw_library_data = response_data.data;

//get items
const show_data = [];
Expand Down Expand Up @@ -715,9 +710,12 @@ router.post("/getEpisodes", async (req, res) => {

router.post("/getItemDetails", async (req, res) => {
try {
const { Id } = req.body;
let query = `SELECT im."Name" "FileName",im.*,i.* FROM jf_library_items i left join jf_item_info im on i."Id" = im."Id" where i."Id"=$1`;
const { itemId: Id } = req.body;
// Fetching item allow to skip syncing of whole jellyfin database into jellystats, only fetching when using it
await fetchItem(req, res)

let query = `SELECT im."Name" "FileName",im.*,i.* FROM jf_library_items i left join jf_item_info im on i."Id" = im."Id" where i."Id"=$1`;
const jellyfinClient = await getJellyfinClient();
const { rows: items } = await db.query(query, [Id]);

if (items.length === 0) {
Expand Down Expand Up @@ -812,14 +810,17 @@ router.post("/getLibraryHistory", async (req, res) => {

router.post("/getItemHistory", async (req, res) => {
try {
console.log(req.body);
console.log(req.body);
console.log(req.body);
const { itemid } = req.body;

const { rows } = await db.query(
`select jf_playback_activity.*
from jf_playback_activity jf_playback_activity
where
("EpisodeId"=$1 OR "SeasonId"=$1 OR "NowPlayingItemId"=$1);`,
[idemid],
[itemid],
);

const groupedResults = rows.map((item) => ({
Expand All @@ -841,8 +842,8 @@ router.post("/getUserHistory", async (req, res) => {

const { rows } = await db.query(
`select jf_playback_activity.*
from jf_playback_activity jf_playback_activity
where "UserId"=$1;`,
from jf_playback_activity
where "UserId" = $1;`,
[userid],
);

Expand Down
Loading

0 comments on commit 1ab1064

Please sign in to comment.