generated from template/slidev-template
162 lines
4.7 KiB
TypeScript
162 lines
4.7 KiB
TypeScript
import { app, storage } from './app.ts';
|
||
|
||
export type CloudflareConfig = {
|
||
// Cloudflare 访问地址
|
||
website: string;
|
||
domain: string;
|
||
zone_id: string;
|
||
// 更新IPv4记录的ID
|
||
record_id4: string;
|
||
// 更新IPv6记录的ID
|
||
record_id6: string;
|
||
api_token: string;
|
||
ipv6: string;
|
||
ipv4: string;
|
||
flag: number; // 0: 不更新, 1: 仅IPv4, 2: 仅IPv6, 3: IPv4和IPv6
|
||
time: string; // 上次更新时间戳
|
||
}
|
||
app.route({
|
||
path: 'ip',
|
||
key: 'task',
|
||
description: `执行IP更新任务
|
||
1. 读取配置文件cloudflare.json
|
||
2. 根据flag决定更新IPv4和/或IPv6地址
|
||
3. 获取当前公网IP地址
|
||
4. 如果IP地址有变化则调用 router: cf/update 更新DNS记录
|
||
5. 保存最新的IP地址和更新时间戳到配置文件
|
||
`,
|
||
}).define(async (ctx) => {
|
||
const config = await storage.getItem<CloudflareConfig>('cloudflare.json');
|
||
if (!config) {
|
||
ctx.throw?.('未找到配置');
|
||
}
|
||
const now = Date.now();
|
||
const date = new Date(now);
|
||
const updateIp = async (isV4 = true) => {
|
||
const res = await app.call({ path: 'ip', key: isV4 ? 'v4' : 'v6' });
|
||
if (res.code !== 200) {
|
||
ctx.throw(res.message);
|
||
}
|
||
const newIp = res.body.ip as string;
|
||
const oldIp = isV4 ? config.ipv4 : config.ipv6;
|
||
if (newIp !== oldIp) {
|
||
// IP地址有变化,更新DNS记录
|
||
await app.call({
|
||
path: 'cf', key: 'update', payload: {
|
||
zone_id: config.zone_id,
|
||
record_id: isV4 ? config.record_id4 : config.record_id6,
|
||
domain: config.domain,
|
||
new_ip: newIp,
|
||
api_token: config.api_token,
|
||
type: isV4 ? 'A' : 'AAAA',
|
||
}
|
||
}, {});
|
||
// 更新配置文件中的IP地址
|
||
if (isV4) {
|
||
config.ipv4 = newIp;
|
||
} else {
|
||
config.ipv6 = newIp;
|
||
}
|
||
config.time = date.toLocaleString();
|
||
await storage.setItem('cloudflare.json', config);
|
||
console.log(date.toLocaleString() + ` 更新 ${isV4 ? 'IPv4' : 'IPv6'} 地址为: ${newIp}`);
|
||
} else {
|
||
console.log(date.toLocaleString() + ` ${isV4 ? 'IPv4' : 'IPv6'} 地址未改变: ${newIp}`);
|
||
}
|
||
}
|
||
if (config.flag === 1) {
|
||
await updateIp(true);
|
||
}
|
||
if (config.flag === 2) {
|
||
await updateIp(false);
|
||
}
|
||
if (config.flag === 3) {
|
||
await updateIp(true);
|
||
await updateIp(false);
|
||
}
|
||
ctx.body = { message: '任务完成' };
|
||
}).addTo(app);
|
||
|
||
app.route({
|
||
path: 'ip',
|
||
key: 'init',
|
||
description: '初始化配置文件cloudflare.json',
|
||
}).define(async (ctx) => {
|
||
// 初始化逻辑
|
||
const config = await storage.getItem<CloudflareConfig>('cloudflare.json');
|
||
|
||
const isIpv4 = config?.flag === 1 || config?.flag === 3;
|
||
const isIpv6 = config?.flag === 2 || config?.flag === 3;
|
||
const apiToken = config?.api_token || '';
|
||
if (!apiToken) {
|
||
ctx.throw?.('配置错误:api_token为空');
|
||
}
|
||
const getIp = async (isV4: boolean) => {
|
||
const res = await app.call({ path: 'ip', key: isV4 ? 'v4' : 'v6' });
|
||
if (res.code !== 200) {
|
||
ctx.throw?.(`获取${isV4 ? 'IPv4' : 'IPv6'}地址失败: ` + res.message);
|
||
}
|
||
return res.body.ip as string;
|
||
}
|
||
const createCfRecord = async (isV4: boolean) => {
|
||
const newIp = await getIp(isV4);
|
||
const cfRes = await app.call({
|
||
path: 'cf',
|
||
key: 'create',
|
||
payload: {
|
||
zone_id: config.zone_id,
|
||
domain: config.domain,
|
||
new_ip: newIp,
|
||
api_token: config.api_token,
|
||
type: isV4 ? 'A' : 'AAAA',
|
||
}
|
||
});
|
||
if (cfRes.code !== 200) {
|
||
ctx.throw?.(`创建${isV4 ? 'IPv4' : 'IPv6'}记录失败: ` + cfRes.message);
|
||
}
|
||
console.log(`创建${isV4 ? 'IPv4' : 'IPv6'}记录结果:`, cfRes.body.record_id);
|
||
const record_id = cfRes.body.record_id as string;
|
||
|
||
if (isV4) {
|
||
config.record_id4 = record_id;
|
||
} else {
|
||
config.record_id6 = record_id;
|
||
}
|
||
config.time = new Date().toLocaleString();
|
||
await storage.setItem('cloudflare.json', config);
|
||
}
|
||
let isInit = false;
|
||
if (isIpv4 && config.record_id4 === '') {
|
||
console.log('配置错误:需要更新IPv4地址,但record_id4为空, 正在创建新记录...');
|
||
await createCfRecord(true);
|
||
isInit = true;
|
||
}
|
||
if (isIpv6 && config.record_id6 === '') {
|
||
console.log('配置警告:需要更新IPv6地址,但record_id6为空,正在创建新记录...');
|
||
await createCfRecord(false);
|
||
isInit = true;
|
||
}
|
||
ctx.body = { init: isInit, message: '初始化完成' };
|
||
|
||
}).addTo(app);
|
||
|
||
export const main = async () => {
|
||
const res = await app.call({
|
||
path: 'ip',
|
||
key: 'init',
|
||
});
|
||
if (res.code !== 200) {
|
||
console.error('初始化失败:', res.message);
|
||
return;
|
||
}
|
||
if (res.body.init) {
|
||
console.log('初始化完成,并创建了必要的DNS记录,任务结束。');
|
||
return;
|
||
}
|
||
await app.call({
|
||
path: 'ip',
|
||
key: 'task',
|
||
})
|
||
}
|
||
|