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 11e6608 commit adac373
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 116 deletions.
4 changes: 2 additions & 2 deletions services/login.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const fetch = require("node-fetch");
const { saveToken, headers, loadProxies } = require("../utils/file");
const { headers, loadProxies } = require("../utils/file");
const { HttpsProxyAgent } = require("https-proxy-agent");
const { logger } = require("../utils/logger");
const fs = require('fs');
const { verifyToken, getExistingToken } = require("../utils/token");
const { saveToken, verifyToken, getExistingToken } = require("../utils/token");
const { CONFIG_PATHS } = require('../config');

// Add delay utility function at the top
Expand Down
32 changes: 1 addition & 31 deletions utils/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,6 @@ const fs = require("fs").promises;
const { logger } = require("./logger");
const { CONFIG_PATHS, DATA_PATHS } = require('../config');

// Function to save the token
async function saveToken(data) {
try {
let tokens = [];
try {
const fileData = await fs.readFile(DATA_PATHS.TOKENS_FILE, 'utf8');
tokens = JSON.parse(fileData);
} catch (error) {
logger("No previous tokens found.", "error");
}

const tokenIndex = tokens.findIndex(token => token.username === data.username);

if (tokenIndex !== -1) {
tokens[tokenIndex] = data;
logger(`Token for ${data.username} updated.`);
} else {
tokens.push(data);
logger(`Token for ${data.username} added.`);
}

await fs.writeFile(DATA_PATHS.TOKENS_FILE, JSON.stringify(tokens, null, 2));
logger('Token saved successfully!', "success");

} catch (error) {
logger('Error saving token:', "error", error);
}
}


// Function to read all saved tokens
async function readToken() {
try {
Expand Down Expand Up @@ -66,4 +36,4 @@ const headers = {
"sec-fetch-site": "none",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
}
module.exports = { saveToken, readToken, loadProxies, headers };
module.exports = { readToken, loadProxies, headers };
226 changes: 143 additions & 83 deletions utils/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,112 +8,172 @@ const { DATA_PATHS, CONFIG_PATHS } = require('../config');
const TOKEN_FILE = DATA_PATHS.TOKENS_FILE;
const ACCOUNT_FILE = CONFIG_PATHS.ACCOUNTS_FILE;

// 读取账号信息
async function readAccountCredentials() {

// Helper function to add delay
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

// Function to save the token with retry mechanism
async function saveToken(data, retries = 3, backoff = 1000) {
for (let i = 0; i < retries; i++) {
try {
const fileData = await fs.readFile(ACCOUNT_FILE, 'utf8');
return fileData
.split('\n')
.filter(line => line.trim() !== '')
.map(line => {
const [email, password] = line.split(':').map(s => s.trim());
return { email, password };
});
// Create a temporary file for atomic write
const tempFile = `${DATA_PATHS.TOKENS_FILE}.tmp`;

let tokens = [];
try {
const fileData = await fs.readFile(DATA_PATHS.TOKENS_FILE, 'utf8');
tokens = JSON.parse(fileData);
} catch (error) {
logger("No previous tokens found, creating new file.", "info");
}

const tokenIndex = tokens.findIndex(token => token.username === data.username);

if (tokenIndex !== -1) {
tokens[tokenIndex] = data;
logger(`Token for ${data.username} updated.`);
} else {
tokens.push(data);
logger(`Token for ${data.username} added.`);
}

// Write to temporary file first
await fs.writeFile(tempFile, JSON.stringify(tokens, null, 2));

// Atomically rename temp file to actual file
try {
await fs.rename(tempFile, DATA_PATHS.TOKENS_FILE);
logger('Token saved successfully!', "success");
return; // Success - exit the retry loop
} catch (renameError) {
// If rename fails, try to clean up temp file
try {
await fs.unlink(tempFile);
} catch (unlinkError) {
// Ignore unlink errors
}
throw renameError;
}

} catch (error) {
logger('Error reading account credentials:', 'error', error);
return [];
if (i === retries - 1) {
// Last retry failed
logger('Error saving token:', "error", error);
throw error;
}
// Wait before retrying with exponential backoff
await delay(backoff * Math.pow(2, i));
logger(`Retrying token save for ${data.username} (attempt ${i + 2}/${retries})`, "info");
}
}
}

// 读取账号信息
async function readAccountCredentials() {
try {
const fileData = await fs.readFile(ACCOUNT_FILE, 'utf8');
return fileData
.split('\n')
.filter(line => line.trim() !== '')
.map(line => {
const [email, password] = line.split(':').map(s => s.trim());
return { email, password };
});
} catch (error) {
logger('Error reading account credentials:', 'error', error);
return [];
}
}

// 验证token
async function verifyToken(token, API_BASE) {
try {
const response = await fetch(`${API_BASE}/api/points`, {
headers: {
'Authorization': `Bearer ${token}`,
...headers
}
});
return response.status === 200;
} catch (error) {
logger('Error verifying token:', 'error', error);
return false;
}
try {
const response = await fetch(`${API_BASE}/api/points`, {
headers: {
'Authorization': `Bearer ${token}`,
...headers
}
});
return response.status === 200;
} catch (error) {
logger('Error verifying token:', 'error', error);
return false;
}
}

// 获取已存token
async function getExistingToken(username) {
try {
const fileData = await fs.readFile(TOKEN_FILE, 'utf8');
const tokens = JSON.parse(fileData);
const tokenData = tokens.find(t => t.username === username);
return tokenData?.token;
} catch (error) {
return null;
}
try {
const fileData = await fs.readFile(TOKEN_FILE, 'utf8');
const tokens = JSON.parse(fileData);
const tokenData = tokens.find(t => t.username === username);
return tokenData?.token;
} catch (error) {
return null;
}
}

// 直接在token.js中实现token刷新逻辑
async function refreshToken(username, API_BASE, proxy) {
try {
// 获取账号信息
const accounts = await readAccountCredentials();
const account = accounts.find(acc => acc.email === username);

if (!account) {
throw new Error(`No credentials found for ${username}`);
}
try {
// 获取账号信息
const accounts = await readAccountCredentials();
const account = accounts.find(acc => acc.email === username);

// 直接进行登录请求获取新token
const agent = new HttpsProxyAgent(proxy);
const response = await fetch(`${API_BASE}/api/login`, {
method: 'POST',
headers: {
...headers,
'content-type': 'application/json'
},
body: JSON.stringify({
email: account.email,
password: account.password
}),
agent
});

if (response.ok) {
const data = await response.json();
if (data.token) {
// 保存新token
await saveToken({ token: data.token, username });
logger(`Token refreshed for ${username}`, 'success');
return data.token;
}
}
throw new Error(`Failed to refresh token for ${username}`);
} catch (error) {
logger(`Failed to refresh token for ${username}:`, 'error', error);
throw error;
if (!account) {
throw new Error(`No credentials found for ${username}`);
}

// 直接进行登录请求获取新token
const agent = new HttpsProxyAgent(proxy);
const response = await fetch(`${API_BASE}/api/login`, {
method: 'POST',
headers: {
...headers,
'content-type': 'application/json'
},
body: JSON.stringify({
email: account.email,
password: account.password
}),
agent
});

if (response.ok) {
const data = await response.json();
if (data.token) {
// 保存新token
await saveToken({ token: data.token, username });
logger(`Token refreshed for ${username}`, 'success');
return data.token;
}
}
throw new Error(`Failed to refresh token for ${username}`);
} catch (error) {
logger(`Failed to refresh token for ${username}:`, 'error', error);
throw error;
}
}

// API调用的包装函数
async function withTokenRefresh(apiCall, username, token, API_BASE, proxy) {
try {
return await apiCall(token);
} catch (error) {
if (error.status === 401 || error.status === 403) {
logger(`Token expired for ${username}, attempting refresh...`);
const newToken = await refreshToken(username, API_BASE, proxy);
if (newToken) {
return await apiCall(newToken);
}
}
throw error;
try {
return await apiCall(token);
} catch (error) {
if (error.status === 401 || error.status === 403) {
logger(`Token expired for ${username}, attempting refresh...`);
const newToken = await refreshToken(username, API_BASE, proxy);
if (newToken) {
return await apiCall(newToken);
}
}
throw error;
}
}

module.exports = {
verifyToken,
getExistingToken,
refreshToken,
withTokenRefresh
verifyToken,
getExistingToken,
refreshToken,
withTokenRefresh
};

0 comments on commit adac373

Please sign in to comment.