mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-07-16 01:13:27 +01:00
chore: refactor
This commit is contained in:
18
utils/jellyfin/image/getPrimaryImage.ts
Normal file
18
utils/jellyfin/image/getPrimaryImage.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { getImageApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
|
||||
export const getPrimaryImage = async (
|
||||
api: Api,
|
||||
itemId: string,
|
||||
): Promise<string> => {
|
||||
const image = await getImageApi(api).getItemImage({
|
||||
itemId,
|
||||
imageType: "Primary",
|
||||
quality: 90,
|
||||
width: 1000,
|
||||
});
|
||||
|
||||
console.log("getPrimaryImage ~", image.data);
|
||||
|
||||
return image.data;
|
||||
};
|
||||
46
utils/jellyfin/items/getUserItemData.ts
Normal file
46
utils/jellyfin/items/getUserItemData.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import {
|
||||
getMediaInfoApi,
|
||||
getUserLibraryApi,
|
||||
} from "@jellyfin/sdk/lib/utils/api";
|
||||
|
||||
/**
|
||||
* Fetches the media info for a given item.
|
||||
*
|
||||
* @param {Api} api - The Jellyfin API instance.
|
||||
* @param {string} itemId - The ID of the media to fetch info for.
|
||||
* @param {string} userId - The ID of the user to fetch info for.
|
||||
*
|
||||
* @returns {Promise<BaseItemDto>} - The media info.
|
||||
*/
|
||||
export const getUserItemData = async ({
|
||||
api,
|
||||
itemId,
|
||||
userId,
|
||||
}: {
|
||||
api: Api | null | undefined;
|
||||
itemId: string | null | undefined;
|
||||
userId: string | null | undefined;
|
||||
}) => {
|
||||
if (!api || !itemId || !userId) {
|
||||
return null;
|
||||
}
|
||||
return (await getUserLibraryApi(api).getItem({ itemId, userId })).data;
|
||||
};
|
||||
|
||||
export const getPlaybackInfo = async (
|
||||
api?: Api | null | undefined,
|
||||
itemId?: string | null | undefined,
|
||||
userId?: string | null | undefined,
|
||||
) => {
|
||||
if (!api || !itemId || !userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const a = await getMediaInfoApi(api).getPlaybackInfo({
|
||||
itemId,
|
||||
userId,
|
||||
});
|
||||
|
||||
return a.data;
|
||||
};
|
||||
8
utils/jellyfin/jellyfin.ts
Normal file
8
utils/jellyfin/jellyfin.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
|
||||
/**
|
||||
* Generates the authorization headers for Jellyfin API requests.
|
||||
*/
|
||||
export const getAuthHeaders = (api: Api) => ({
|
||||
Authorization: `MediaBrowser DeviceId="${api.deviceInfo.id}", Token="${api.accessToken}"`,
|
||||
});
|
||||
47
utils/jellyfin/playstate/markAsNotPlayed.ts
Normal file
47
utils/jellyfin/playstate/markAsNotPlayed.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { AxiosError } from "axios";
|
||||
|
||||
interface MarkAsNotPlayedParams {
|
||||
api: Api | null | undefined;
|
||||
itemId: string | null | undefined;
|
||||
userId: string | null | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a media item as not played for a specific user.
|
||||
*
|
||||
* @param params - The parameters for marking an item as not played
|
||||
* @returns A promise that resolves to true if the operation was successful, false otherwise
|
||||
*/
|
||||
export const markAsNotPlayed = async ({
|
||||
api,
|
||||
itemId,
|
||||
userId,
|
||||
}: MarkAsNotPlayedParams): Promise<boolean> => {
|
||||
if (!api || !itemId || !userId) {
|
||||
console.error("Invalid parameters for markAsNotPlayed");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.axiosInstance.delete(
|
||||
`${api.basePath}/UserPlayedItems/${itemId}`,
|
||||
{
|
||||
params: { userId },
|
||||
headers: {
|
||||
Authorization: `MediaBrowser DeviceId="${api.deviceInfo.id}", Token="${api.accessToken}"`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
const axiosError = error as AxiosError;
|
||||
console.error(
|
||||
"Failed to mark item as not played:",
|
||||
axiosError.message,
|
||||
axiosError.response?.status,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
50
utils/jellyfin/playstate/markAsPlayed.ts
Normal file
50
utils/jellyfin/playstate/markAsPlayed.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { AxiosError } from "axios";
|
||||
import { getAuthHeaders } from "../jellyfin";
|
||||
|
||||
interface MarkAsPlayedParams {
|
||||
api: Api | null | undefined;
|
||||
item: BaseItemDto | null | undefined;
|
||||
userId: string | null | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a media item as played and updates its progress to completion.
|
||||
*
|
||||
* @param params - The parameters for marking an item as played
|
||||
* @returns A promise that resolves to true if the operation was successful, false otherwise
|
||||
*/
|
||||
export const markAsPlayed = async ({
|
||||
api,
|
||||
item,
|
||||
userId,
|
||||
}: MarkAsPlayedParams): Promise<boolean> => {
|
||||
if (!api || !item?.Id || !userId || !item.RunTimeTicks) {
|
||||
console.error("Invalid parameters for markAsPlayed");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const [playedResponse, progressResponse] = await Promise.all([
|
||||
api.axiosInstance.post(
|
||||
`${api.basePath}/UserPlayedItems/${item.Id}`,
|
||||
{ userId, datePlayed: new Date().toISOString() },
|
||||
{ headers: getAuthHeaders(api) },
|
||||
),
|
||||
api.axiosInstance.post(
|
||||
`${api.basePath}/Sessions/Playing/Progress`,
|
||||
{
|
||||
ItemId: item.Id,
|
||||
PositionTicks: item.RunTimeTicks,
|
||||
MediaSourceId: item.Id,
|
||||
},
|
||||
{ headers: getAuthHeaders(api) },
|
||||
),
|
||||
]);
|
||||
|
||||
return playedResponse.status === 200 && progressResponse.status === 200;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
44
utils/jellyfin/playstate/reportPlaybackProgress.ts
Normal file
44
utils/jellyfin/playstate/reportPlaybackProgress.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { AxiosError } from "axios";
|
||||
import { getAuthHeaders } from "../jellyfin";
|
||||
|
||||
interface ReportPlaybackProgressParams {
|
||||
api: Api | null | undefined;
|
||||
sessionId: string | null | undefined;
|
||||
itemId: string | null | undefined;
|
||||
positionTicks: number | null | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports playback progress to the Jellyfin server.
|
||||
*
|
||||
* @param params - The parameters for reporting playback progress
|
||||
* @throws {Error} If any required parameter is missing
|
||||
*/
|
||||
export const reportPlaybackProgress = async ({
|
||||
api,
|
||||
sessionId,
|
||||
itemId,
|
||||
positionTicks,
|
||||
}: ReportPlaybackProgressParams): Promise<void> => {
|
||||
if (!api || !sessionId || !itemId || positionTicks == null) {
|
||||
throw new Error("Missing required parameters for reportPlaybackProgress");
|
||||
}
|
||||
|
||||
try {
|
||||
await api.axiosInstance.post(
|
||||
`${api.basePath}/Sessions/Playing/Progress`,
|
||||
{
|
||||
ItemId: itemId,
|
||||
PlaySessionId: sessionId,
|
||||
IsPaused: false,
|
||||
PositionTicks: Math.round(positionTicks),
|
||||
CanSeek: true,
|
||||
MediaSourceId: itemId,
|
||||
},
|
||||
{ headers: getAuthHeaders(api) },
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
61
utils/jellyfin/playstate/reportPlaybackStopped.ts
Normal file
61
utils/jellyfin/playstate/reportPlaybackStopped.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { AxiosError } from "axios";
|
||||
import { getAuthHeaders } from "../jellyfin";
|
||||
|
||||
interface PlaybackStoppedParams {
|
||||
api: Api | null | undefined;
|
||||
sessionId: string | null | undefined;
|
||||
itemId: string | null | undefined;
|
||||
positionTicks: number | null | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports playback stopped event to the Jellyfin server.
|
||||
*
|
||||
* @param {PlaybackStoppedParams} params - The parameters for the report.
|
||||
* @param {Api} params.api - The Jellyfin API instance.
|
||||
* @param {string} params.sessionId - The session ID.
|
||||
* @param {string} params.itemId - The item ID.
|
||||
* @param {number} params.positionTicks - The playback position in ticks.
|
||||
*/
|
||||
export const reportPlaybackStopped = async ({
|
||||
api,
|
||||
sessionId,
|
||||
itemId,
|
||||
positionTicks,
|
||||
}: PlaybackStoppedParams): Promise<void> => {
|
||||
// Validate input parameters
|
||||
if (!api || !sessionId || !itemId || !positionTicks) {
|
||||
console.log("Missing required parameters", {
|
||||
api,
|
||||
sessionId,
|
||||
itemId,
|
||||
positionTicks,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = `${api.basePath}/PlayingItems/${itemId}`;
|
||||
const params = {
|
||||
playSessionId: sessionId,
|
||||
positionTicks: Math.round(positionTicks),
|
||||
mediaSourceId: itemId,
|
||||
};
|
||||
const headers = getAuthHeaders(api);
|
||||
|
||||
// Send DELETE request to report playback stopped
|
||||
await api.axiosInstance.delete(url, { params, headers });
|
||||
} catch (error) {
|
||||
// Log the error with additional context
|
||||
if (error instanceof AxiosError) {
|
||||
console.error(
|
||||
"Failed to report playback progress",
|
||||
error.message,
|
||||
error.response?.data,
|
||||
);
|
||||
} else {
|
||||
console.error("Failed to report playback progress", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
45
utils/jellyfin/tvshows/nextUp.ts
Normal file
45
utils/jellyfin/tvshows/nextUp.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { AxiosError } from "axios";
|
||||
import { getAuthHeaders } from "../jellyfin";
|
||||
|
||||
interface NextUpParams {
|
||||
itemId?: string | null;
|
||||
userId?: string | null;
|
||||
api?: Api | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the next up episodes for a series or all series for a user.
|
||||
*
|
||||
* @param params - The parameters for fetching next up episodes
|
||||
* @returns A promise that resolves to an array of BaseItemDto representing the next up episodes
|
||||
*/
|
||||
export const nextUp = async ({
|
||||
itemId,
|
||||
userId,
|
||||
api,
|
||||
}: NextUpParams): Promise<BaseItemDto[]> => {
|
||||
if (!userId || !api) {
|
||||
console.error("Invalid parameters for nextUp: missing userId or api");
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.axiosInstance.get<{ Items: BaseItemDto[] }>(
|
||||
`${api.basePath}/Shows/NextUp`,
|
||||
{
|
||||
params: {
|
||||
SeriesId: itemId || undefined,
|
||||
UserId: userId,
|
||||
Fields: "MediaSourceCount",
|
||||
},
|
||||
headers: getAuthHeaders(api),
|
||||
},
|
||||
);
|
||||
|
||||
return response.data.Items;
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user