Rename to hkt.sh
This commit is contained in:
186
scripts/peekabo-monitor.js
Normal file
186
scripts/peekabo-monitor.js
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Peekabo Networks 自动续费监控脚本
|
||||
* 每天 00:05 检测账单,有账单自动用余额续费
|
||||
* 续费失败通知 Telegram
|
||||
*/
|
||||
|
||||
const https = require('https');
|
||||
|
||||
// ========== 配置 ==========
|
||||
const ACCOUNTS = [
|
||||
{ email: 'mail@mailpre.com', password: 'hawvys-Vitcy7-kyxzuf' },
|
||||
{ email: 'mf0@msn.com', password: '@a110110' },
|
||||
{ email: 'yxvmhk@qq.com', password: '@a110110' }
|
||||
];
|
||||
|
||||
const TG_BOT_TOKEN = '8300905342:AAH3Q78FuR5Exrw2zWYJHFRyVeLlws3xnww';
|
||||
const TG_CHAT_ID = '165067365';
|
||||
const BASE_URL = 'gigo.peekabo.io';
|
||||
|
||||
// ========== Telegram 通知 ==========
|
||||
async function sendTG(message) {
|
||||
const data = JSON.stringify({ chat_id: TG_CHAT_ID, text: message, parse_mode: 'HTML' });
|
||||
return new Promise((resolve) => {
|
||||
const req = https.request({
|
||||
hostname: 'api.telegram.org',
|
||||
path: `/bot${TG_BOT_TOKEN}/sendMessage`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
}, res => { let b = ''; res.on('data', c => b += c); res.on('end', () => resolve(b)); });
|
||||
req.write(data);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
// ========== HTTP 请求 ==========
|
||||
function request(options, postData = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = https.request(options, res => {
|
||||
let body = '';
|
||||
res.on('data', c => body += c);
|
||||
res.on('end', () => resolve({
|
||||
status: res.statusCode,
|
||||
headers: res.headers,
|
||||
body,
|
||||
cookies: res.headers['set-cookie'] || []
|
||||
}));
|
||||
});
|
||||
req.on('error', reject);
|
||||
if (postData) req.write(postData);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
// ========== 检测单个账户 ==========
|
||||
async function checkAccount(account) {
|
||||
const result = { email: account.email, invoices: [], paid: [], failed: [], error: null };
|
||||
let cookies = '';
|
||||
|
||||
try {
|
||||
// 1. 获取登录页面拿 token
|
||||
const loginPage = await request({
|
||||
hostname: BASE_URL,
|
||||
path: '/index.php?rp=/login',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
const tokenMatch = loginPage.body.match(/name="token" value="([^"]+)"/);
|
||||
if (!tokenMatch) { result.error = '获取token失败'; return result; }
|
||||
|
||||
cookies = loginPage.cookies.map(c => c.split(';')[0]).join('; ');
|
||||
|
||||
// 2. 登录
|
||||
const loginData = `token=${tokenMatch[1]}&username=${encodeURIComponent(account.email)}&password=${encodeURIComponent(account.password)}`;
|
||||
const loginRes = await request({
|
||||
hostname: BASE_URL,
|
||||
path: '/index.php?rp=/login',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Cookie': cookies
|
||||
}
|
||||
}, loginData);
|
||||
|
||||
// 更新 cookies
|
||||
if (loginRes.cookies.length) {
|
||||
cookies = loginRes.cookies.map(c => c.split(';')[0]).join('; ');
|
||||
}
|
||||
|
||||
// 3. 检查是否登录成功 - 访问客户区
|
||||
const dashboard = await request({
|
||||
hostname: BASE_URL,
|
||||
path: '/clientarea.php',
|
||||
method: 'GET',
|
||||
headers: { 'Cookie': cookies }
|
||||
});
|
||||
|
||||
if (!dashboard.body.includes('My Dashboard') && !dashboard.body.includes('Logout')) {
|
||||
result.error = '登录失败';
|
||||
return result;
|
||||
}
|
||||
|
||||
// 4. 获取未付账单
|
||||
const invoicesPage = await request({
|
||||
hostname: BASE_URL,
|
||||
path: '/clientarea.php?action=invoices',
|
||||
method: 'GET',
|
||||
headers: { 'Cookie': cookies }
|
||||
});
|
||||
|
||||
// 匹配未付账单
|
||||
const unpaidRegex = /viewinvoice\.php\?id=(\d+)[^>]*>.*?#\d+.*?<\/a>.*?\$([0-9.]+).*?Unpaid/gs;
|
||||
let match;
|
||||
while ((match = unpaidRegex.exec(invoicesPage.body)) !== null) {
|
||||
result.invoices.push({ id: match[1], amount: parseFloat(match[2]) });
|
||||
}
|
||||
|
||||
// 5. 如果有未付账单,尝试用余额支付
|
||||
for (const inv of result.invoices) {
|
||||
const payRes = await request({
|
||||
hostname: BASE_URL,
|
||||
path: `/viewinvoice.php?id=${inv.id}`,
|
||||
method: 'GET',
|
||||
headers: { 'Cookie': cookies }
|
||||
});
|
||||
|
||||
// 检查是否有 Apply Credit 按钮
|
||||
if (payRes.body.includes('applycredit')) {
|
||||
const creditRes = await request({
|
||||
hostname: BASE_URL,
|
||||
path: `/viewinvoice.php?id=${inv.id}&applycredit=true`,
|
||||
method: 'GET',
|
||||
headers: { 'Cookie': cookies }
|
||||
});
|
||||
|
||||
if (creditRes.body.includes('Paid') || creditRes.status === 302) {
|
||||
result.paid.push(inv);
|
||||
} else {
|
||||
result.failed.push({ ...inv, reason: '支付失败' });
|
||||
}
|
||||
} else {
|
||||
result.failed.push({ ...inv, reason: '无法使用余额' });
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
result.error = err.message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ========== 主函数 ==========
|
||||
async function main() {
|
||||
console.log(`[${new Date().toISOString()}] 开始检测...`);
|
||||
|
||||
let msg = '🔔 <b>Peekabo 账单检测</b>\n\n';
|
||||
let needNotify = false;
|
||||
|
||||
for (const acc of ACCOUNTS) {
|
||||
const r = await checkAccount(acc);
|
||||
msg += `📧 <code>${r.email}</code>\n`;
|
||||
|
||||
if (r.error) {
|
||||
msg += `❌ ${r.error}\n`;
|
||||
needNotify = true;
|
||||
} else if (r.invoices.length === 0) {
|
||||
msg += `✅ 无待付账单\n`;
|
||||
} else {
|
||||
if (r.paid.length) msg += `✅ 已付: ${r.paid.map(i => '$' + i.amount).join(', ')}\n`;
|
||||
if (r.failed.length) {
|
||||
msg += `❌ 失败: ${r.failed.map(i => '$' + i.amount).join(', ')}\n`;
|
||||
needNotify = true;
|
||||
}
|
||||
}
|
||||
msg += '\n';
|
||||
}
|
||||
|
||||
if (needNotify) {
|
||||
await sendTG(msg);
|
||||
console.log('已通知');
|
||||
} else {
|
||||
console.log('全部正常');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user