Rename to hkt.sh
This commit is contained in:
206
scripts/nodeseek-vp404-checkin.mjs
Normal file
206
scripts/nodeseek-vp404-checkin.mjs
Normal file
@@ -0,0 +1,206 @@
|
||||
import WebSocket from 'ws';
|
||||
import { appendFileSync } from 'fs';
|
||||
|
||||
const CDP_PORT = 18800;
|
||||
const COOKIE_VALUE = '3cfeb30b562daec31ba63bf64fdb3838';
|
||||
const TARGET_URL = 'https://www.nodeseek.com';
|
||||
const LOG_FILE = '/Users/jianzhang/.openclaw/workspace/scripts/checkin.log';
|
||||
|
||||
let msgId = 1;
|
||||
let pendingCallbacks = new Map();
|
||||
let loadEventResolve = null;
|
||||
|
||||
function log(message) {
|
||||
const timestamp = new Date().toISOString();
|
||||
const logLine = `[${timestamp}] [VP404] ${message}\n`;
|
||||
console.log(logLine.trim());
|
||||
try {
|
||||
appendFileSync(LOG_FILE, logLine);
|
||||
} catch (e) {
|
||||
console.error('Failed to write log:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function send(ws, method, params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = msgId++;
|
||||
const msg = JSON.stringify({ id, method, params });
|
||||
pendingCallbacks.set(id, { resolve, reject });
|
||||
ws.send(msg);
|
||||
|
||||
setTimeout(() => {
|
||||
if (pendingCallbacks.has(id)) {
|
||||
pendingCallbacks.delete(id);
|
||||
reject(new Error(`Timeout for ${method}`));
|
||||
}
|
||||
}, 30000);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
log('开始 NodeSeek VP404 签到任务');
|
||||
|
||||
let ws;
|
||||
let targetId = null;
|
||||
|
||||
try {
|
||||
// Step 1: Get browser WebSocket URL
|
||||
log('获取 CDP 连接信息...');
|
||||
const resp = await fetch(`http://127.0.0.1:${CDP_PORT}/json/version`);
|
||||
const version = await resp.json();
|
||||
const browserWsUrl = version.webSocketDebuggerUrl;
|
||||
log(`Browser WS: ${browserWsUrl}`);
|
||||
|
||||
// Step 2: Connect to browser
|
||||
ws = new WebSocket(browserWsUrl);
|
||||
|
||||
ws.on('message', (data) => {
|
||||
try {
|
||||
const msg = JSON.parse(data.toString());
|
||||
|
||||
// Handle command responses
|
||||
if (msg.id && pendingCallbacks.has(msg.id)) {
|
||||
const { resolve, reject } = pendingCallbacks.get(msg.id);
|
||||
pendingCallbacks.delete(msg.id);
|
||||
if (msg.error) {
|
||||
reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
||||
} else {
|
||||
resolve(msg.result);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle load event
|
||||
if (msg.method === 'Page.loadEventFired' && loadEventResolve) {
|
||||
loadEventResolve();
|
||||
loadEventResolve = null;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
ws.on('open', resolve);
|
||||
ws.on('error', reject);
|
||||
});
|
||||
log('CDP 连接成功');
|
||||
|
||||
// Step 3: Create new target
|
||||
log('创建新标签页...');
|
||||
const targetResult = await send(ws, 'Target.createTarget', {
|
||||
url: 'about:blank'
|
||||
});
|
||||
targetId = targetResult.targetId;
|
||||
log(`Target ID: ${targetId}`);
|
||||
|
||||
// Step 4: Get target's WebSocket URL via HTTP
|
||||
const targetsResp = await fetch(`http://127.0.0.1:${CDP_PORT}/json`);
|
||||
const targets = await targetsResp.json();
|
||||
const pageTarget = targets.find(t => t.id === targetId);
|
||||
|
||||
if (!pageTarget) {
|
||||
throw new Error('找不到创建的标签页');
|
||||
}
|
||||
|
||||
const pageWsUrl = pageTarget.webSocketDebuggerUrl;
|
||||
log(`Page WS: ${pageWsUrl}`);
|
||||
|
||||
// Step 5: Close browser connection and connect to page
|
||||
ws.close();
|
||||
await sleep(500);
|
||||
|
||||
ws = new WebSocket(pageWsUrl);
|
||||
ws.on('message', (data) => {
|
||||
try {
|
||||
const msg = JSON.parse(data.toString());
|
||||
|
||||
if (msg.id && pendingCallbacks.has(msg.id)) {
|
||||
const { resolve, reject } = pendingCallbacks.get(msg.id);
|
||||
pendingCallbacks.delete(msg.id);
|
||||
if (msg.error) {
|
||||
reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
||||
} else {
|
||||
resolve(msg.result);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.method === 'Page.loadEventFired' && loadEventResolve) {
|
||||
loadEventResolve();
|
||||
loadEventResolve = null;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
ws.on('open', resolve);
|
||||
ws.on('error', reject);
|
||||
});
|
||||
log('已连接到页面');
|
||||
|
||||
// Step 6: Enable domains
|
||||
await send(ws, 'Page.enable');
|
||||
await send(ws, 'Network.enable');
|
||||
|
||||
// Step 7: Set cookie
|
||||
log('设置 Cookie...');
|
||||
await send(ws, 'Network.setCookie', {
|
||||
name: '_nk',
|
||||
value: COOKIE_VALUE,
|
||||
domain: '.nodeseek.com',
|
||||
path: '/'
|
||||
});
|
||||
log('Cookie 设置成功');
|
||||
|
||||
// Step 8: Navigate
|
||||
log('导航到 NodeSeek...');
|
||||
const loadPromise = new Promise(resolve => { loadEventResolve = resolve; });
|
||||
await send(ws, 'Page.navigate', { url: TARGET_URL });
|
||||
|
||||
log('等待页面加载...');
|
||||
await loadPromise;
|
||||
log('页面加载完成');
|
||||
|
||||
// Step 9: Wait 8 seconds
|
||||
log('等待 8 秒...');
|
||||
await sleep(8000);
|
||||
|
||||
// Step 10: Call attendance API
|
||||
log('调用签到 API...');
|
||||
const evalResult = await send(ws, 'Runtime.evaluate', {
|
||||
expression: `fetch('/api/attendance',{
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json'},
|
||||
body:JSON.stringify({random:true})
|
||||
}).then(r => r.json()).catch(e => ({error: e.message}))`,
|
||||
returnByValue: true,
|
||||
awaitPromise: true
|
||||
});
|
||||
|
||||
const result = evalResult.result.value;
|
||||
log(`签到结果: ${JSON.stringify(result)}`);
|
||||
|
||||
// Step 11: Close page
|
||||
log('关闭标签页...');
|
||||
await send(ws, 'Page.close');
|
||||
|
||||
ws.close();
|
||||
log('签到任务完成 ✓');
|
||||
|
||||
} catch (error) {
|
||||
log(`错误: ${error.message}`);
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
try {
|
||||
ws.close();
|
||||
} catch (e) {}
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user