Refactor agent.user.js to improve server management and logging. Introduce heartbeat reporting functionality and update the match pattern for broader compatibility. Enhance debug logging for better traceability.
This commit is contained in:
@@ -3,7 +3,8 @@
|
|||||||
// @namespace http://baf.thuanle.me
|
// @namespace http://baf.thuanle.me
|
||||||
// @version 2025.07.31
|
// @version 2025.07.31
|
||||||
// @author TL
|
// @author TL
|
||||||
// @match https://www.binance.com/en/alpha/bsc/*
|
// @description Automated trading agent for Binance Alpha Farm
|
||||||
|
// @match https://www.binance.com/*
|
||||||
// @run-at document-idle
|
// @run-at document-idle
|
||||||
// @grant GM_setValue
|
// @grant GM_setValue
|
||||||
// @grant GM_getValue
|
// @grant GM_getValue
|
||||||
@@ -20,6 +21,20 @@
|
|||||||
(async () => {
|
(async () => {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// ====== Servers ======
|
||||||
|
const BAF_SERVERS = {
|
||||||
|
local: { label: '🏠 Local', url: 'http://localhost:3000' },
|
||||||
|
prod: { label: '🌐 Prod', url: 'https://baf.thuanle.me' },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const CONFIG = {
|
||||||
|
heartbeat_interval: 10000,
|
||||||
|
is_debug: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ====== Storage ======
|
// ====== Storage ======
|
||||||
const STORAGE = {
|
const STORAGE = {
|
||||||
key_token: 'baf-agent-token',
|
key_token: 'baf-agent-token',
|
||||||
@@ -31,18 +46,15 @@
|
|||||||
setServerMode: (mode) => GM_setValue(STORAGE.key_server_mode, mode),
|
setServerMode: (mode) => GM_setValue(STORAGE.key_server_mode, mode),
|
||||||
};
|
};
|
||||||
|
|
||||||
// ====== Servers (có icon) ======
|
|
||||||
const BAF_SERVERS = {
|
|
||||||
local: { label: '🏠 Local', url: 'http://localhost:3000' },
|
|
||||||
prod: { label: '🌐 Prod', url: 'https://baf.thuanle.me' },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ====== Utility ======
|
// ====== Utility ======
|
||||||
const TL = {
|
const TL = {
|
||||||
log: (msg, ...args) => GM_log(`[TL]\n${msg}`, ...args),
|
debug: (tag, msg, ...args) => CONFIG.is_debug && GM_log(`[TL] [${tag}]\n${msg}`, ...args),
|
||||||
error: (msg, ...args) => GM_log(`[TL] [ERROR] ❌\n${msg}`, ...args),
|
log: (tag, msg, ...args) => GM_log(`[TL] [${tag}]\n${msg}`, ...args),
|
||||||
|
error: (tag, msg, ...args) => GM_log(`[TL] [ERROR] [${tag}] ❌\n${msg}`, ...args),
|
||||||
|
|
||||||
noti: (title, text, timeout = 2500) => {
|
noti: (title, text, timeout = 2500) => {
|
||||||
if (typeof GM_notification === 'function') {
|
if (typeof GM_notification === 'function') {
|
||||||
GM_notification({ title, text, timeout });
|
GM_notification({ title, text, timeout });
|
||||||
@@ -58,7 +70,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// ====== DOM helpers ======
|
// ====== DOM helpers ======
|
||||||
TL.ui = {
|
TL.dom = {
|
||||||
isVisible: (el) => {
|
isVisible: (el) => {
|
||||||
if (!el) return false;
|
if (!el) return false;
|
||||||
const cs = getComputedStyle(el);
|
const cs = getComputedStyle(el);
|
||||||
@@ -109,7 +121,7 @@
|
|||||||
let data = text;
|
let data = text;
|
||||||
const isJSON = /content-type:\s*application\/json/i.test(resp.responseHeaders || '');
|
const isJSON = /content-type:\s*application\/json/i.test(resp.responseHeaders || '');
|
||||||
if (isJSON) { try { data = JSON.parse(text); } catch { } }
|
if (isJSON) { try { data = JSON.parse(text); } catch { } }
|
||||||
TL.log(`${init.method} ${resp.status} ${url}`, data);
|
TL.debug(`net`,`${init.method} ${resp.status} ${url}`, data);
|
||||||
resolve({
|
resolve({
|
||||||
status: resp.status,
|
status: resp.status,
|
||||||
ok: resp.status >= 200 && resp.status < 300,
|
ok: resp.status >= 200 && resp.status < 300,
|
||||||
@@ -162,7 +174,7 @@
|
|||||||
get: (path, params, init = {}) => BAF.request('GET', path, { params, headers: init.headers }),
|
get: (path, params, init = {}) => BAF.request('GET', path, { params, headers: init.headers }),
|
||||||
post: (path, body, init = {}) => BAF.request('POST', path, { body, headers: init.headers }),
|
post: (path, body, init = {}) => BAF.request('POST', path, { body, headers: init.headers }),
|
||||||
|
|
||||||
ping: () => BAF.post('/agent/ping'),
|
ping: (status) => BAF.post('/agent/ping', status),
|
||||||
};
|
};
|
||||||
|
|
||||||
// ====== Cấu hình menu ======
|
// ====== Cấu hình menu ======
|
||||||
@@ -175,13 +187,13 @@
|
|||||||
await STORAGE.setServerMode(next);
|
await STORAGE.setServerMode(next);
|
||||||
const nsv = await BAF.getServer();
|
const nsv = await BAF.getServer();
|
||||||
const msg = `Switched to ${nsv.label} (${nsv.url})`;
|
const msg = `Switched to ${nsv.label} (${nsv.url})`;
|
||||||
TL.log(msg);
|
TL.debug(`BAF`,msg);
|
||||||
TL.noti('BAF Server Switched', msg);
|
TL.noti('BAF Server Switched', msg);
|
||||||
|
|
||||||
await TL.delay(300);
|
await TL.delay(300);
|
||||||
location.reload();
|
location.reload();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
TL.error('switch server error', e);
|
TL.error('BAF','switch server error', e);
|
||||||
TL.noti('BAF Server Switched', `Switch server error: ${e.message}`);
|
TL.noti('BAF Server Switched', `Switch server error: ${e.message}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -198,11 +210,11 @@
|
|||||||
const resStr =
|
const resStr =
|
||||||
`Server: ${s.label} (${s.url})\n` +
|
`Server: ${s.label} (${s.url})\n` +
|
||||||
`Status: ${res.ok ? 'Connected ✅' : 'Failed ❌'} (${res.status})`;
|
`Status: ${res.ok ? 'Connected ✅' : 'Failed ❌'} (${res.status})`;
|
||||||
TL.log(resStr);
|
TL.debug(`BAF`,resStr);
|
||||||
TL.noti('BAF Server', resStr);
|
TL.noti('BAF Server', resStr);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const resStr = `ping error: ${e.message}`;
|
const resStr = `ping error: ${e.message}`;
|
||||||
TL.error(resStr);
|
TL.error('BAF',resStr);
|
||||||
TL.noti('BAF Server', resStr);
|
TL.noti('BAF Server', resStr);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -215,7 +227,7 @@
|
|||||||
const loginBtn = document.querySelector('#toLoginPage');
|
const loginBtn = document.querySelector('#toLoginPage');
|
||||||
const regBtn = document.querySelector('#toRegisterPage');
|
const regBtn = document.querySelector('#toRegisterPage');
|
||||||
|
|
||||||
if (TL.dom.isVisible?.(loginBtn) || TL.dom.isVisible?.(regBtn)) return false;
|
if (TL.dom.isVisible?.(loginBtn) || TL.ui.isVisible?.(regBtn)) return false;
|
||||||
if (!loginBtn && !regBtn) return true;
|
if (!loginBtn && !regBtn) return true;
|
||||||
|
|
||||||
return null; // đang load hoặc chưa rõ
|
return null; // đang load hoặc chưa rõ
|
||||||
@@ -223,17 +235,18 @@
|
|||||||
|
|
||||||
isLoggedIn: async (timeoutMs = 6000, pollMs = 200) => {
|
isLoggedIn: async (timeoutMs = 6000, pollMs = 200) => {
|
||||||
const deadline = Date.now() + timeoutMs;
|
const deadline = Date.now() + timeoutMs;
|
||||||
|
TL.debug(`BINANCE`,`isLoggedIn: Checking login state...`);
|
||||||
while (Date.now() < deadline) {
|
while (Date.now() < deadline) {
|
||||||
const state = BINANCE.detectLoginState();
|
const state = BINANCE.detectLoginState();
|
||||||
if (state !== null) {
|
if (state !== null) {
|
||||||
TL.log(`[BINANCE] isLoggedIn => ${state ? 'true' : 'false'}`);
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
TL.debug(`BINANCE`,`isLoggedIn: not found. Sleeping...`);
|
||||||
await TL.delay(pollMs);
|
await TL.delay(pollMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fallback = BINANCE.detectLoginState() ?? false;
|
const fallback = BINANCE.detectLoginState() ?? false;
|
||||||
TL.log(`[BINANCE] isLoggedIn (timeout, fallback) => ${fallback ? 'true' : 'false'}`);
|
TL.debug(`BINANCE`,`isLoggedIn (timeout, fallback) => ${fallback ? 'true' : 'false'}`);
|
||||||
return fallback;
|
return fallback;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -241,18 +254,38 @@
|
|||||||
|
|
||||||
// ====== Main ======
|
// ====== Main ======
|
||||||
async function welcome_message() {
|
async function welcome_message() {
|
||||||
|
|
||||||
const s = await BAF.getServer();
|
const s = await BAF.getServer();
|
||||||
const res = await BAF.ping();
|
const res = await BAF.ping();
|
||||||
|
|
||||||
const resStr =
|
const resStr =
|
||||||
`Server: ${s.label} (${s.url})\n` +
|
`Server: ${s.label} (${s.url})\n` +
|
||||||
`Status: ${res.ok ? 'Connected ✅' : 'Failed ❌'} (${res.status})`;
|
`Status: ${res.ok ? 'Connected ✅' : 'Failed ❌'} (${res.status})\n`;
|
||||||
|
|
||||||
TL.log(resStr);
|
TL.log(`BAF`,resStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====== Heartbeat ======
|
||||||
|
async function heartbeat_report() {
|
||||||
|
try {
|
||||||
|
const isLoggedIn = await BINANCE.isLoggedIn();
|
||||||
|
|
||||||
|
const status = {
|
||||||
|
logged_in: isLoggedIn
|
||||||
|
};
|
||||||
|
|
||||||
|
// Log heartbeat
|
||||||
|
TL.debug(`HEARTBEAT`,`${JSON.stringify(status, null, 2)}`);
|
||||||
|
await BAF.ping(status);
|
||||||
|
return status;
|
||||||
|
} catch (e) {
|
||||||
|
TL.error('HEARTBEAT', e.message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ====== Khởi tạo ======
|
// ====== Khởi tạo ======
|
||||||
await welcome_message();
|
await welcome_message();
|
||||||
await createGM_Menu();
|
await createGM_Menu();
|
||||||
|
setInterval(heartbeat_report, CONFIG.heartbeat_interval);
|
||||||
|
|
||||||
})();
|
})();
|
||||||
Reference in New Issue
Block a user