mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 15:03:26 +00:00
Compare commits
1 Commits
9694630cdf
...
bd8a4394ea
Author | SHA1 | Date | |
---|---|---|---|
|
bd8a4394ea |
@@ -1,6 +1,17 @@
|
|||||||
import { ofetch } from "ofetch";
|
import { ofetch } from "ofetch";
|
||||||
|
|
||||||
import type { LoginResponse } from "./types";
|
export interface SessionResponse {
|
||||||
|
id: string;
|
||||||
|
userId: string;
|
||||||
|
createdAt: string;
|
||||||
|
accessedAt: string;
|
||||||
|
device: string;
|
||||||
|
userAgent: string;
|
||||||
|
}
|
||||||
|
export interface LoginResponse {
|
||||||
|
session: SessionResponse;
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
export function getAuthHeaders(token: string): Record<string, string> {
|
export function getAuthHeaders(token: string): Record<string, string> {
|
||||||
return {
|
return {
|
||||||
|
@@ -1,55 +0,0 @@
|
|||||||
import { ofetch } from "ofetch";
|
|
||||||
|
|
||||||
import type {
|
|
||||||
AccountWithToken,
|
|
||||||
BookmarkInput,
|
|
||||||
BookmarkMediaItem,
|
|
||||||
BookmarkResponse,
|
|
||||||
} from "./types";
|
|
||||||
import { getAuthHeaders } from "./auth";
|
|
||||||
|
|
||||||
export function bookmarkMediaToInput(
|
|
||||||
tmdbId: string,
|
|
||||||
item: BookmarkMediaItem,
|
|
||||||
): BookmarkInput {
|
|
||||||
return {
|
|
||||||
meta: {
|
|
||||||
title: item.title,
|
|
||||||
type: item.type,
|
|
||||||
poster: item.poster,
|
|
||||||
year: item.year ?? 0,
|
|
||||||
},
|
|
||||||
tmdbId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function addBookmark(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
input: BookmarkInput,
|
|
||||||
) {
|
|
||||||
return ofetch<BookmarkResponse>(
|
|
||||||
`/users/${account.userId}/bookmarks/${input.tmdbId}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
baseURL: url,
|
|
||||||
body: input,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeBookmark(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
id: string,
|
|
||||||
) {
|
|
||||||
return ofetch<{ tmdbId: string }>(
|
|
||||||
`/users/${account.userId}/bookmarks/${id}`,
|
|
||||||
{
|
|
||||||
method: "DELETE",
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
baseURL: url,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
@@ -1,30 +0,0 @@
|
|||||||
import { ofetch } from "ofetch";
|
|
||||||
|
|
||||||
import type { AccountWithToken, BookmarkInput, ProgressInput } from "./types";
|
|
||||||
import { getAuthHeaders } from "./auth";
|
|
||||||
|
|
||||||
export function importProgress(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
progressItems: ProgressInput[],
|
|
||||||
) {
|
|
||||||
return ofetch<void>(`/users/${account.userId}/progress/import`, {
|
|
||||||
method: "PUT",
|
|
||||||
body: progressItems,
|
|
||||||
baseURL: url,
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function importBookmarks(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
bookmarks: BookmarkInput[],
|
|
||||||
) {
|
|
||||||
return ofetch<void>(`/users/${account.userId}/bookmarks`, {
|
|
||||||
method: "PUT",
|
|
||||||
body: bookmarks,
|
|
||||||
baseURL: url,
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
});
|
|
||||||
}
|
|
@@ -1,13 +1,3 @@
|
|||||||
export const name = "api";
|
export const name = "api";
|
||||||
export * from "./auth";
|
export * from "./auth";
|
||||||
export * from "./bookmarks";
|
|
||||||
export * from "./crypto";
|
export * from "./crypto";
|
||||||
export * from "./import";
|
|
||||||
export * from "./login";
|
|
||||||
export * from "./meta";
|
|
||||||
export * from "./progress";
|
|
||||||
export * from "./register";
|
|
||||||
export * from "./sessions";
|
|
||||||
export * from "./settings";
|
|
||||||
export * from "./types";
|
|
||||||
export * from "./user";
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import { ofetch } from "ofetch";
|
import { ofetch } from "ofetch";
|
||||||
|
|
||||||
import type {
|
import type { SessionResponse } from "./auth";
|
||||||
ChallengeTokenResponse,
|
|
||||||
LoginInput,
|
export interface ChallengeTokenResponse {
|
||||||
LoginResponse,
|
challenge: string;
|
||||||
} from "./types";
|
}
|
||||||
|
|
||||||
export async function getLoginChallengeToken(
|
export async function getLoginChallengeToken(
|
||||||
url: string,
|
url: string,
|
||||||
@@ -19,6 +19,20 @@ export async function getLoginChallengeToken(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LoginResponse {
|
||||||
|
session: SessionResponse;
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoginInput {
|
||||||
|
publicKey: string;
|
||||||
|
challenge: {
|
||||||
|
code: string;
|
||||||
|
signature: string;
|
||||||
|
};
|
||||||
|
device: string;
|
||||||
|
}
|
||||||
|
|
||||||
export async function loginAccount(
|
export async function loginAccount(
|
||||||
url: string,
|
url: string,
|
||||||
data: LoginInput,
|
data: LoginInput,
|
||||||
|
@@ -1,6 +1,12 @@
|
|||||||
import { ofetch } from "ofetch";
|
import { ofetch } from "ofetch";
|
||||||
|
|
||||||
import type { MetaResponse } from "./types";
|
export interface MetaResponse {
|
||||||
|
version: string;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
hasCaptcha: boolean;
|
||||||
|
captchaClientKey?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getBackendMeta(url: string): Promise<MetaResponse> {
|
export async function getBackendMeta(url: string): Promise<MetaResponse> {
|
||||||
return ofetch<MetaResponse>("/meta", {
|
return ofetch<MetaResponse>("/meta", {
|
||||||
|
@@ -1,102 +0,0 @@
|
|||||||
import { ofetch } from "ofetch";
|
|
||||||
|
|
||||||
import type {
|
|
||||||
AccountWithToken,
|
|
||||||
ProgressInput,
|
|
||||||
ProgressMediaItem,
|
|
||||||
ProgressResponse,
|
|
||||||
ProgressUpdateItem,
|
|
||||||
} from "./types";
|
|
||||||
import { getAuthHeaders } from "./auth";
|
|
||||||
|
|
||||||
export function progressUpdateItemToInput(
|
|
||||||
item: ProgressUpdateItem,
|
|
||||||
): ProgressInput {
|
|
||||||
return {
|
|
||||||
duration: item.progress?.duration ?? 0,
|
|
||||||
watched: item.progress?.watched ?? 0,
|
|
||||||
tmdbId: item.tmdbId,
|
|
||||||
meta: {
|
|
||||||
title: item.title ?? "",
|
|
||||||
type: item.type ?? "",
|
|
||||||
year: item.year ?? NaN,
|
|
||||||
poster: item.poster,
|
|
||||||
},
|
|
||||||
episodeId: item.episodeId,
|
|
||||||
seasonId: item.seasonId,
|
|
||||||
episodeNumber: item.episodeNumber,
|
|
||||||
seasonNumber: item.seasonNumber,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function progressMediaItemToInputs(
|
|
||||||
tmdbId: string,
|
|
||||||
item: ProgressMediaItem,
|
|
||||||
): ProgressInput[] {
|
|
||||||
if (item.type === "show") {
|
|
||||||
return Object.entries(item.episodes).flatMap(([_, episode]) => ({
|
|
||||||
duration: item.progress?.duration ?? episode.progress.duration,
|
|
||||||
watched: item.progress?.watched ?? episode.progress.watched,
|
|
||||||
tmdbId,
|
|
||||||
meta: {
|
|
||||||
title: item.title ?? "",
|
|
||||||
type: item.type ?? "",
|
|
||||||
year: item.year ?? NaN,
|
|
||||||
poster: item.poster,
|
|
||||||
},
|
|
||||||
episodeId: episode.id,
|
|
||||||
seasonId: episode.seasonId,
|
|
||||||
episodeNumber: episode.number,
|
|
||||||
seasonNumber: item.seasons[episode.seasonId]?.number,
|
|
||||||
updatedAt: new Date(episode.updatedAt).toISOString(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
duration: item.progress?.duration ?? 0,
|
|
||||||
watched: item.progress?.watched ?? 0,
|
|
||||||
tmdbId,
|
|
||||||
updatedAt: new Date(item.updatedAt).toISOString(),
|
|
||||||
meta: {
|
|
||||||
title: item.title ?? "",
|
|
||||||
type: item.type ?? "",
|
|
||||||
year: item.year ?? NaN,
|
|
||||||
poster: item.poster,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function setProgress(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
input: ProgressInput,
|
|
||||||
) {
|
|
||||||
return ofetch<ProgressResponse>(
|
|
||||||
`/users/${account.userId}/progress/${input.tmdbId}`,
|
|
||||||
{
|
|
||||||
method: "PUT",
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
baseURL: url,
|
|
||||||
body: input,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeProgress(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
id: string,
|
|
||||||
episodeId?: string,
|
|
||||||
seasonId?: string,
|
|
||||||
) {
|
|
||||||
await ofetch(`/users/${account.userId}/progress/${id}`, {
|
|
||||||
method: "DELETE",
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
baseURL: url,
|
|
||||||
body: {
|
|
||||||
episodeId,
|
|
||||||
seasonId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
@@ -1,41 +0,0 @@
|
|||||||
import { ofetch } from "ofetch";
|
|
||||||
|
|
||||||
import type {
|
|
||||||
ChallengeTokenResponse,
|
|
||||||
RegisterInput,
|
|
||||||
SessionResponse,
|
|
||||||
UserResponse,
|
|
||||||
} from "./types";
|
|
||||||
|
|
||||||
export async function getRegisterChallengeToken(
|
|
||||||
url: string,
|
|
||||||
captchaToken?: string,
|
|
||||||
): Promise<ChallengeTokenResponse> {
|
|
||||||
return ofetch<ChallengeTokenResponse>("/auth/register/start", {
|
|
||||||
method: "POST",
|
|
||||||
body: {
|
|
||||||
captchaToken,
|
|
||||||
},
|
|
||||||
baseURL: url,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RegisterResponse {
|
|
||||||
user: UserResponse;
|
|
||||||
session: SessionResponse;
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function registerAccount(
|
|
||||||
url: string,
|
|
||||||
data: RegisterInput,
|
|
||||||
): Promise<RegisterResponse> {
|
|
||||||
return ofetch<RegisterResponse>("/auth/register/complete", {
|
|
||||||
method: "POST",
|
|
||||||
body: {
|
|
||||||
namespace: "movie-web",
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
baseURL: url,
|
|
||||||
});
|
|
||||||
}
|
|
@@ -1,8 +1,36 @@
|
|||||||
import { ofetch } from "ofetch";
|
import { ofetch } from "ofetch";
|
||||||
|
|
||||||
import type { AccountWithToken, SessionResponse, SessionUpdate } from "./types";
|
|
||||||
import { getAuthHeaders } from "./auth";
|
import { getAuthHeaders } from "./auth";
|
||||||
|
|
||||||
|
export interface SessionResponse {
|
||||||
|
id: string;
|
||||||
|
userId: string;
|
||||||
|
createdAt: string;
|
||||||
|
accessedAt: string;
|
||||||
|
device: string;
|
||||||
|
userAgent: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SessionUpdate {
|
||||||
|
deviceName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Account {
|
||||||
|
profile: {
|
||||||
|
colorA: string;
|
||||||
|
colorB: string;
|
||||||
|
icon: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AccountWithToken = Account & {
|
||||||
|
sessionId: string;
|
||||||
|
userId: string;
|
||||||
|
token: string;
|
||||||
|
seed: string;
|
||||||
|
deviceName: string;
|
||||||
|
};
|
||||||
|
|
||||||
export async function getSessions(url: string, account: AccountWithToken) {
|
export async function getSessions(url: string, account: AccountWithToken) {
|
||||||
return ofetch<SessionResponse[]>(`/users/${account.userId}/sessions`, {
|
return ofetch<SessionResponse[]>(`/users/${account.userId}/sessions`, {
|
||||||
headers: getAuthHeaders(account.token),
|
headers: getAuthHeaders(account.token),
|
||||||
|
@@ -1,12 +1,22 @@
|
|||||||
import { ofetch } from "ofetch";
|
import { ofetch } from "ofetch";
|
||||||
|
|
||||||
import type {
|
import type { AccountWithToken } from "./sessions";
|
||||||
AccountWithToken,
|
|
||||||
SettingsInput,
|
|
||||||
SettingsResponse,
|
|
||||||
} from "./types";
|
|
||||||
import { getAuthHeaders } from "./auth";
|
import { getAuthHeaders } from "./auth";
|
||||||
|
|
||||||
|
export interface SettingsInput {
|
||||||
|
applicationLanguage?: string;
|
||||||
|
applicationTheme?: string | null;
|
||||||
|
defaultSubtitleLanguage?: string;
|
||||||
|
proxyUrls?: string[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SettingsResponse {
|
||||||
|
applicationTheme?: string | null;
|
||||||
|
applicationLanguage?: string | null;
|
||||||
|
defaultSubtitleLanguage?: string | null;
|
||||||
|
proxyUrls?: string[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
export function updateSettings(
|
export function updateSettings(
|
||||||
url: string,
|
url: string,
|
||||||
account: AccountWithToken,
|
account: AccountWithToken,
|
||||||
|
@@ -1,231 +0,0 @@
|
|||||||
export interface SessionResponse {
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
createdAt: string;
|
|
||||||
accessedAt: string;
|
|
||||||
device: string;
|
|
||||||
userAgent: string;
|
|
||||||
}
|
|
||||||
export interface LoginResponse {
|
|
||||||
session: SessionResponse;
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BookmarkMetaInput {
|
|
||||||
title: string;
|
|
||||||
year: number;
|
|
||||||
poster?: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BookmarkInput {
|
|
||||||
tmdbId: string;
|
|
||||||
meta: BookmarkMetaInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChallengeTokenResponse {
|
|
||||||
challenge: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LoginResponse {
|
|
||||||
session: SessionResponse;
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LoginInput {
|
|
||||||
publicKey: string;
|
|
||||||
challenge: {
|
|
||||||
code: string;
|
|
||||||
signature: string;
|
|
||||||
};
|
|
||||||
device: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MetaResponse {
|
|
||||||
version: string;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
hasCaptcha: boolean;
|
|
||||||
captchaClientKey?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RegisterInput {
|
|
||||||
publicKey: string;
|
|
||||||
challenge: {
|
|
||||||
code: string;
|
|
||||||
signature: string;
|
|
||||||
};
|
|
||||||
device: string;
|
|
||||||
profile: {
|
|
||||||
colorA: string;
|
|
||||||
colorB: string;
|
|
||||||
icon: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProgressInput {
|
|
||||||
meta?: {
|
|
||||||
title: string;
|
|
||||||
year: number;
|
|
||||||
poster?: string;
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
tmdbId: string;
|
|
||||||
watched: number;
|
|
||||||
duration: number;
|
|
||||||
seasonId?: string;
|
|
||||||
episodeId?: string;
|
|
||||||
seasonNumber?: number;
|
|
||||||
episodeNumber?: number;
|
|
||||||
updatedAt?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SessionResponse {
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
createdAt: string;
|
|
||||||
accessedAt: string;
|
|
||||||
device: string;
|
|
||||||
userAgent: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SessionUpdate {
|
|
||||||
deviceName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Account {
|
|
||||||
profile: {
|
|
||||||
colorA: string;
|
|
||||||
colorB: string;
|
|
||||||
icon: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AccountWithToken = Account & {
|
|
||||||
sessionId: string;
|
|
||||||
userId: string;
|
|
||||||
token: string;
|
|
||||||
seed: string;
|
|
||||||
deviceName: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface SettingsInput {
|
|
||||||
applicationLanguage?: string;
|
|
||||||
applicationTheme?: string | null;
|
|
||||||
defaultSubtitleLanguage?: string;
|
|
||||||
proxyUrls?: string[] | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SettingsResponse {
|
|
||||||
applicationTheme?: string | null;
|
|
||||||
applicationLanguage?: string | null;
|
|
||||||
defaultSubtitleLanguage?: string | null;
|
|
||||||
proxyUrls?: string[] | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserResponse {
|
|
||||||
id: string;
|
|
||||||
namespace: string;
|
|
||||||
name: string;
|
|
||||||
roles: string[];
|
|
||||||
createdAt: string;
|
|
||||||
profile: {
|
|
||||||
colorA: string;
|
|
||||||
colorB: string;
|
|
||||||
icon: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserEdit {
|
|
||||||
profile?: {
|
|
||||||
colorA: string;
|
|
||||||
colorB: string;
|
|
||||||
icon: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BookmarkMediaItem {
|
|
||||||
title: string;
|
|
||||||
year?: number;
|
|
||||||
poster?: string;
|
|
||||||
type: "show" | "movie";
|
|
||||||
updatedAt: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BookmarkResponse {
|
|
||||||
tmdbId: string;
|
|
||||||
meta: {
|
|
||||||
title: string;
|
|
||||||
year: number;
|
|
||||||
poster?: string;
|
|
||||||
type: "show" | "movie";
|
|
||||||
};
|
|
||||||
updatedAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProgressItem {
|
|
||||||
watched: number;
|
|
||||||
duration: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProgressSeasonItem {
|
|
||||||
title: string;
|
|
||||||
number: number;
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProgressEpisodeItem {
|
|
||||||
title: string;
|
|
||||||
number: number;
|
|
||||||
id: string;
|
|
||||||
seasonId: string;
|
|
||||||
updatedAt: number;
|
|
||||||
progress: ProgressItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProgressMediaItem {
|
|
||||||
title: string;
|
|
||||||
year?: number;
|
|
||||||
poster?: string;
|
|
||||||
type: "show" | "movie";
|
|
||||||
progress?: ProgressItem;
|
|
||||||
updatedAt: number;
|
|
||||||
seasons: Record<string, ProgressSeasonItem>;
|
|
||||||
episodes: Record<string, ProgressEpisodeItem>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProgressUpdateItem {
|
|
||||||
title?: string;
|
|
||||||
year?: number;
|
|
||||||
poster?: string;
|
|
||||||
type?: "show" | "movie";
|
|
||||||
progress?: ProgressItem;
|
|
||||||
tmdbId: string;
|
|
||||||
id: string;
|
|
||||||
episodeId?: string;
|
|
||||||
seasonId?: string;
|
|
||||||
episodeNumber?: number;
|
|
||||||
seasonNumber?: number;
|
|
||||||
action: "upsert" | "delete";
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProgressResponse {
|
|
||||||
tmdbId: string;
|
|
||||||
season: {
|
|
||||||
id?: string;
|
|
||||||
number?: number;
|
|
||||||
};
|
|
||||||
episode: {
|
|
||||||
id?: string;
|
|
||||||
number?: number;
|
|
||||||
};
|
|
||||||
meta: {
|
|
||||||
title: string;
|
|
||||||
year: number;
|
|
||||||
poster?: string;
|
|
||||||
type: "show" | "movie";
|
|
||||||
};
|
|
||||||
duration: string;
|
|
||||||
watched: string;
|
|
||||||
updatedAt: string;
|
|
||||||
}
|
|
@@ -1,133 +0,0 @@
|
|||||||
import { ofetch } from "ofetch";
|
|
||||||
|
|
||||||
import type {
|
|
||||||
AccountWithToken,
|
|
||||||
BookmarkMediaItem,
|
|
||||||
BookmarkResponse,
|
|
||||||
ProgressMediaItem,
|
|
||||||
ProgressResponse,
|
|
||||||
SessionResponse,
|
|
||||||
UserEdit,
|
|
||||||
UserResponse,
|
|
||||||
} from "./types";
|
|
||||||
import { getAuthHeaders } from "./auth";
|
|
||||||
|
|
||||||
export function bookmarkResponsesToEntries(responses: BookmarkResponse[]) {
|
|
||||||
const entries = responses.map((bookmark) => {
|
|
||||||
const item: BookmarkMediaItem = {
|
|
||||||
...bookmark.meta,
|
|
||||||
updatedAt: new Date(bookmark.updatedAt).getTime(),
|
|
||||||
};
|
|
||||||
return [bookmark.tmdbId, item] as const;
|
|
||||||
});
|
|
||||||
|
|
||||||
return Object.fromEntries(entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function progressResponsesToEntries(responses: ProgressResponse[]) {
|
|
||||||
const items: Record<string, ProgressMediaItem> = {};
|
|
||||||
|
|
||||||
responses.forEach((v) => {
|
|
||||||
if (!items[v.tmdbId]) {
|
|
||||||
items[v.tmdbId] = {
|
|
||||||
title: v.meta.title,
|
|
||||||
poster: v.meta.poster,
|
|
||||||
type: v.meta.type,
|
|
||||||
updatedAt: new Date(v.updatedAt).getTime(),
|
|
||||||
episodes: {},
|
|
||||||
seasons: {},
|
|
||||||
year: v.meta.year,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const item = items[v.tmdbId];
|
|
||||||
if (!item) return;
|
|
||||||
|
|
||||||
// Since each watched episode is a single array entry but with the same tmdbId, the root item updatedAt will only have the first episode's timestamp (which is not the newest).
|
|
||||||
// Here, we are setting it explicitly so the updatedAt always has the highest updatedAt from the episodes.
|
|
||||||
if (new Date(v.updatedAt).getTime() > item.updatedAt) {
|
|
||||||
item.updatedAt = new Date(v.updatedAt).getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type === "movie") {
|
|
||||||
item.progress = {
|
|
||||||
duration: Number(v.duration),
|
|
||||||
watched: Number(v.watched),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type === "show" && v.season.id && v.episode.id) {
|
|
||||||
item.seasons[v.season.id] = {
|
|
||||||
id: v.season.id,
|
|
||||||
number: v.season.number ?? 0,
|
|
||||||
title: "",
|
|
||||||
};
|
|
||||||
item.episodes[v.episode.id] = {
|
|
||||||
id: v.episode.id,
|
|
||||||
number: v.episode.number ?? 0,
|
|
||||||
title: "",
|
|
||||||
progress: {
|
|
||||||
duration: Number(v.duration),
|
|
||||||
watched: Number(v.watched),
|
|
||||||
},
|
|
||||||
seasonId: v.season.id,
|
|
||||||
updatedAt: new Date(v.updatedAt).getTime(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getUser(
|
|
||||||
url: string,
|
|
||||||
token: string,
|
|
||||||
): Promise<{ user: UserResponse; session: SessionResponse }> {
|
|
||||||
return ofetch<{ user: UserResponse; session: SessionResponse }>(
|
|
||||||
"/users/@me",
|
|
||||||
{
|
|
||||||
headers: getAuthHeaders(token),
|
|
||||||
baseURL: url,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function editUser(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
object: UserEdit,
|
|
||||||
): Promise<{ user: UserResponse; session: SessionResponse }> {
|
|
||||||
return ofetch<{ user: UserResponse; session: SessionResponse }>(
|
|
||||||
`/users/${account.userId}`,
|
|
||||||
{
|
|
||||||
method: "PATCH",
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
body: object,
|
|
||||||
baseURL: url,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deleteUser(
|
|
||||||
url: string,
|
|
||||||
account: AccountWithToken,
|
|
||||||
): Promise<UserResponse> {
|
|
||||||
return ofetch<UserResponse>(`/users/${account.userId}`, {
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
baseURL: url,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getBookmarks(url: string, account: AccountWithToken) {
|
|
||||||
return ofetch<BookmarkResponse[]>(`/users/${account.userId}/bookmarks`, {
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
baseURL: url,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getProgress(url: string, account: AccountWithToken) {
|
|
||||||
return ofetch<ProgressResponse[]>(`/users/${account.userId}/progress`, {
|
|
||||||
headers: getAuthHeaders(account.token),
|
|
||||||
baseURL: url,
|
|
||||||
});
|
|
||||||
}
|
|
Reference in New Issue
Block a user