178 lines
4.7 KiB
TypeScript
178 lines
4.7 KiB
TypeScript
import { ARTALK_SERVER, ARTALK_SITE } from "./config";
|
|
|
|
// Artalk API v2 types
|
|
export interface ArtalkComment {
|
|
id: number;
|
|
content: string;
|
|
nick: string;
|
|
email: string;
|
|
page_key: string;
|
|
page_title: string;
|
|
user_id: number;
|
|
ua: string;
|
|
ip: string;
|
|
is_collapsed: boolean;
|
|
is_pending: boolean;
|
|
is_pinned: boolean;
|
|
vote_up: number;
|
|
vote_down: number;
|
|
rid: number;
|
|
date: string;
|
|
updated_at: string;
|
|
badge_word?: string;
|
|
is_allow_reply?: boolean;
|
|
children?: ArtalkComment[];
|
|
}
|
|
|
|
export interface ArtalkPage {
|
|
id: number;
|
|
admin_only: boolean;
|
|
key: string;
|
|
title: string;
|
|
url: string;
|
|
view: number;
|
|
comment_count: number;
|
|
date: string;
|
|
}
|
|
|
|
let authToken: string | null = null;
|
|
|
|
export function setAuthToken(token: string | null) {
|
|
authToken = token;
|
|
}
|
|
|
|
export function getAuthToken(): string | null {
|
|
return authToken;
|
|
}
|
|
|
|
export async function login(
|
|
email: string,
|
|
password: string
|
|
): Promise<{ token: string; user: { name: string; email: string } }> {
|
|
const url = `${ARTALK_SERVER}/api/v2/auth/email/login`;
|
|
const res = await fetch(url, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ email, password }),
|
|
});
|
|
|
|
const json = await res.json();
|
|
|
|
if (!json || !json.token) {
|
|
throw new Error(json.msg || "登录失败");
|
|
}
|
|
|
|
authToken = json.token as string;
|
|
return { token: authToken, user: json.user };
|
|
}
|
|
|
|
export async function getPages(options?: {
|
|
offset?: number;
|
|
limit?: number;
|
|
type?: "all" | "admin_only";
|
|
}): Promise<{ pages: ArtalkPage[]; total: number }> {
|
|
const { offset = 0, limit = 50, type = "all" } = options || {};
|
|
|
|
const params = new URLSearchParams({
|
|
site_name: ARTALK_SITE,
|
|
offset: offset.toString(),
|
|
limit: limit.toString(),
|
|
type,
|
|
});
|
|
|
|
const url = `${ARTALK_SERVER}/api/v2/pages?${params.toString()}`;
|
|
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
if (authToken) headers["Authorization"] = `Bearer ${authToken}`;
|
|
|
|
const res = await fetch(url, { headers });
|
|
const json = await res.json();
|
|
|
|
if (json.msg && !json.pages && !json.count) {
|
|
throw new Error(json.msg);
|
|
}
|
|
|
|
return { pages: json.pages || json.data || [], total: json.count || json.total || 0 };
|
|
}
|
|
|
|
export async function getComments(
|
|
pageKey: string,
|
|
options?: { offset?: number; limit?: number }
|
|
): Promise<{ comments: ArtalkComment[]; total: number }> {
|
|
const { offset = 0, limit = 100 } = options || {};
|
|
|
|
const params = new URLSearchParams({
|
|
site_name: ARTALK_SITE,
|
|
page_key: pageKey,
|
|
offset: offset.toString(),
|
|
limit: limit.toString(),
|
|
flat_mode: "true",
|
|
sort_by: "date_desc",
|
|
});
|
|
|
|
const url = `${ARTALK_SERVER}/api/v2/comments?${params.toString()}`;
|
|
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
if (authToken) headers["Authorization"] = `Bearer ${authToken}`;
|
|
|
|
const res = await fetch(url, { headers });
|
|
const json = await res.json();
|
|
|
|
if (json.msg && !json.comments && !json.count) {
|
|
throw new Error(json.msg);
|
|
}
|
|
|
|
return { comments: json.comments || json.data || [], total: json.count || json.total || 0 };
|
|
}
|
|
|
|
async function artalkMutate<T>(endpoint: string, method: string, body: Record<string, unknown>): Promise<T> {
|
|
const url = `${ARTALK_SERVER}${endpoint}`;
|
|
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
if (authToken) headers["Authorization"] = `Bearer ${authToken}`;
|
|
|
|
const res = await fetch(url, { method, headers, body: JSON.stringify(body) });
|
|
const json = await res.json();
|
|
|
|
if (json.msg) {
|
|
throw new Error(json.msg);
|
|
}
|
|
return (json.data || json) as T;
|
|
}
|
|
|
|
export async function updateComment(
|
|
id: number,
|
|
data: {
|
|
content?: string;
|
|
is_collapsed?: boolean;
|
|
is_pending?: boolean;
|
|
is_pinned?: boolean;
|
|
rid?: number;
|
|
}
|
|
): Promise<ArtalkComment> {
|
|
return artalkMutate<ArtalkComment>(`/api/v2/comments/${id}`, "PUT", { ...data, site_name: ARTALK_SITE });
|
|
}
|
|
|
|
export async function createComment(data: {
|
|
page_key: string;
|
|
content: string;
|
|
name: string;
|
|
email: string;
|
|
rid?: number;
|
|
}): Promise<ArtalkComment> {
|
|
return artalkMutate<ArtalkComment>("/api/v2/comments", "POST", { ...data, site_name: ARTALK_SITE });
|
|
}
|
|
|
|
export async function deleteComment(id: number): Promise<void> {
|
|
await artalkMutate<void>(`/api/v2/comments/${id}`, "DELETE", { site_name: ARTALK_SITE });
|
|
}
|
|
|
|
export async function updatePage(
|
|
id: number,
|
|
data: { key: string; title: string; admin_only?: boolean }
|
|
): Promise<ArtalkPage> {
|
|
return artalkMutate<ArtalkPage>(`/api/v2/pages/${id}`, "PUT", {
|
|
key: data.key,
|
|
title: data.title,
|
|
admin_only: data.admin_only ?? false,
|
|
site_name: ARTALK_SITE,
|
|
});
|
|
}
|