This commit is contained in:
Vaica committed 2026-06-21 23:58:29 +08:00
1 parent 424355da7c
commit 7b3173e89d
5 files changed
+86 -6

No files matched your search

+7 -2
View File
@@ -35,8 +35,13 @@ RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
# Install Hugo and su-exec (for entrypoint)
RUN apk add --no-cache hugo su-exec
# Install specific Hugo version, git and su-exec
ARG HUGO_VERSION=0.128.2
RUN wget -q https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz -O /tmp/hugo.tar.gz && \
tar -xzf /tmp/hugo.tar.gz -C /tmp && \
mv /tmp/hugo /usr/local/bin/hugo && \
rm /tmp/hugo.tar.gz && \
apk add --no-cache git su-exec
# Create non-root user
RUN addgroup --system --gid 1001 nodejs && \
+1
View File
@@ -12,6 +12,7 @@ services:
restart: unless-stopped
ports:
- "8016:8016"
- "1313:1313"
volumes:
# Hugo 博客目录(必须)- 映射宿主机博客根目录到容器内 /blog
- ..:/blog
+7
View File
@@ -15,9 +15,16 @@ fi
if [ -d "/blog/static" ]; then
chown -R nextjs:nodejs /blog/static
fi
if [ -d "/blog/.git" ]; then
chown -R nextjs:nodejs /blog/.git
fi
if [ -f "/blog/hugo.toml" ]; then
chown nextjs:nodejs /blog/hugo.toml
fi
# 配置 git(容器内 nextjs 用户)
su-exec nextjs git config --global user.name "Write Server" 2>/dev/null
su-exec nextjs git config --global user.email "write@usj.cc" 2>/dev/null
# 以 nextjs 用户启动应用
exec su-exec nextjs "$@"
+14 -4
View File
@@ -95,10 +95,20 @@ document.getElementById('form').addEventListener('submit', async function(e) {
}
});
// 已登录则直接跳转
if (localStorage.getItem('wauth')) {
location.href = '/';
}
// 已登录则验证后跳转
(function(){
var tok = localStorage.getItem('wauth');
if (!tok) return;
fetch('/auth/check', { headers: { 'Authorization': 'Basic ' + tok } }).then(function(r) {
if (r.ok) {
location.href = '/';
} else {
localStorage.removeItem('wauth');
}
}).catch(function() {
localStorage.removeItem('wauth');
});
})();
</script>
</body>
</html>
+57
View File
@@ -70,6 +70,9 @@ export async function startPolling(): Promise<void> {
const msg = update.message as {
chat?: { id: number };
photo?: { file_id: string }[];
document?: { file_id: string; file_name?: string; mime_type?: string };
animation?: { file_id: string; file_name?: string; mime_type?: string };
video?: { file_id: string; file_name?: string };
text?: string;
caption?: string;
reply_to_message?: { text?: string };
@@ -78,11 +81,21 @@ export async function startPolling(): Promise<void> {
const chatId = msg.chat.id;
if (!allowed(chatId)) continue;
// 处理图片
if (msg.photo && hasSession(chatId)) {
await handlePhoto(chatId, msg.photo, msg.caption);
continue;
}
// 处理 GIF / 文档 / 视频
if ((msg.animation || msg.document || msg.video) && hasSession(chatId)) {
const file = msg.animation || msg.document || msg.video;
if (file) {
await handleDocument(chatId, file.file_id, file.file_name, msg.caption);
}
continue;
}
if (!msg.text) continue;
const fullText = msg.text.trim();
@@ -204,6 +217,50 @@ async function handlePhoto(chatId: number, photos: { file_id: string }[], captio
}
}
async function handleDocument(chatId: number, fileId: string, fileName?: string, caption?: string) {
try {
const fs = await import("fs");
const path = await import("path");
const { getSession } = await import("./sessions");
const s = getSession(chatId);
if (!s.dirPath) {
await sendMessage(chatId, "❌ 请先发 /new 或 /edit 开始写作");
return;
}
const fileRes = await tg<{ file_path?: string }>("getFile", { file_id: fileId });
if (!fileRes.ok || !fileRes.result?.file_path) {
await sendMessage(chatId, "❌ 文件获取失败(可能文件太大,Telegram 限制 20MB)");
return;
}
const filePath = fileRes.result.file_path;
const fileUrl = "https://api.telegram.org/file/bot" + TG_TOKEN + "/" + filePath;
const fileBuffer = await fetch(fileUrl).then((r) => r.arrayBuffer());
const articleDir = s.dirPath;
if (!fs.existsSync(articleDir)) fs.mkdirSync(articleDir, { recursive: true });
const ext = fileName?.split(".").pop() || filePath.split(".").pop() || "gif";
const filename = Date.now() + "-" + fileId.slice(0, 8) + "." + ext;
fs.writeFileSync(path.join(articleDir, filename), Buffer.from(fileBuffer));
// GIF 用图片语法,其他用链接
const isImage = ["gif", "webp", "png", "jpg", "jpeg"].includes(ext.toLowerCase());
const fileCaption = caption || fileName || "file";
if (isImage) {
appendContent(chatId, `\n![${fileCaption}](${filename})\n`);
} else {
appendContent(chatId, `\n[${fileCaption}](${filename})\n`);
}
await sendMessage(chatId, `📎 文件已保存:${filename}`);
} catch (e) {
console.error("[bot:document]", e instanceof Error ? e.message : String(e));
await sendMessage(chatId, "❌ 文件保存失败");
}
}
async function handleCommand(chatId: number, cmd: string, arg?: string) {
try {
if (cmd === "noop") return;