diff --git a/agent.user.js b/agent.user.js index 4938a15..7839b98 100644 --- a/agent.user.js +++ b/agent.user.js @@ -3,7 +3,8 @@ // @namespace http://baf.thuanle.me // @version 2025.07.31 // @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 // @grant GM_setValue // @grant GM_getValue @@ -20,6 +21,20 @@ (async () => { '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 ====== const STORAGE = { key_token: 'baf-agent-token', @@ -31,18 +46,15 @@ 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 ====== const TL = { - log: (msg, ...args) => GM_log(`[TL]\n${msg}`, ...args), - error: (msg, ...args) => GM_log(`[TL] [ERROR] ❌\n${msg}`, ...args), + debug: (tag, msg, ...args) => CONFIG.is_debug && GM_log(`[TL] [${tag}]\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) => { if (typeof GM_notification === 'function') { GM_notification({ title, text, timeout }); @@ -58,7 +70,7 @@ // ====== DOM helpers ====== - TL.ui = { + TL.dom = { isVisible: (el) => { if (!el) return false; const cs = getComputedStyle(el); @@ -109,7 +121,7 @@ let data = text; const isJSON = /content-type:\s*application\/json/i.test(resp.responseHeaders || ''); 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({ status: resp.status, ok: resp.status >= 200 && resp.status < 300, @@ -162,7 +174,7 @@ get: (path, params, init = {}) => BAF.request('GET', path, { params, 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 ====== @@ -175,13 +187,13 @@ await STORAGE.setServerMode(next); const nsv = await BAF.getServer(); const msg = `Switched to ${nsv.label} (${nsv.url})`; - TL.log(msg); + TL.debug(`BAF`,msg); TL.noti('BAF Server Switched', msg); await TL.delay(300); location.reload(); } 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}`); } }); @@ -198,11 +210,11 @@ const resStr = `Server: ${s.label} (${s.url})\n` + `Status: ${res.ok ? 'Connected ✅' : 'Failed ❌'} (${res.status})`; - TL.log(resStr); + TL.debug(`BAF`,resStr); TL.noti('BAF Server', resStr); } catch (e) { const resStr = `ping error: ${e.message}`; - TL.error(resStr); + TL.error('BAF',resStr); TL.noti('BAF Server', resStr); } }); @@ -215,7 +227,7 @@ const loginBtn = document.querySelector('#toLoginPage'); 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; return null; // đang load hoặc chưa rõ @@ -223,17 +235,18 @@ isLoggedIn: async (timeoutMs = 6000, pollMs = 200) => { const deadline = Date.now() + timeoutMs; + TL.debug(`BINANCE`,`isLoggedIn: Checking login state...`); while (Date.now() < deadline) { const state = BINANCE.detectLoginState(); if (state !== null) { - TL.log(`[BINANCE] isLoggedIn => ${state ? 'true' : 'false'}`); return state; } + TL.debug(`BINANCE`,`isLoggedIn: not found. Sleeping...`); await TL.delay(pollMs); } 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; }, }; @@ -241,18 +254,38 @@ // ====== Main ====== async function welcome_message() { - const s = await BAF.getServer(); const res = await BAF.ping(); + const resStr = `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 ====== await welcome_message(); await createGM_Menu(); + setInterval(heartbeat_report, CONFIG.heartbeat_interval); + })(); \ No newline at end of file