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

This commit is contained in:
Vaica committed 2026-06-02 11:43:58 +08:00
1 parent 2c6bd1c964
commit 791be8bd4f
15 files changed
+76 -41

No files matched your search

+6
View File
@@ -49,6 +49,12 @@ jobs:
continue-on-error: true
run: node scripts/optimize_images.js
- name: Fetch AI Greetings
continue-on-error: true
env:
RSS_API_TOKEN: ${{ secrets.RSS_API_TOKEN }}
run: node scripts/fetch_greetings.js
- name: Commit Optimized Images
continue-on-error: true
run: |
@@ -1,7 +1,7 @@
---
title: 尝试接入telegram机器人
date: '2026-06-01T00:00:00.000Z'
slug: 2026-06-01-尝试接入-telegram-机器人
title: 尝试接入 telegram 机器人
date: '2026-06-02T00:00:00.000Z'
slug: '202606021139'
draft: false
categories:
- 生活
+1 -1
View File
@@ -219,7 +219,7 @@ hasCJKLanguage = true
# 打赏配置 (Reward Configuration)
# ----------------------------------------------------------------------------
[params.reward]
enable = true
enable = false
wechat = "/image/reward/new.png"
# alipay = "/image/reward/alipay.jpg"
# qq = "/image/reward/reward.png"
+2 -2
View File
@@ -58,13 +58,13 @@ async function main() {
}
});
// Pick one random greeting per time slot, fall back to generic pool
// Keep all greetings per time slot (frontend picks randomly)
var timeGreetings = {};
timeKeys.forEach(function(key) {
var list = byTime[key];
if (list.length === 0) list = generic;
if (list.length > 0) {
timeGreetings[key] = list[Math.floor(Math.random() * list.length)];
timeGreetings[key] = list;
}
});
+12 -10
View File
@@ -354,17 +354,19 @@ function initInlineSearch() {
}
// 2. Check Time of Day (if greetings configured)
else if (window.searchGreetings) {
if (hour >= 6 && hour < 11 && window.searchGreetings.morning) {
text = window.searchGreetings.morning;
} else if (hour >= 11 && hour < 14 && window.searchGreetings.noon) {
text = window.searchGreetings.noon;
} else if (hour >= 14 && hour < 18 && window.searchGreetings.afternoon) {
text = window.searchGreetings.afternoon;
} else if (hour >= 18 && hour < 22 && window.searchGreetings.evening) {
text = window.searchGreetings.evening;
} else if ((hour >= 22 || hour < 6) && window.searchGreetings.night) {
text = window.searchGreetings.night;
function pickGreeting(key) {
var val = window.searchGreetings[key];
if (!val) return null;
if (Array.isArray(val)) return val[Math.floor(Math.random() * val.length)];
return val;
}
var picked = null;
if (hour >= 6 && hour < 11) picked = pickGreeting('morning');
else if (hour >= 11 && hour < 14) picked = pickGreeting('noon');
else if (hour >= 14 && hour < 18) picked = pickGreeting('afternoon');
else if (hour >= 18 && hour < 22) picked = pickGreeting('evening');
else if (hour >= 22 || hour < 6) picked = pickGreeting('night');
if (picked) text = picked;
}
var typeInterval;
+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 };
}