Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
fanyilun0 authored Jan 16, 2025
1 parent adac373 commit 1997f28
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 50 deletions.
76 changes: 61 additions & 15 deletions services/heartbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ const { readToken, loadProxies, headers } = require("../utils/file");
const { logger } = require("../utils/logger");
const { withTokenRefresh } = require("../utils/token");
const fs = require('fs').promises;
const { DATA_PATHS, HEARTBEAT_INTERVAL, NODE_TEST_INTERVAL } = require('../config');
const { DATA_PATHS, TIME_INTERVALS } = require('../config');

const HEARTBEAT_INTERVAL = TIME_INTERVALS.HEARTBEAT_INTERVAL;
const NODE_TEST_INTERVAL = TIME_INTERVALS.NODE_TEST_INTERVAL;

// 新增:保存points到本地文件
async function savePoints(username, points, timestamp = Date.now()) {
Expand Down Expand Up @@ -74,25 +77,33 @@ async function fetchPoints(token, username, agent, API_BASE) {
// 保存运行时间记录
async function saveRunTimes(username, type, timestamp = Date.now()) {
try {
logger(`开始保存运行时间 - ${username} - ${type}`, 'info');

// 读取现有数据
let timeData = [];
try {
const fileData = await fs.readFile(DATA_PATHS.RUNTIME_FILE, 'utf8');
timeData = JSON.parse(fileData);
} catch (error) {
logger(`读取运行时间文件失败: ${error.message}, 将创建新文件`, 'warn');
timeData = [];
}

const existingIndex = timeData.findIndex(p => p.username === username);
// 计算时间
const nextRun = type === 'heartbeat' ?
timestamp + HEARTBEAT_INTERVAL :
timestamp + NODE_TEST_INTERVAL;

const timeRecord = existingIndex >= 0 ? timeData[existingIndex] : {
// 更新记录
const existingIndex = timeData.findIndex(p => p.username === username);
const timeRecord = {
username,
lastHeartbeat: null,
nextHeartbeat: null,
lastNodeTest: null,
nextNodeTest: null
...(existingIndex >= 0 ? timeData[existingIndex] : {
lastHeartbeat: null,
nextHeartbeat: null,
lastNodeTest: null,
nextNodeTest: null
})
};

if (type === 'heartbeat') {
Expand All @@ -103,40 +114,75 @@ async function saveRunTimes(username, type, timestamp = Date.now()) {
timeRecord.nextNodeTest = nextRun;
}

// 更新数组
if (existingIndex >= 0) {
timeData[existingIndex] = timeRecord;
} else {
timeData.push(timeRecord);
}

await fs.writeFile(DATA_PATHS.RUNTIME_FILE, JSON.stringify(timeData, null, 2));
logger(`Runtime saved for ${username} - ${type}`, 'info');
// 保存数据
const recordToSave = JSON.stringify(timeData, null, 2);
await fs.writeFile(DATA_PATHS.RUNTIME_FILE, recordToSave, 'utf8');

logger(`成功保存运行时间 - ${username}:
- 类型: ${type}
- 当前时间戳: ${timestamp}
- 下次运行时间戳: ${nextRun}`, 'success');

} catch (error) {
logger(`Error saving runtime for ${username}: ${error.message}`, 'error');
logger(`保存运行时间失败 - ${username}: ${error.message}`, 'error');
logger(`错误堆栈: ${error.stack}`, 'debug');
throw error;
}
}

// 检查是否需要运行
async function shouldRun(username, type) {
try {
logger(`检查${username}是否需要运行${type}`, 'info');

const fileData = await fs.readFile(DATA_PATHS.RUNTIME_FILE, 'utf8');
const timeData = JSON.parse(fileData);
logger(`成功读取运行时间记录,共${timeData.length}条记录`, 'info');

const record = timeData.find(p => p.username === username);
if (!record) return true;
if (!record) {
logger(`未找到${username}的运行记录,允许运行`, 'info');
return true;
}

const now = Date.now();
if (type === 'heartbeat') {
return !record.nextHeartbeat || now >= record.nextHeartbeat;
const shouldExecute = !record.nextHeartbeat || now >= record.nextHeartbeat;
const timeLeft = record.nextHeartbeat ? Math.max(0, record.nextHeartbeat - now) : 0;

logger(`${username}的心跳检查:
- 当前时间戳: ${now}
- 下次运行时间戳: ${record.nextHeartbeat || 'null'}
- 剩余时间: ${Math.floor(timeLeft / 1000)}
- 是否运行: ${shouldExecute ? '是' : '否'}`, 'info');

return shouldExecute;
} else {
return !record.nextNodeTest || now >= record.nextNodeTest;
const shouldExecute = !record.nextNodeTest || now >= record.nextNodeTest;
const timeLeft = record.nextNodeTest ? Math.max(0, record.nextNodeTest - now) : 0;

logger(`${username}的节点测试检查:
- 当前时间戳: ${now}
- 下次运行时间戳: ${record.nextNodeTest || 'null'}
- 剩余时间: ${Math.floor(timeLeft / 1000)}
- 是否运行: ${shouldExecute ? '是' : '否'}`, 'info');

return shouldExecute;
}
} catch (error) {
return true; // 如果文件不存在或出错,默认允许运行
logger(`检查${username}运行时间时出错: ${error.message},默认允许运行`, 'warn');
return true;
}
}

// Function to send heartbeat
// 修改 sendHeartbeat 函数,在成功时保存运行时间
async function sendHeartbeat(API_BASE) {
const proxies = await loadProxies();
if (proxies.length === 0) {
Expand Down
46 changes: 41 additions & 5 deletions services/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ async function readUsersFromFile() {
}
}

// 添加简单的文件锁机制
let isWriting = false;
const writeQueue = [];

async function writeWithLock(operation) {
if (isWriting) {
// 如果正在写入,将操作加入队列
await new Promise(resolve => writeQueue.push(resolve));
}

isWriting = true;
try {
await operation();
} finally {
isWriting = false;
if (writeQueue.length > 0) {
// 处理队列中的下一个写入操作
const next = writeQueue.shift();
next();
}
}
}

// 修改:登录函数,增加详细日志
async function login(email, password, API_BASE, proxy) {
try {
Expand Down Expand Up @@ -72,7 +95,11 @@ async function login(email, password, API_BASE, proxy) {
const data = await response.json();
if (data.token) {
logger(`New token received for ${email}`, 'info');
await saveToken({ token: data.token, username: email });
// 使用写入锁保存token
await writeWithLock(async () => {
logger(`Saving token for ${email}...`, 'info');
await saveToken({ token: data.token, username: email });
});
logger(`New login successful for ${email}!`, 'success');
return {
success: true,
Expand Down Expand Up @@ -129,29 +156,38 @@ async function loginWithAllAccounts(API_BASE) {
failedAccounts: []
};

logger(`开始处理账号,共${accounts.length}个`, 'info');

for (let i = 0; i < accounts.length; i++) {
const account = accounts[i];
const proxy = proxies[i % proxies.length];

logger(`Processing account ${i + 1}/${accounts.length}: ${account.email}`, 'info');
logger(`处理第${i + 1}个账号: ${account.email}`, 'info');
const loginResult = await login(account.email, account.password, API_BASE, proxy);

if (loginResult.success) {
if (loginResult.isNewLogin) {
results.newLogins++;
logger(`New login successful for ${account.email}`, 'success');
logger(`${account.email} 新登录成功,当前新登录数: ${results.newLogins}`, 'success');
} else {
results.validTokens++;
logger(`Using existing valid token for ${account.email}`, 'success');
logger(`${account.email} 使用现有token,当前有效token数: ${results.validTokens}`, 'success');
}
} else {
results.failed++;
results.failedAccounts.push({
email: account.email,
error: loginResult.error
});
logger(`Failed to process ${account.email}: ${loginResult.error}`, 'error');
logger(`${account.email} 处理失败,当前失败数: ${results.failed}`, 'error');
}

// 每次循环都输出当前统计
logger(`当前统计:
- 总账号数: ${results.total}
- 有效token数: ${results.validTokens}
- 新登录数: ${results.newLogins}
- 失败数: ${results.failed}`, 'info');
}

logger(`Login process completed:
Expand Down
21 changes: 21 additions & 0 deletions utils/logger.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
const chalk = require('chalk');
const fs = require('fs');
const path = require('path');
const { DATA_PATHS } = require('../config');

// 确保日志目录存在
const logDir = path.join(process.cwd(), 'logs');
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}

// 创建当前日期的日志文件
const getLogFile = () => {
const date = new Date().toISOString().split('T')[0];
return path.join(logDir, `${date}.log`);
};

function logger(message, level = 'info', value = "") {
const now = new Date().toISOString();
Expand All @@ -10,7 +25,13 @@ function logger(message, level = 'info', value = "") {
debug: chalk.magenta,
};
const color = colors[level] || chalk.white;

// 控制台输出(带颜色)
console.log(color(`[${now}] [${level.toUpperCase()}]: ${message}`), chalk.yellow(value));

// 写入文件(不带颜色)
const logMessage = `[${now}] [${level.toUpperCase()}]: ${message} ${value}\n`;
fs.appendFileSync(getLogFile(), logMessage);
}

module.exports = { logger };
Loading

0 comments on commit 1997f28

Please sign in to comment.