精简若干功能,优化slug生成规则

This commit is contained in:
Vaica committed 2026-06-02 11:43:58 +08:00
1 parent 05bf116c20
commit f9b2a0e77b
15 files changed
+76 -41

No files matched your search

+3 -1
View File
@@ -5,7 +5,7 @@ import { deployQueue } from "@/lib/git";
import { hugo } from "@/lib/hugo";
import { getLanIP, DEFAULT_AUTHOR } from "@/lib/config";
import { sendMessage, tg } from "./tg";
import { getSession, hasSession, clearSession, saveSession, undoLastChunk } from "./sessions";
import { getSession, hasSession, clearSession, saveSession, undoLastChunk, initSessionDir } from "./sessions";
import { makeSlug, sessionSummary, truncateText } from "./helpers";
import { getCached, setCache, invalidateByPrefix } from "./cache";
@@ -221,6 +221,7 @@ handlers.new = async (chatId, title) => {
s.draft = true;
s.author = DEFAULT_AUTHOR;
s.chunks = [];
initSessionDir(chatId, title);
await tg("sendMessage", {
chat_id: chatId,
text: "📝 开始写:<b>" + title + "</b>\n\n📂 设置分类(可选)",
@@ -320,6 +321,7 @@ handlers.edit = async (chatId, slug) => {
s.originalSlug = post.frontMatter.slug;
s.content = "";
s.chunks = [];
s.dirPath = post.dirPath;
s.categories = (post.frontMatter.categories as string[]) || [];
s.tags = (post.frontMatter.tags as string[]) || [];
s.author = post.frontMatter.author || DEFAULT_AUTHOR;
+8 -14
View File
@@ -1,13 +1,12 @@
import path from "path";
import { CONTENT_DIR } from "@/lib/config";
export function makeSlug(title: string): string {
const dateStr = new Date().toISOString().slice(0, 10);
const slugPart = (title || "untitled")
.replace(/[^\w一-鿿㐀-䶿]+/g, "-")
.replace(/^-+|-+$/g, "")
.toLowerCase() || "post";
return dateStr + "-" + slugPart;
const now = new Date();
const y = now.getFullYear();
const m = String(now.getMonth() + 1).padStart(2, "0");
const d = String(now.getDate()).padStart(2, "0");
const h = String(now.getHours()).padStart(2, "0");
const mi = String(now.getMinutes()).padStart(2, "0");
const s = String(now.getSeconds()).padStart(2, "0");
return `${y}${m}${d}${h}${mi}${s}`;
}
export function sessionSummary(s: {
@@ -26,11 +25,6 @@ export function sessionSummary(s: {
return parts.filter(Boolean).join(" · ");
}
export function getArticleDirPath(slug: string): string {
const year = slug.slice(0, 4);
return path.join(CONTENT_DIR, year, slug);
}
export function truncateText(text: string, maxLen: number): string {
if (text.length <= maxLen) return text;
return text.slice(0, maxLen) + "\n\n... 前 " + maxLen + " 字";
+6 -3
View File
@@ -171,11 +171,14 @@ async function handlePhoto(chatId: number, photos: { file_id: string }[], captio
try {
const fs = await import("fs");
const path = await import("path");
const { CONTENT_DIR } = await import("@/lib/config");
const { getSession } = await import("./sessions");
const { getArticleDirPath } = await import("./helpers");
const s = getSession(chatId);
if (!s.dirPath) {
await sendMessage(chatId, "❌ 请先发 /new 或 /edit 开始写作");
return;
}
const largestPhoto = photos[photos.length - 1];
const fileRes = await tg<{ file_path?: string }>("getFile", { file_id: largestPhoto.file_id });
if (!fileRes.ok || !fileRes.result?.file_path) return;
@@ -185,7 +188,7 @@ async function handlePhoto(chatId: number, photos: { file_id: string }[], captio
const imgBuffer = await fetch(fileUrl).then((r) => r.arrayBuffer());
// Save to article's own folder (Hugo page bundle)
const articleDir = getArticleDirPath(s.slug);
const articleDir = s.dirPath;
if (!fs.existsSync(articleDir)) fs.mkdirSync(articleDir, { recursive: true });
const ext = filePath.split(".").pop() || "jpg";
+27 -3
View File
@@ -1,5 +1,6 @@
import { createPost, updatePost, getPost } from "@/lib/posts";
import { DEFAULT_AUTHOR } from "@/lib/config";
import { DEFAULT_AUTHOR, CONTENT_DIR } from "@/lib/config";
import path from "path";
export interface Session {
title: string;
@@ -11,6 +12,18 @@ export interface Session {
draft: boolean;
chunks: string[];
originalSlug?: string;
dirPath: string;
}
function computeDirPath(title: string, date?: string): string {
const d = date ? new Date(date) : new Date();
const year = d.getFullYear().toString();
const dateStr = d.toISOString().slice(0, 10);
const titlePart = (title || "untitled")
.replace(/[^\w一-鿿㐀-䶿]+/g, "-")
.replace(/^-+|-+$/g, "")
.toLowerCase() || "post";
return path.join(CONTENT_DIR, year, `${dateStr}-${titlePart}`);
}
const sessions = new Map<number, Session>();
@@ -26,6 +39,7 @@ export function getSession(chatId: number): Session {
author: DEFAULT_AUTHOR,
draft: true,
chunks: [],
dirPath: "",
});
}
return sessions.get(chatId)!;
@@ -56,11 +70,19 @@ export function undoLastChunk(chatId: number): boolean {
return true;
}
export function initSessionDir(chatId: number, title: string, date?: string): void {
const s = getSession(chatId);
if (!s.dirPath) {
s.dirPath = computeDirPath(title, date);
}
}
export async function saveSession(s: Session, isDraft: boolean): Promise<void> {
const dateStr = new Date().toISOString().slice(0, 10);
const frontMatter = {
title: s.title,
slug: s.slug,
date: new Date().toISOString().slice(0, 10),
date: dateStr,
draft: isDraft,
categories: s.categories,
tags: s.tags,
@@ -71,7 +93,9 @@ export async function saveSession(s: Session, isDraft: boolean): Promise<void> {
if (existing) {
const result = updatePost(s.slug, frontMatter, s.content);
if (!result.success) throw new Error("更新文章失败");
s.dirPath = result.dirPath;
} else {
createPost(frontMatter, s.content);
const dirPath = createPost(frontMatter, s.content);
s.dirPath = dirPath;
}
}
+6 -2
View File
@@ -155,7 +155,7 @@ export function createPost(frontMatter: PostFrontMatter, content: string): strin
const date = new Date(frontMatter.date || new Date());
const year = date.getFullYear().toString();
const dateStr = date.toISOString().slice(0, 10);
// Folder name: date + sanitized title (Chinese-friendly)
// Folder name: date + sanitized title (human-readable on disk)
const titlePart = (frontMatter.title || "untitled")
.replace(/[^\w一-鿿㐀-䶿]+/g, "-")
.replace(/^-+|-+$/g, "")
@@ -202,7 +202,11 @@ export function updatePost(
const newDate = new Date(merged.date || post.frontMatter.date);
const newYear = newDate.getFullYear().toString();
const newDateStr = newDate.toISOString().slice(0, 10);
const newDirName = `${newDateStr}-${frontMatter.slug}`;
const titlePart = (merged.title || "untitled")
.replace(/[^\w一-鿿㐀-䶿]+/g, "-")
.replace(/^-+|-+$/g, "")
.toLowerCase() || "post";
const newDirName = `${newDateStr}-${titlePart}`;
const newDirPath = path.join(CONTENT_DIR, newYear, newDirName);
if (fs.existsSync(newDirPath) && newDirPath !== post.dirPath) {
+2 -2
View File
@@ -1,4 +1,4 @@
declare module "marked" {
export function marked(src: string): string;
export function parse(src: string): string;
export function parse(src: string, options?: Record<string, unknown>): string;
export const marked: { parse: typeof parse };
}