This commit is contained in:
Vaica committed 2026-06-24 14:20:43 +08:00
1 parent 9a083b50b4
commit bf0fae69d6
2 files changed
+84 -6

No files matched your search

+82 -6
View File
@@ -1,4 +1,4 @@
import { ARTALK_SERVER, ARTALK_SITE } from "@/lib/config";
import { ARTALK_SERVER, ARTALK_SITE, ARTALK_ADMIN_EMAIL, ARTALK_ADMIN_PASSWORD } from "@/lib/config";
import { sendMessage } from "./tg";
import { ALLOWED_IDS } from "./config";
@@ -13,22 +13,98 @@ interface ArtalkComment {
let lastCheckedId = 0;
let notifierStarted = false;
let authToken: string | null = null;
let tokenExpiry = 0;
// 登录 Artalk 获取管理员 token
async function loginToArtalk(): Promise<string | null> {
if (!ARTALK_ADMIN_EMAIL || !ARTALK_ADMIN_PASSWORD) {
console.error("[comment-notify] ARTALK_ADMIN_EMAIL or ARTALK_ADMIN_PASSWORD not configured");
return null;
}
// 获取所有评论(使用 type=all 参数)
async function fetchLatestComments(): Promise<ArtalkComment[]> {
try {
// 尝试使用 type=all 参数获取所有评论
const url = `${ARTALK_SERVER}/api/v2/comments?site_name=${encodeURIComponent(ARTALK_SITE)}&type=all&limit=5&sort_by=created_at&sort_order=desc`;
console.log("[comment-notify] fetching comments with type=all...");
const url = `${ARTALK_SERVER}/api/v2/auth/email/login`;
console.log("[comment-notify] logging in to Artalk...");
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: ARTALK_ADMIN_EMAIL,
password: ARTALK_ADMIN_PASSWORD,
}),
});
if (!res.ok) {
console.error("[comment-notify] login failed:", res.status);
return null;
}
const data = await res.json() as { token?: string; user?: { name: string } };
if (!data.token) {
console.error("[comment-notify] no token in response");
return null;
}
console.log("[comment-notify] logged in as:", data.user?.name || "admin");
return data.token;
} catch (e) {
console.error("[comment-notify] login error:", e instanceof Error ? e.message : String(e));
return null;
}
}
// 获取或刷新 token
async function getAuthToken(): Promise<string | null> {
const now = Date.now();
// Token 有效(提前 5 分钟刷新)
if (authToken && now < tokenExpiry - 5 * 60 * 1000) {
return authToken;
}
// 登录获取新 token
authToken = await loginToArtalk();
if (authToken) {
// Token 有效期设为 24 小时(Artalk 默认较长)
tokenExpiry = now + 24 * 60 * 60 * 1000;
}
return authToken;
}
// 获取所有评论(使用管理员 API)
async function fetchLatestComments(): Promise<ArtalkComment[]> {
try {
const token = await getAuthToken();
if (!token) {
console.error("[comment-notify] no auth token available");
return [];
}
// 使用管理员 API 获取所有评论
const url = `${ARTALK_SERVER}/api/v2/admin/comments?site_name=${encodeURIComponent(ARTALK_SITE)}&limit=5&sort_by=date&sort_order=desc`;
console.log("[comment-notify] fetching comments with admin API...");
const res = await fetch(url, {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
},
});
if (!res.ok) {
const errorText = await res.text().catch(() => "Unable to read response");
console.error("[comment-notify] fetch failed:", res.status, res.statusText);
console.error("[comment-notify] response:", errorText);
// 如果是认证失败,清除 token 以便下次重试
if (res.status === 401 || res.status === 403) {
authToken = null;
tokenExpiry = 0;
}
return [];
}
+2
View File
@@ -13,6 +13,8 @@ export const RECYCLE_POSTS_DIR = path.join(RECYCLE_DIR, "posts");
export const RECYCLE_META_DIR = path.join(RECYCLE_DIR, "meta");
export const ARTALK_SERVER = process.env.ARTALK_SERVER || "https://artalk.usj.cc";
export const ARTALK_SITE = process.env.ARTALK_SITE || "优世界";
export const ARTALK_ADMIN_EMAIL = process.env.ARTALK_ADMIN_EMAIL || "";
export const ARTALK_ADMIN_PASSWORD = process.env.ARTALK_ADMIN_PASSWORD || "";
export const ITEMS_PER_PAGE = parseInt(process.env.ITEMS_PER_PAGE || "20", 10);
export const RECYCLE_DAYS = parseInt(process.env.RECYCLE_DAYS || "30", 10);
export const HUGO_PREVIEW = process.env.NEXT_PUBLIC_HUGO_PREVIEW || process.env.HUGO_PREVIEW || "http://localhost:1313";