Files

309 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 工具库与脚本模块
## 工具库 (`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` 同步、脚本侧加载顺序