Deploy to Production / pre-check (push) Successful in 1m10s
Deploy to Production / build (push) Successful in 4m44s
Deploy to Production / deploy-edgeone (push) Successful in 3m39s
Deploy to Production / finalize (push) Successful in 35s
Deploy to Production / notify-failure (push) Skipped
评论与订阅已合并为同一个 Cloudflare Worker(artalk-cf, 同时服务 api.200181.xyz 与 artalk.200181.xyz)。为收敛到 单一域名/单一面板,评论入口统一切到 api.200181.xyz。 - hugo.toml params.artalk.server → api.200181.xyz - write-server ARTALK_SERVER 默认值同步 - 注意:post.usj.cc 服务器 .env 里若有 ARTALK_SERVER 覆盖项需同步改
68 lines
2.9 KiB
TypeScript
68 lines
2.9 KiB
TypeScript
import path from "path";
|
|
import os from "os";
|
|
|
|
// 博客根目录
|
|
// Docker 构建时 BLOG_ROOT=/blog 已被 Turbopack 内联
|
|
// 本地开发时回退到上级目录
|
|
export const BLOG_ROOT = process.env.BLOG_ROOT || path.resolve(process.cwd(), "..");
|
|
|
|
export const CONTENT_DIR = path.join(BLOG_ROOT, "content", "posts");
|
|
export const STATIC_DIR = path.join(BLOG_ROOT, "static");
|
|
export const RECYCLE_DIR = path.join(process.cwd(), "recycle");
|
|
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://api.200181.xyz";
|
|
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";
|
|
export const RSS_API_BASE = process.env.RSS_API_BASE || "https://api.200181.xyz";
|
|
export const RSS_API_TOKEN = process.env.RSS_API_TOKEN || "";
|
|
export const WECHAT_APP_ID = process.env.WECHAT_APP_ID || "";
|
|
export const WECHAT_APP_SECRET = process.env.WECHAT_APP_SECRET || "";
|
|
|
|
// Bot 配置
|
|
export const TG_BOT_TOKEN = process.env.TG_BOT_TOKEN || "";
|
|
export const TG_ALLOWED_IDS: number[] = (process.env.TG_ALLOWED_CHAT_IDS || "")
|
|
.split(",").map((s) => s.trim()).filter(Boolean).map(Number);
|
|
|
|
// Linux 默认网络接口(eth0, ens33 等),Windows 默认 WLAN
|
|
export const PREFER_IFACE = process.env.PREFER_IFACE || (process.platform === "linux" ? "eth0" : "WLAN");
|
|
export const DEFAULT_AUTHOR = process.env.DEFAULT_AUTHOR || "小赵";
|
|
|
|
export function getLanIP(): string {
|
|
const ifs = os.networkInterfaces();
|
|
const candidates: { name: string; address: string }[] = [];
|
|
for (const [name, addrs] of Object.entries(ifs)) {
|
|
if (!addrs) continue;
|
|
for (const a of addrs) {
|
|
if (a.family !== "IPv4" || a.internal) continue;
|
|
if (a.address.startsWith("169.254.")) continue;
|
|
candidates.push({ name, address: a.address });
|
|
}
|
|
}
|
|
|
|
// 优先查找首选接口
|
|
const pref = candidates.find((c) =>
|
|
c.name.toLowerCase().includes(PREFER_IFACE.toLowerCase())
|
|
);
|
|
if (pref) return pref.address;
|
|
|
|
// 查找真实网络接口(排除虚拟接口)
|
|
const real = candidates.find((c) => {
|
|
const n = c.name.toLowerCase();
|
|
return !n.includes("vmware") &&
|
|
!n.includes("virtual") &&
|
|
!n.includes("vethernet") &&
|
|
!n.includes("docker") &&
|
|
!n.includes("br-") &&
|
|
!n.includes("veth");
|
|
});
|
|
if (real) return real.address;
|
|
|
|
// 返回第一个可用地址
|
|
return candidates[0]?.address || "0.0.0.0";
|
|
}
|