GitHub Trending Notifier 对外提供的接口和内部 API 详细说明。
本技能主要包含三个外部 API 调用:
- GitHub Search API - 获取热门仓库
- OpenRouter Chat Completion API - 生成 AI 摘要
- 通知渠道 API - 发送消息 (Telegram/Discord/Feishu)
此外,还提供 OpenClaw 内部的命令行接口用于技能触发。
node scripts/trending.js [options]该脚本不接受传统命令行参数,所有配置通过环境变量读取。
| 退出码 | 含义 |
|---|---|
0 |
成功执行,通知已发送(或无新仓库) |
1 |
配置错误或 API 调用失败 |
# 标准运行
node scripts/trending.js
# 带调试输出
DEBUG=* node scripts/trending.js端点: GET https://api.github.com/search/repositories
认证: Bearer Token (GITHUB_TOKEN)
请求参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
q |
String | ✅ | 搜索查询字符串 |
sort |
String | ❌ | 排序方式: stars, forks, help-wanted-issues, updated |
order |
String | ❌ | 排序顺序: desc (默认), asc |
per_page |
Number | ❌ | 每页数量 (默认 30, 最大 100) |
当前实现查询:
const dateStr = since.toISOString().split('T')[0]; // 昨天日期
const query = `created:>=${dateStr} stars:>100 sort:stars-desc`;示例响应:
{
"total_count": 12345,
"incomplete_results": false,
"items": [
{
"id": 123456,
"name": "awesome-project",
"full_name": "owner/awesome-project",
"html_url": "https://github.com/owner/awesome-project",
"description": "A fantastic project description",
"stargazers_count": 5678,
"forks_count": 890,
"language": "TypeScript",
"created_at": "2025-03-07T10:30:00Z",
"updated_at": "2025-03-07T12:45:00Z",
"owner": {
"login": "owner",
"avatar_url": "https://github.com/owner.png"
}
}
]
}字段映射:
| 变量名 | API 字段 | 类型 | 说明 |
|---|---|---|---|
repo.id |
id |
Number | 仓库 ID |
repo.name |
name |
String | 仓库名称 |
repo.full_name |
full_name |
String | 完整名称 (owner/repo) |
repo.html_url |
html_url |
String | 仓库 URL |
repo.description |
description |
String | 描述 |
repo.stargazers_count |
stargazers_count |
Number | Star 数 |
repo.forks_count |
forks_count |
Number | Fork 数 |
repo.language |
language |
String | 主要编程语言 |
repo.created_at |
created_at |
String | 创建时间 (ISO 8601) |
repo.owner.login |
owner.login |
String | 所有者用户名 |
端点: POST https://openrouter.ai/api/v1/chat/completions
认证: Bearer Token (OPENROUTER_API_KEY)
请求头:
| 头部 | 值 | 必需 | 说明 |
|---|---|---|---|
Authorization |
Bearer <OPENROUTER_API_KEY> |
✅ | API 密钥 |
Content-Type |
application/json |
✅ | 请求格式 |
HTTP-Referer |
https://openclaw.ai |
✅ | 推荐站点标识 |
X-Title |
OpenClaw HR Agent |
✅ | 应用名称 |
请求体:
{
"model": "openai/gpt-4o-mini",
"messages": [
{
"role": "user",
"content": "请用中文总结这个 GitHub 项目的亮点(3句话以内):\n\n项目名称: owner/repo\n描述: 项目描述\n语言: TypeScript\n星数: 5678\nFork: 890\n\n亮点:"
}
],
"max_tokens": 150,
"temperature": 0.7
}响应体:
{
"id": "chatcmpl-xxx",
"object": "chat.completion",
"created": 1700000000,
"model": "openai/gpt-4o-mini",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "这是一个创新的 TypeScript 项目,具有出色的可维护性。社区活跃度高,文档完善。适合作为学习现代前端开发的参考案例。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 45,
"completion_tokens": 32,
"total_tokens": 77
}
}提取摘要:
const summary = result.choices[0].message.content.trim();错误处理:
- 网络错误 / 超时 → 使用备用摘要
'AI 摘要暂不可用' - API 返回错误 → 记录日志并跳过该仓库
- 响应无 choices → 使用备用摘要
标准消息结构:
🔥 GitHub Trending 今日推荐
1. owner/repo-name
⭐ 5678 | 🍴 890 | TypeScript
📝 AI 生成的摘要文本(3句话)
🔗 https://github.com/owner/repo-name
2. owner/another-repo
⭐ 4321 | 🍴 567 | Python
📝 另一个仓库的摘要...
🔗 https://github.com/owner/another-repo
[... 更多仓库]
每个仓库包含:
- 序号和仓库完整名称
- Star 数、Fork 数、编程语言
- AI 生成的亮点摘要(3句话以内)
- GitHub 仓库链接
当前实现依赖 OpenClaw 的 message.send() 方法,支持:
| 渠道 | 配置变量 | 目标格式 |
|---|---|---|
| Telegram | NOTIFY_CHANNEL="telegram" |
<bot_token>:<chat_id> |
| Feishu | NOTIFY_CHANNEL="feishu" |
Webhook URL |
| Discord | NOTIFY_CHANNEL="discord" |
Webhook URL |
适配新渠道:
编辑 scripts/trending.js 中的 sendNotification() 函数:
async function sendNotification(notifications) {
let message = buildMessage(notifications); // 构建消息
// 根据渠道使用不同的发送逻辑
switch (CONFIG.notifyChannel) {
case 'telegram':
await sendTelegram(message, CONFIG.notifyTarget);
break;
case 'feishu':
await sendFeishu(message, CONFIG.notifyTarget);
break;
case 'discord':
await sendDiscord(message, CONFIG.notifyTarget);
break;
default:
console.log('📢 通知内容:\n', message); // 降级到控制台输出
}
}
// 实现具体发送函数
async function sendTelegram(text, target) {
const [botToken, chatId] = target.split(':');
const url = `https://api.telegram.org/bot${botToken}/sendMessage`;
const body = { chat_id: chatId, text, parse_mode: 'Markdown' };
// ... fetch 实现
}const CONFIG = {
githubToken: process.env.GITHUB_TOKEN,
openrouterKey: process.env.OPENROUTER_API_KEY,
notifyChannel: process.env.NOTIFY_CHANNEL || 'telegram',
notifyTarget: process.env.NOTIFY_TARGET,
maxRepos: parseInt(process.env.MAX_REPOS) || 5,
openrouterModel: process.env.OPENROUTER_MODEL || 'openai/gpt-4o-mini'
};| 配置项 | 环境变量 | 类型 | 默认 | 说明 |
|---|---|---|---|---|
githubToken |
GITHUB_TOKEN |
String | - | GitHub PAT (必需) |
openrouterKey |
OPENROUTER_API_KEY |
String | - | OpenRouter Key (必需) |
notifyChannel |
NOTIFY_CHANNEL |
String | telegram |
通知渠道 |
notifyTarget |
NOTIFY_TARGET |
String | - | 目标标识 (必需) |
maxRepos |
MAX_REPOS |
Number | 5 |
最大仓库数 |
openrouterModel |
OPENROUTER_MODEL |
String | openai/gpt-4o-mini |
AI 模型 |
| 模型名称 | 特点 | 推荐场景 |
|---|---|---|
openai/gpt-4o-mini |
快速、经济 | 日常使用 ✅ |
openai/gpt-4o |
高质量、稍慢 | 高精度摘要 |
anthropic/claude-3.5-sonnet |
智能、长文本 | 复杂项目分析 |
google/gemini-2.0-flash-001 |
快速、多语言 | 多语言支持 |
meta-llama/llama-3.3-70b-instruct |
开源、可控 | 本地部署偏好 |
💡 提示:模型列表请查看 OpenRouter 官方模型页
| 代码 | 含义 | 可能原因 | 解决方案 |
|---|---|---|---|
0 |
成功 | - | - |
1 |
一般错误 | 环境变量缺失、API 调用失败 | 检查日志,验证配置 |
2 |
配置错误 | GITHUB_TOKEN 未设置 | 设置 GITHUB_TOKEN |
3 |
网络错误 | 无法访问 GitHub/OpenRouter | 检查网络连接 |
4 |
API 限流 | GitHub/OpenRouter 速率限制 | 降低请求频率,使用更少仓库数 |
通过 LOG_LEVEL 控制输出详细程度:
LOG_LEVEL=debug node scripts/trending.js # 最详细
LOG_LEVEL=info node scripts/trending.js # 默认
LOG_LEVEL=warn node scripts/trending.js # 仅警告
LOG_LEVEL=error node scripts/trending.js # 仅错误日志级别映射:
debug- 包含所有 HTTP 请求详情、API 响应体info- 标准运行信息(默认)warn- 警告信息error- 仅错误信息
// 自定义发送逻辑
async function sendToCustomWebhook(notifications) {
const webhookUrl = process.env.CUSTOM_WEBHOOK_URL;
const payload = {
text: buildMessage(notifications),
timestamp: new Date().toISOString(),
source: 'github-trending-notifier'
};
const response = await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`Webhook failed: ${response.status}`);
}
}// 使用 SQLite/PostgreSQL 存储历史记录
import Database from 'better-sqlite3';
const db = new Database('trending.db');
// 保存仓库到数据库
function saveRepos(repos) {
const stmt = db.prepare(`
INSERT OR IGNORE INTO repos (github_id, name, stars, language, fetched_at)
VALUES (?, ?, ?, ?, datetime('now'))
`);
for (const repo of repos) {
stmt.run(repo.id, repo.full_name, repo.stargazers_count, repo.language);
}
}| 指标 | 典型值 | 说明 |
|---|---|---|
| API 调用次数 | 1 (GitHub) + N (OpenRouter) | N = MAX_REPOS |
| 执行时间 | 10-30 秒 | 受网络延迟和 AI 生成速度影响 |
| 内存占用 | < 50 MB | 纯 Node.js,无重型依赖 |
| 网络请求 | 1+N 次外部调用 | 可配置并发数优化 |
API 版本: v1.0.0
最后更新: 2025-03-08