Files
blog/write-server/src/lib/artalk.ts
T
2026-06-21 20:42:44 +08:00

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,
});
}