309 lines
14 KiB
Markdown
309 lines
14 KiB
Markdown
# 工具库与脚本模块
|
||
|
||
## 工具库 (`src/lib/`)
|
||
|
||
### prisma.ts - 数据库客户端
|
||
- Prisma单例模式,防止开发环境热重载创建多实例
|
||
- 使用PrismaMariaDb adapter
|
||
- 连接池配置(connection_limit=20, pool_timeout=30)
|
||
- 日志: 开发环境warn/error,生产环境error
|
||
- **环境变量校验**: DATABASE_URL 未设置时抛出明确错误(移除硬编码默认连接串)
|
||
|
||
### auth.ts - 认证配置
|
||
- NextAuth配置导出
|
||
- Credentials Provider(用户邮箱密码)
|
||
- GitHub OAuth Provider
|
||
- JWT策略
|
||
- 登录频率限制(7次/分钟)
|
||
- 导出GET/POST handler
|
||
|
||
### admin-auth.ts - 管理员API认证
|
||
- 导出 `getAdminSession()` — 获取当前会话(带缓存)
|
||
- 导出 `requireAdmin()` — 管理员权限验证中间件
|
||
- 导出 `requirePermission(key)` — 细粒度权限点校验
|
||
- 导出 `getAllUserPermissions()` — 获取当前用户全部权限
|
||
- 导出 `getUserPermissionKeys(userId)` — 获取用户权限键集合
|
||
- 验证session中角色和权限
|
||
- 返回401/403错误响应
|
||
|
||
### utils.ts - 工具函数
|
||
- `cn(...inputs)` — 合并clsx + tailwind-merge的className工具
|
||
- `extractJSON(str)` — JSON提取工具,支持markdown代码块包裹、花括号/方括号容错
|
||
|
||
### validation.ts - 数据验证
|
||
- Zod验证schemas
|
||
- 包含: registerSchema, loginSchema, paginationSchema, toolImportSchema(**max(100)**), skillImportSchema(**max(100)**), newsImportSchema(**max(50)**), checkTypeSchema(**max(50)**), profileUpdateSchema, favoriteSchema, historySchema, taskRunSchema, roleCreateSchema, categoryCreateSchema, skillCategoryCreateSchema, systemConfigUpdateSchema
|
||
- 批量导入数组均有数量上限,防止一次请求导入过多数据
|
||
|
||
### deepseek.ts - DeepSeek评测生成
|
||
- 依赖: openai (兼容OpenAI接口)
|
||
- 认证: process.env.DEEPSEEK_API_KEY
|
||
- baseURL: https://api.deepseek.com/v1
|
||
- 模型: 环境变量 `DEEPSEEK_MODEL`(默认 `deepseek-v4-pro`)
|
||
- 客户端配置: `timeout: 120000`, `maxRetries: 2`
|
||
- `generateReview(repoName, description, stars, license, readme)`: 调用DeepSeek生成五维评测
|
||
- 综合分校验: 自动计算五维均分,偏差>0.3时修正
|
||
- JSON提取: 兼容markdown代码块包裹的响应
|
||
|
||
### github.ts - GitHub数据采集
|
||
- 依赖: octokit
|
||
- 认证: process.env.GITHUB_TOKEN (推荐设置,提升限流60→5000次/小时)
|
||
- Octokit配置: `request.timeout: 30000`
|
||
- **withRetry**: 指数退避重试(最多3次),403/404/422 不重试直接抛
|
||
- `searchHotRepos(query, minStars, maxResults)`: 搜索热门仓库,按Star降序(带重试)
|
||
- `getRepoReadme(owner, repo)`: 获取仓库README内容(base64解码)(带重试+错误日志)
|
||
- `GitHubRepo` 接口: id, full_name, html_url, description, stargazers_count, forks_count, language, license, topics, updated_at, readme
|
||
|
||
### logo-fetcher.ts - Logo抓取引擎
|
||
- 导出 `fetchLogo(websiteUrl, html?): Promise<string>` — 返回Logo URL
|
||
- 导出 `fetchLogoWithMethod(websiteUrl, html?): Promise<LogoFetchResult>` — 返回 `{url, method}`
|
||
- 10种抓取策略按优先级执行
|
||
- 支持从SystemConfig读取配置
|
||
- 每种成功方法返回中文名称
|
||
- 所有 catch 块均添加 `console.warn` 日志(9处)
|
||
|
||
### logo-storage.ts - Logo本地存储
|
||
- 导出 `downloadLogo(url, filename): Promise<string>`
|
||
- 下载远程Logo到 `/public/logos/` 目录
|
||
- 返回本地路径如 `/logos/filename.png`
|
||
- **安全**: 最大文件大小 5MB
|
||
- **安全**: SVG 内容自动消毒 script/iframe/on-event 标签
|
||
- **哈希算法**: 使用 SHA256 生成文件名(不再使用 MD5)
|
||
|
||
### rate-limit.ts - 频率限制
|
||
- `rateLimit(ip, maxRequests, windowMs)` — IP频率限制
|
||
- 内存存储(Map)
|
||
- 默认: 10次/分钟
|
||
- **自动清理**: 每5分钟自动清理过期IP记录,防止内存无限增长
|
||
|
||
### use-permission.ts - 前端权限Hook
|
||
- 客户端Hook
|
||
- 获取当前用户权限
|
||
- 提供 `can(key)`, `canAny(keys)`, `canAll(keys)` 方法
|
||
|
||
---
|
||
|
||
## 脚本 (`scripts/`)
|
||
|
||
### 定时任务脚本(6个 + 1个日报 + 1个新闻推社区,均含TaskLog记录)
|
||
|
||
#### task1-discover-tools.mjs — Task1 发现AI工具
|
||
- 每天06:00由Crontab触发
|
||
- 从36kr/IT之家/开源中国RSS抓取新闻,调用DeepSeek提取AI工具信息
|
||
- 去重后入库PendingTool,含checkWebsiteOk/checkLogoOk等巡检结果
|
||
- 结果写入TaskLog(taskKey: task1-discover-tools)
|
||
|
||
#### task3-check-tools.mjs — Task3 工具巡检
|
||
- 每天03:00由Crontab触发
|
||
- 检查所有已发布Tool网站可访问性+Logo有效性,更新websiteOk/logoOk字段
|
||
- 对PendingTool逐一检查,四项检查全部通过则自动发布为正式Tool
|
||
- **FK回退**: categoryId为NULL时动态取数据库第一个有效分类(不再硬编码 `|| 1`)
|
||
- 结果写入TaskLog(taskKey: task3-check-tools),含websiteFails/logoFails/autoPublished统计
|
||
|
||
#### task4 daily-discover.mjs — Task4 发现AI技能
|
||
- 每天05:00由Crontab触发
|
||
- GitHub搜索AI相关项目(stars≥1000,日上限30)
|
||
- DeepSeek预评测后入库**PendingSkill**(不是直接创建Skill)
|
||
- 去重检查: skill表 + pendingSkill表
|
||
- 仓库内容质量过滤(isValidAIProject): 排除文档/教程/面试题/书单类Repo
|
||
- 结果写入TaskLog(taskKey: task4-discover-skills),含discovered/skipped/reviewed/failed统计
|
||
|
||
#### task5-update-stars.mjs — Task5 更新技能星值
|
||
- 每天01:00由Crontab触发
|
||
- 查询所有sourceUrl含github.com的Skill
|
||
- 通过Octokit API获取最新stargazers_count
|
||
- 更新githubStars/starsChangeDay/starsChangeWeek/starsChangeMonth
|
||
- 维护githubStarsHistory数组(保留最近90天)
|
||
- 结果写入TaskLog(taskKey: task5-update-stars),含updated/failed/skipped统计
|
||
|
||
#### task6-review-hot.mjs — Task6 评测热门技能
|
||
- 每天04:00由Crontab触发
|
||
- 查找2个已发布但无SkillReview的最热门GitHub技能(按githubStars/viewCount排序)
|
||
- 获取GitHub README,调用DeepSeek API生成五维评测
|
||
- 创建SkillReview(status: PUBLISHED),更新Skill.lastReviewedAt
|
||
- 结果写入TaskLog(taskKey: task6-review-hot),含reviewed/failed统计
|
||
|
||
#### daily-news.mjs — AI日报生成
|
||
- 每天07:30由Crontab触发
|
||
- 多源搜索: 36kr RSS + IT之家 RSS + 开源中国 RSS + HackerNews API + Google News RSS
|
||
- 新闻过滤: 发布日期近2天内 + AI关键词匹配
|
||
- DeepSeek整理格式生成中文日报(标题+摘要+条目)
|
||
- 入库DailyReport表
|
||
- 结果写入TaskLog(taskKey: daily-news),含reportId/itemCount/title统计
|
||
|
||
#### task7-news-to-community.mjs — Task7 新闻推社区
|
||
- 每天08:00由Crontab触发
|
||
- 查询今日(或昨天)已发布日报 → 按新闻category映射到社区板块
|
||
- 映射规则: product→ai-tools / business→ai-news / model→tech / opensource→tech / policy→ai-news / insight→discuss
|
||
- 以admin用户身份创建ForumTopic,去重(按标题),更新板块topicCount
|
||
- 结果写入TaskLog(taskKey: task7-news-to-community),含created/skipped统计
|
||
|
||
#### seed-task-configs.mjs — 任务配置种子数据
|
||
- 一次性运行(幂等,创建或更新)
|
||
- 初始化7个TaskConfig记录(task1/3/4/5/6/7 + daily-news)
|
||
- 含默认cronExpr、enabled=true、description
|
||
|
||
### 其他脚本
|
||
|
||
#### auto-review.mjs (自动化评测脚本 — 已被Task4/Task6替代)
|
||
- 依赖: @prisma/client, @prisma/adapter-mariadb, octokit, openai
|
||
- 流程: GitHub搜索→README获取→DeepSeek评测→Skill入库→SkillReview入库→日志记录
|
||
- 配置: SEARCH_QUERIES(4个关键词), MIN_STARS(500→已被Task4提升为1000), DAILY_LIMIT(8→已有Task4用的30)
|
||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node scripts/auto-review.mjs`
|
||
|
||
#### publish-reviews.mjs (发布评测脚本)
|
||
- 将DRAFT状态SkillReview改为PUBLISHED
|
||
- 将对应draft状态Skill改为published
|
||
- 注: Task6-review-hot.mjs 创建的SkillReview直接为PUBLISHED,无需此脚本
|
||
|
||
#### generate-review-content.mjs (生成评测内容)
|
||
- 调用DeepSeek生成评测长文、视频脚本、社交卡片
|
||
- 用于已评测技能的内容生成
|
||
|
||
#### organize-content.mjs (内容整理脚本)
|
||
- 整理和归类内容
|
||
|
||
#### test-github.mjs (GitHub API测试)
|
||
- 测试searchHotRepos和getRepoReadme功能
|
||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node -r dotenv/config scripts/test-github.mjs`
|
||
|
||
#### test-deepseek.mjs (DeepSeek API测试)
|
||
- 测试generateReview功能,使用langflow作为测试用例
|
||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node scripts/test-deepseek.mjs`
|
||
|
||
#### test-content-generation.mjs (内容生成测试)
|
||
- 测试评测内容生成管线
|
||
|
||
#### debug-json.mjs (JSON解析调试)
|
||
- 调试JSON解析逻辑
|
||
|
||
#### delete-drafts.mjs (删除草稿)
|
||
- 批量删除草稿数据
|
||
|
||
#### cleanup-non-ai.mjs (清理非AI项目)
|
||
- 清理误入库的非AI技能数据
|
||
- 使用isValidAIProject过滤
|
||
|
||
#### db-status.mjs (数据库状态)
|
||
- 检查数据库连接和数据状态
|
||
|
||
#### seed-permissions.mjs (权限种子数据)
|
||
- 初始化全部权限点+角色
|
||
- 幂等运行
|
||
|
||
#### migrate-logos.mjs (Logo迁移)
|
||
- 迁移Logo到本地存储
|
||
|
||
---
|
||
|
||
## 运维脚本
|
||
|
||
### 容器 Entrypoint 脚本
|
||
- `scripts/entrypoint-app.sh` — APP 容器启动入口,执行 prisma migrate deploy(幂等)后启动 next start
|
||
- `scripts/entrypoint-cron.sh` — CRON 容器启动入口,校验 .env 和 crontab.txt 后启动 supercronic
|
||
|
||
### 卷备份脚本
|
||
- `scripts/backup-volumes.sh` — 备份 4 个命名卷到 `/home/ubuntu/zhuiguang-ai-backup/dockers/`,保留 7 天
|
||
- `scripts/install-cron-backup.sh` — 安装主机备份 cron(每天 03:00 执行备份)
|
||
|
||
### 定时任务调度
|
||
- `crontab.txt` — supercronic 调度配置(25 条定时任务),不再使用主机 crontab + cron-wrapper.sh
|
||
|
||
### lib/retry.mjs
|
||
- 重试工具函数
|
||
|
||
---
|
||
|
||
## Bot系统脚本
|
||
|
||
### bot-activity.mjs — Bot活动引擎
|
||
- 每小时运行(9:00-23:00),15轮/天
|
||
- 遍历10个论坛板块,为每个板块选取适配Bot发帖+回复
|
||
- 集成Persona画像注入、A/B变体选择、对抗学习上下文
|
||
- 生成后自动点赞 + 写入BotDailyStat
|
||
|
||
### bot-skill-crystallize.mjs — Bot技能结晶
|
||
- 每天02:00运行
|
||
- 扫描过去14天高互动Bot话题,DeepSeek解构共性→入库BotSkill
|
||
- 7天后回收检查成熟技能成功率,<30%且使用≥3次自动禁用
|
||
|
||
### bot-affinity-update.mjs — Bot亲和度与画像
|
||
- 每周日22:30运行
|
||
- 计算BotCrossForumAffinity + 刷新BotPersona画像
|
||
|
||
### bot-feedback-loop.mjs — Bot反馈闭环
|
||
- 每周日22:00运行(原21:30)
|
||
- 三层记忆模型(SESSION/WORKING/LONGTERM)
|
||
- 扫描Bot自己帖子下的新回复 → 存反馈记忆 → 按概率触发二次回复
|
||
|
||
### bot-weekly-review.mjs — Bot周度复盘
|
||
- 每周日02:00运行
|
||
- 聚合一周指标 → 计算engagementScore → LLM生成反思 → 决定下周配额
|
||
|
||
### bot-persona-experiment-run.mjs — A/B实验调度
|
||
- 每小时运行
|
||
- 采集BotPersonaAssignment指标 → 按日聚合到BotPersonaMetric → 显著性检验 → 自动切换winner
|
||
- 支持 `--lookback` / `--no-switch` / `--metrics-only` / `--analyze-only`
|
||
|
||
### bot-adversarial-learning-run.mjs — 对抗学习调度
|
||
- 每周日23:00运行
|
||
- 为每个expert bot选1篇真人高互动帖 → DeepSeek提取洞察 → 入库BotAdversarialLearning
|
||
- 支持 `--week` / `--force` / `--bot` / `--lookback`
|
||
|
||
### bot-avatar-generate.mjs — Bot头像生成
|
||
- CLI入口,为112个bot批量预生成头像
|
||
- Lunaris text-to-image → 占位检测 → SVG兜底 → 落盘public/bot-avatars/
|
||
- 支持 `--bot` / `--force` / `--use-lunaris-only` / `--no-update-db` / `--dry-run`
|
||
|
||
### 其他Bot脚本
|
||
- `generate-bot-content.mjs` — 独立Bot内容生成(手动/临时运行)
|
||
- `seed-bot-forum.mjs` — 论坛板块+Bot初始内容种子
|
||
- `backfill-bot-daily-stats.mjs` — BotDailyStat历史数据回填
|
||
- `test-bot-stats.mjs` — Bot统计测试调试工具
|
||
|
||
### Bot共享库 (`scripts/lib/`)
|
||
|
||
#### bot-persona.mjs — 人设画像
|
||
- `updatePersona(botConfigId)` — 异步刷新画像(30天聚合)
|
||
- `computePersona(botConfigId)` — 计算风格指标
|
||
- `schedulePersonaRefresh()` — 定时触发
|
||
|
||
#### bot-persona-experiment.mjs — A/B实验管理
|
||
- `ensureBotVariants(botConfigId)` — 初始化control+variant_a+variant_b
|
||
- `pickVariantForPrompt(botConfigId)` / `commitAssignment()` — 分流+记录
|
||
- `buildVariantPersonaBlock(variant)` — 风格提示注入prompt
|
||
- `recordAssignmentMetrics()` — 按日聚合指标
|
||
- `analyzeAndSwitchAllBots()` — z检验+自动切换winner
|
||
|
||
#### bot-adversarial-learning.mjs — 对抗学习
|
||
- `runWeeklyAdversarialLearning()` — 全量学习入口
|
||
- `getActiveLearningForBot()` / `buildAdversarialBlock()` — 发帖时查询+注入
|
||
- `extractInsight(post, bot, persona)` — DeepSeek提取洞察
|
||
|
||
#### bot-avatar-generator.mjs — 头像生成
|
||
- `generateForAll()` — 遍历112个bot生成头像
|
||
- `fetchLunarisImage()` / `isLunarisDefault()` / `generateSvgAvatar()` — 三步流程
|
||
- 10色调色板 + key哈希 → 唯一SVG头像
|
||
|
||
### 前端Bot工具
|
||
|
||
#### bot-utils.ts (`src/lib/bot-utils.ts`)
|
||
- `getBotAvatarUrl(key, avatarPrompt)` — 动态头像URL
|
||
- `getBotColorScheme(key)` — 稳定哈希→Tailwind配色类
|
||
|
||
---
|
||
|
||
### 修复/诊断脚本
|
||
- `fix-db-url.cjs` — 批量修复所有 `.mjs` 脚本的 `mysql://` → `mariadb://` 协议兼容(PrismaMariaDb adapter 要求)
|
||
- `fix-ts-types.cjs` — 批量移除 `.mjs` 文件中的 TypeScript 类型注解(`.mjs` 不支持 TS 语法)
|
||
- `check-categories.cjs` — 检查数据库社区板块分类,输出所有 ForumCategory 的 id/name/slug
|
||
|
||
---
|
||
|
||
## 开发规则引用
|
||
> Shell 脚本和运维开发必须遵守以下规则:
|
||
> - [第十三章 - Shell脚本规范](file:///c:/SGP_KF/ZhuiGuangAI/zhuiguang-ai/.trae/rules/project_rules.md):`set -e`、PASS/FAIL/WARN 结构化输出、资源预检、禁止操作清单
|
||
> - [第八章 - 定时任务规范](file:///c:/SGP_KF/ZhuiGuangAI/zhuiguang-ai/.trae/rules/project_rules.md):entrypoint-cron.sh 信号处理、启动校验、健康检查端点;日志三层目录;任务幂等性
|
||
> - [第十八章 - AI/Bot系统规范](file:///c:/SGP_KF/ZhuiGuangAI/zhuiguang-ai/.trae/rules/project_rules.md):Bot角色定义、活动脚本5大约定、AI API隔离、提示词管理
|
||
> - [第十九章 - 环境变量管理规范](file:///c:/SGP_KF/ZhuiGuangAI/zhuiguang-ai/.trae/rules/project_rules.md):变量分级、`.env.example` 同步、脚本侧加载顺序
|