我的插件源:https://ksmirror.fjgjkg.xyz/market.json
注:更换完源后记得重启koishi,不然可能无法访问插件商店。
index.js的代码请用评论里的,这里的是老版本有bug
接下来是教程部分(该项目实际上是https://shangxueink.github.io/koishi-registry-aggregator/market.json 的镜像,因为github.io在国内不好访问,所以专门做个镜像)
本教程教你如何把 ksmirror 部署到 Cloudflare Workers,实现每 25 分钟自动拉取并缓存市场清单。
1. 准备工作
2. 创建项目目录
mkdir ksmirror && cd ksmirror
3. 复制文件
wrangler.toml
name = "ksmirror"
main = "index.js"
compatibility_date = "2024-05-01"
kv_namespaces = [
{ binding = "CACHE", id = "YOUR_KV_ID", preview_id = "YOUR_PREVIEW_KV_ID" }
]
[triggers]
crons = ["*/25 * * * *"]
替换 YOUR_KV_ID 。
index.js
export default {
async fetch(req, env) {
const url = new URL(req.url);
if (url.pathname !== '/market.json') {
return new Response('Not Found', { status: 404 });
}
try {
// 1. 先看 KV 缓存
const cached = await env.CACHE.get('market.json', 'text');
if (cached) {
return new Response(cached, {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=1500',
'X-Cache': 'HIT'
}
});
}
// 2. 拉取上游
const upstream = await fetch(
'https://shangxueink.github.io/koishi-registry-aggregator/market.json',
{ cf: { cacheTtl: 0 } }
);
if (!upstream.ok) {
return new Response(`Upstream ${upstream.status}`, { status: 502 });
}
// 3. 过滤非法 JSON 记录
const raw = await upstream.text();
const filtered = filterValidPlugins(raw);
// 4. 写 KV 并返回
const body = JSON.stringify(filtered, null, 2);
await env.CACHE.put('market.json', body, { expirationTtl: 1500 });
return new Response(body, {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=1500',
'X-Cache': 'MISS'
}
});
} catch (e) {
return new Response('Internal Error: ' + e.message, { status: 500 });
}
},
async scheduled(_, env) {
try {
const r = await fetch(
'https://shangxueink.github.io/koishi-registry-aggregator/market.json',
{ cf: { cacheTtl: 0 } }
);
if (!r.ok) {
console.error('Upstream', r.status);
return;
}
const raw = await r.text();
const filtered = filterValidPlugins(raw);
await env.CACHE.put('market.json', JSON.stringify(filtered, null, 2), {
expirationTtl: 1500
});
console.log('KV refreshed');
} catch (e) {
console.error('Scheduled error', e);
}
}
};
// ---------- 工具函数 ----------
function filterValidPlugins(rawText) {
let arr;
try {
// 先整体 parse 一次
arr = JSON.parse(rawText);
} catch {
// 整体都不是合法 JSON,直接返回空数组
return [];
}
if (!Array.isArray(arr)) return [];
// 逐条二次校验:能 stringify → parse 成功的才保留
return arr.filter(item => {
try {
JSON.parse(JSON.stringify(item));
return item && typeof item === 'object';
} catch {
return false;
}
});
}
4. 登录并创建 KV
wrangler login
wrangler kv namespace create CACHE
把返回的 id 填进 wrangler.toml。(preview_id 不用管
5. 部署
wrangler deploy
6. 绑定自定义域名(建议,防止被墙
- 在 Cloudflare Dashboard → Workers →
ksmirror→ Settings → Triggers → Custom Domains 添加ksmirror.你的域名.顶级域名 - 或手动加一条 CNAME:
ksmirror CNAME ksmirror.<your-account>.workers.dev
7. 验证(以我的源为例
curl https://ksmirror.fjgjkg.xyz/market.json
常见问题
- 域名解析失败: 确保 DNS 记录已生效,等待 1-2 分钟。
- Requests 超标: 提高浏览器缓存时间(如
max-age=7200)。