Files
biliup/app/lib/api-streamer.ts
T
Noah 40234133e3 fix(webui): 保存配置覆写时保留投稿模板关联 (#1685)
覆写弹窗的 entity 白名单漏了 upload_streamers_id,PUT 整行覆盖后外键变 NULL,后续录像不再投稿并走默认 rm。
2026-09-13 15:40:03 +00:00

164 lines
3.8 KiB
TypeScript

// Fetcher implementation. // The extra argument will be passed via the `arg` property of the 2nd parameter.// In the example below, `arg` will be `'my_token'`
export const API_BASE = process.env.NEXT_PUBLIC_API_SERVER ?? '';
export async function sendRequest<T>(url: string, { arg }: { arg: T }) {
const res = await fetch(API_BASE + url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(arg),
});
await handleResponse(res);
return res.json();
}
export const fetcher = async (input: RequestInfo | URL, init?: RequestInit) => {
const res = await fetch(API_BASE + input, init);
await handleResponse(res);
return res.json();
};
export const proxy = async (input: RequestInfo | URL, init?: RequestInit) => {
const res = await fetch(API_BASE + input, init);
await handleResponse(res);
return res;
};
export async function requestDelete<T>(url: string, { arg }: { arg: T }) {
const res = await fetch(`${API_BASE}${url}/${arg}`, { method: 'DELETE' });
await handleResponse(res);
return res;
}
export async function put<T>(url: string, { arg }: { arg: T }) {
const res = await fetch(`${API_BASE}${url}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(arg),
});
await handleResponse(res);
return res;
}
async function handleResponse(res: Response) {
// 如果未登录,统一跳转
if (res.status === 401) {
// 可选:清理本地状态/缓存
// localStorage.removeItem('token') 等
// 跳转登录(带回跳)
const returnTo = encodeURIComponent(window.location.pathname + window.location.search);
window.location.href = `/login?next=${returnTo}`;
// 抛错让 SWR 知道失败(别返回 json)
throw new Error('Unauthorized');
}
if (!res.ok) {
// 尽量返回服务端错误信息
const text = await res.text().catch(() => '');
throw new Error(text || `HTTP ${res.status}`);
}
return res;
}
type Credit = {
username: string;
uid: number;
};
export interface StudioEntity {
id: number;
template_name: string;
user_cookie: string;
copyright: number;
copyright_source: string;
tid: number;
cover_path: string;
title: string;
description: string;
dynamic: string;
tags: string[];
dtime: number;
// interactive: number;
mission_id?: number;
dolby: number;
hires: number;
no_reprint: number;
is_only_self: number;
up_selection_reply: number;
up_close_reply: number;
up_close_danmu: number;
charging_pay: number;
credits: Credit[];
uploader: string;
extra_fields?: string;
}
export interface LiveStreamerEntity {
id: number;
url: string;
remark: string;
filename: string;
split_time?: number;
split_size?: number;
filename_prefix?: string;
upload_id?: number;
upload_streamers_id?: number | null;
status?: string;
upload_status?: string;
statusTag?: React.ReactNode;
format?: string;
time_range?: string | Date[];
excluded_keywords?: string[];
preprocessor?: Record<'run', string>[];
segment_processor?: Record<'run', string>[];
downloaded_processor?: Record<'run', string>[];
postprocessor?: (Record<'run' | 'mv', string> | 'rm')[];
opt_args?: string[];
override?: Record<string, any>;
}
export interface BiliType {
id: number;
children: BiliType[];
name: string;
desc: string;
}
export interface User {
id: number;
name: string;
value: string;
platform: string;
}
export interface BiliArchive {
aid: number;
bvid: string;
title: string;
cover: string;
reject_reason: string;
reject_reason_url: string;
duration: number;
desc: string;
state: number;
state_desc: string;
dtime: number;
ptime: number;
ctime: number;
}
export interface BiliArchivePage {
from_page: number;
page_size: number;
total: number;
total_pages: number;
fetched_pages: number;
archives: BiliArchive[];
}
export interface FileList {
key: number;
name: string;
updateTime: number;
size: number;
}