refactor: remove verify-code/reply support (not needed)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7,18 +7,14 @@
|
|||||||
* Requires Node.js >= 18 (global fetch).
|
* Requires Node.js >= 18 (global fetch).
|
||||||
*
|
*
|
||||||
* method: login
|
* method: login
|
||||||
* params : { callId, timeout, emit, onReplyRef }
|
* params : { callId, timeout, emit }
|
||||||
* returns: { abort, onReply }
|
* returns: { abort }
|
||||||
*
|
*
|
||||||
* emit(payload) sends a sys-call reply upstream:
|
* emit(payload) sends a sys-call reply upstream:
|
||||||
* { action:'event', event:'qrcode', data:{ url, expire:30, index } }
|
* { action:'event', event:'qrcode', data:{ url, expire:30, index } }
|
||||||
* { action:'event', event:'need_verifycode', data:{ retry } }
|
* { action:'progress', event:'scanned', data:{ status:'waiting_confirm' } }
|
||||||
* { action:'progress', event:'scanned', data:{ status:'waiting_confirm' } }
|
* { action:'finish', event:'success', data:{ accountId } }
|
||||||
* { action:'finish', event:'success', data:{ accountId } }
|
* { action:'finish', event:'failed', code, message }
|
||||||
* { action:'finish', event:'failed', code, message }
|
|
||||||
*
|
|
||||||
* To provide a verify code after 'need_verifycode', the upstream dispatcher
|
|
||||||
* should call the returned onReply({ data: { code: '1234' } }).
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
@@ -227,10 +223,9 @@ async function _fetchQRCode(botType) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _pollQRStatus(apiBaseUrl, qrcode, verifyCode) {
|
async function _pollQRStatus(apiBaseUrl, qrcode) {
|
||||||
try {
|
try {
|
||||||
let endpoint = `ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`;
|
const endpoint = `ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`;
|
||||||
if (verifyCode) endpoint += `&verify_code=${encodeURIComponent(verifyCode)}`;
|
|
||||||
const data = await _getJson(apiBaseUrl, endpoint, QR_LONG_POLL_TIMEOUT_MS);
|
const data = await _getJson(apiBaseUrl, endpoint, QR_LONG_POLL_TIMEOUT_MS);
|
||||||
if (data.ret !== undefined && data.ret !== 0) {
|
if (data.ret !== undefined && data.ret !== 0) {
|
||||||
throw new Error(`get_qrcode_status ret=${data.ret} errmsg=${data.errmsg || ''}`);
|
throw new Error(`get_qrcode_status ret=${data.ret} errmsg=${data.errmsg || ''}`);
|
||||||
@@ -279,47 +274,15 @@ function login({ callId, timeout = 180, botType = DEFAULT_BOT_TYPE, emit }) {
|
|||||||
let aborted = false;
|
let aborted = false;
|
||||||
let finished = false;
|
let finished = false;
|
||||||
|
|
||||||
// Pending verify-code: resolve/reject
|
|
||||||
let _pendingVerifyResolve = null;
|
|
||||||
let _pendingVerifyReject = null;
|
|
||||||
|
|
||||||
function _waitForVerifyCode() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
_pendingVerifyResolve = resolve;
|
|
||||||
_pendingVerifyReject = reject;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onReply(msg) {
|
|
||||||
const event = (msg.event || '').toString();
|
|
||||||
const code = (msg.data && msg.data.code) ? String(msg.data.code).trim() : '';
|
|
||||||
if (event === 'verify_code' && _pendingVerifyResolve) {
|
|
||||||
log.info('weixin', `callId=${callId} verify_code received`);
|
|
||||||
const resolve = _pendingVerifyResolve;
|
|
||||||
_pendingVerifyResolve = null;
|
|
||||||
_pendingVerifyReject = null;
|
|
||||||
resolve(code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function abort() {
|
function abort() {
|
||||||
aborted = true;
|
aborted = true;
|
||||||
if (_pendingVerifyReject) {
|
|
||||||
const reject = _pendingVerifyReject;
|
|
||||||
_pendingVerifyResolve = null;
|
|
||||||
_pendingVerifyReject = null;
|
|
||||||
reject(new Error('aborted'));
|
|
||||||
}
|
|
||||||
log.info('weixin', `callId=${callId} aborted`);
|
log.info('weixin', `callId=${callId} aborted`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeoutMs = Math.max(timeout * 1000, 30_000);
|
const timeoutMs = Math.max(timeout * 1000, 30_000);
|
||||||
|
|
||||||
// Run async without blocking caller
|
// Run async without blocking caller
|
||||||
_runLogin({ callId, timeoutMs, botType, emit,
|
_runLogin({ callId, timeoutMs, botType, emit, isAborted: () => aborted })
|
||||||
isAborted: () => aborted,
|
|
||||||
waitForVerifyCode: _waitForVerifyCode,
|
|
||||||
})
|
|
||||||
.then(() => { finished = true; })
|
.then(() => { finished = true; })
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (finished) return;
|
if (finished) return;
|
||||||
@@ -328,10 +291,10 @@ function login({ callId, timeout = 180, botType = DEFAULT_BOT_TYPE, emit }) {
|
|||||||
emit({ action: 'finish', event: 'failed', code: 500, message: err.message });
|
emit({ action: 'finish', event: 'failed', code: 500, message: err.message });
|
||||||
});
|
});
|
||||||
|
|
||||||
return { abort, onReply };
|
return { abort };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForVerifyCode }) {
|
async function _runLogin({ callId, timeoutMs, botType, emit, isAborted }) {
|
||||||
let qrRefreshCount = 1;
|
let qrRefreshCount = 1;
|
||||||
let scannedEmitted = false;
|
let scannedEmitted = false;
|
||||||
let activeLogin = null;
|
let activeLogin = null;
|
||||||
@@ -344,8 +307,7 @@ async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForV
|
|||||||
qrcode: qrData.qrcode,
|
qrcode: qrData.qrcode,
|
||||||
qrcodeUrl: qrData.qrcode_img_content,
|
qrcodeUrl: qrData.qrcode_img_content,
|
||||||
startedAt: Date.now(),
|
startedAt: Date.now(),
|
||||||
apiBaseUrl: FIXED_BASE_URL,
|
apiBaseUrl: FIXED_BASE_URL,
|
||||||
pendingVerify: null,
|
|
||||||
};
|
};
|
||||||
emit({
|
emit({
|
||||||
action: 'event',
|
action: 'event',
|
||||||
@@ -366,18 +328,12 @@ async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForV
|
|||||||
emit({ action: 'finish', event: 'failed', code: 1003, message: 'QR expired too many times' });
|
emit({ action: 'finish', event: 'failed', code: 1003, message: 'QR expired too many times' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await startOrRefreshQr();
|
await startOrRefreshQr();
|
||||||
scannedEmitted = false;
|
scannedEmitted = false;
|
||||||
activeLogin.pendingVerify = null;
|
continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = await _pollQRStatus(
|
const status = await _pollQRStatus(activeLogin.apiBaseUrl, activeLogin.qrcode);
|
||||||
activeLogin.apiBaseUrl,
|
|
||||||
activeLogin.qrcode,
|
|
||||||
activeLogin.pendingVerify
|
|
||||||
);
|
|
||||||
activeLogin.pendingVerify = null; // consumed
|
|
||||||
|
|
||||||
if (isAborted()) return;
|
if (isAborted()) return;
|
||||||
|
|
||||||
@@ -399,18 +355,10 @@ async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForV
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'need_verifycode': {
|
case 'need_verifycode': {
|
||||||
const retry = !!activeLogin.pendingVerify;
|
// Verify code entry not supported; treat as failure
|
||||||
emit({ action: 'event', event: 'need_verifycode', data: { retry } });
|
log.warn('weixin', `callId=${callId} need_verifycode not supported`);
|
||||||
log.info('weixin', `callId=${callId} need_verifycode (retry=${retry})`);
|
emit({ action: 'finish', event: 'failed', code: 1005, message: 'verify code required (not supported)' });
|
||||||
try {
|
return;
|
||||||
const code = await waitForVerifyCode();
|
|
||||||
if (isAborted()) return;
|
|
||||||
activeLogin.pendingVerify = code;
|
|
||||||
} catch (_) {
|
|
||||||
// aborted while waiting
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'expired': {
|
case 'expired': {
|
||||||
|
|||||||
@@ -8,12 +8,10 @@
|
|||||||
* Supported actions (incoming from VPS):
|
* Supported actions (incoming from VPS):
|
||||||
* request — start a new task
|
* request — start a new task
|
||||||
* cancel — abort a running task
|
* cancel — abort a running task
|
||||||
* reply — forward input to a running task (e.g. verify code)
|
|
||||||
*
|
*
|
||||||
* Handler interface:
|
* Handler interface:
|
||||||
* handler[method](params) → { abort, onReply? }
|
* handler[method](params) → { abort } | function
|
||||||
* abort() — called on cancel
|
* abort() — called on cancel
|
||||||
* onReply(msg) — called on reply (optional)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const log = require('./logger');
|
const log = require('./logger');
|
||||||
@@ -54,18 +52,6 @@ function handle(msg, send) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── reply (e.g. verify code from frontend) ────────────────────────────────
|
|
||||||
if (action === 'reply') {
|
|
||||||
const task = running.get(callId);
|
|
||||||
if (task && typeof task.onReply === 'function') {
|
|
||||||
log.info('sys-call', `reply callId=${callId} event=${msg.event || ''}`);
|
|
||||||
try { task.onReply(msg); } catch (e) { log.warn('sys-call', `onReply error: ${e.message}`); }
|
|
||||||
} else {
|
|
||||||
log.debug('sys-call', `reply for unknown/no-onReply callId=${callId}`);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── request ───────────────────────────────────────────────────────────────
|
// ── request ───────────────────────────────────────────────────────────────
|
||||||
if (action !== 'request') {
|
if (action !== 'request') {
|
||||||
log.warn('sys-call', `unexpected action=${action} callId=${callId}`);
|
log.warn('sys-call', `unexpected action=${action} callId=${callId}`);
|
||||||
@@ -107,7 +93,7 @@ function handle(msg, send) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalise: handler may return a function (abort only) or { abort, onReply }
|
// Normalise: handler may return a function (abort only) or { abort }
|
||||||
if (typeof task === 'function') {
|
if (typeof task === 'function') {
|
||||||
task = { abort: task };
|
task = { abort: task };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user