From 5cf1de9445ba3098fbdfa3e360e7c8c24be261a3 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 12 Jul 2024 22:07:32 +0800 Subject: [PATCH] feat: more logs --- lib/routes/twitter/api/mobile-api/login.ts | 268 +++++++++++---------- lib/utils/request-rewriter/fetch.ts | 1 + 2 files changed, 138 insertions(+), 131 deletions(-) diff --git a/lib/routes/twitter/api/mobile-api/login.ts b/lib/routes/twitter/api/mobile-api/login.ts index 0cba6dd2244640..c9d19a60e75d80 100644 --- a/lib/routes/twitter/api/mobile-api/login.ts +++ b/lib/routes/twitter/api/mobile-api/login.ts @@ -29,149 +29,155 @@ async function login({ username, password, authenticationSecret }) { return (await cache.tryGet( `twitter:authentication:${username}`, async () => { - logger.debug('Twitter login start.'); - const android_id = uuidv5(username, NAMESPACE); - headers['X-Twitter-Client-DeviceID'] = android_id; - - const ct0 = crypto.randomUUID().replaceAll('-', ''); - const guestToken = await got(guestActivateUrl, { - headers: { - authorization: bearerToken, - 'x-csrf-token': ct0, - cookie: 'ct0=' + ct0, - }, - method: 'POST', - }); - logger.debug('Twitter login 1 finished: guest token.'); - - headers['x-guest-token'] = guestToken.data.guest_token; - - const task1 = await ofetch.raw( - 'https://api.x.com/1.1/onboarding/task.json?' + - new URLSearchParams({ - flow_name: 'login', - api_version: '1', - known_device_token: '', - sim_country_code: 'us', - }).toString(), - { + try { + logger.debug('Twitter login start.'); + const android_id = uuidv5(username, NAMESPACE); + headers['X-Twitter-Client-DeviceID'] = android_id; + + const ct0 = crypto.randomUUID().replaceAll('-', ''); + const guestToken = await got(guestActivateUrl, { + headers: { + authorization: bearerToken, + 'x-csrf-token': ct0, + cookie: 'ct0=' + ct0, + }, method: 'POST', - headers, - body: { - flow_token: null, - input_flow_data: { - country_code: null, - flow_context: { - referrer_context: { - referral_details: 'utm_source=google-play&utm_medium=organic', - referrer_url: '', - }, - start_location: { - location: 'deeplink', + }); + logger.debug('Twitter login 1 finished: guest token.'); + + headers['x-guest-token'] = guestToken.data.guest_token; + + const task1 = await ofetch.raw( + 'https://api.x.com/1.1/onboarding/task.json?' + + new URLSearchParams({ + flow_name: 'login', + api_version: '1', + known_device_token: '', + sim_country_code: 'us', + }).toString(), + { + method: 'POST', + headers, + body: { + flow_token: null, + input_flow_data: { + country_code: null, + flow_context: { + referrer_context: { + referral_details: 'utm_source=google-play&utm_medium=organic', + referrer_url: '', + }, + start_location: { + location: 'deeplink', + }, }, + requested_variant: null, + target_user_id: 0, }, - requested_variant: null, - target_user_id: 0, }, - }, - } - ); - logger.debug('Twitter login 2 finished: login flow.'); - - headers.att = task1.headers.get('att'); - - const task2 = await got.post('https://api.x.com/1.1/onboarding/task.json', { - headers, - json: { - flow_token: task1._data.flow_token, - subtask_inputs: [ - { - enter_text: { - suggestion_id: null, - text: username, - link: 'next_link', + } + ); + logger.debug('Twitter login 2 finished: login flow.'); + + headers.att = task1.headers.get('att'); + + const task2 = await got.post('https://api.x.com/1.1/onboarding/task.json', { + headers, + json: { + flow_token: task1._data.flow_token, + subtask_inputs: [ + { + enter_text: { + suggestion_id: null, + text: username, + link: 'next_link', + }, + subtask_id: 'LoginEnterUserIdentifier', }, - subtask_id: 'LoginEnterUserIdentifier', - }, - ], - }, - }); - logger.debug('Twitter login 3 finished: LoginEnterUserIdentifier.'); - - const task3 = await got.post('https://api.x.com/1.1/onboarding/task.json', { - headers, - json: { - flow_token: task2.data.flow_token, - subtask_inputs: [ - { - enter_password: { - password, - link: 'next_link', + ], + }, + }); + logger.debug('Twitter login 3 finished: LoginEnterUserIdentifier.'); + + const task3 = await got.post('https://api.x.com/1.1/onboarding/task.json', { + headers, + json: { + flow_token: task2.data.flow_token, + subtask_inputs: [ + { + enter_password: { + password, + link: 'next_link', + }, + subtask_id: 'LoginEnterPassword', }, - subtask_id: 'LoginEnterPassword', - }, - ], - }, - }); - logger.debug('Twitter login 4 finished: LoginEnterPassword.'); - - const task4 = await got.post('https://api.x.com/1.1/onboarding/task.json', { - headers, - json: { - flow_token: task3.data.flow_token, - subtask_inputs: [ - { - check_logged_in_account: { - link: 'AccountDuplicationCheck_false', + ], + }, + }); + logger.debug('Twitter login 4 finished: LoginEnterPassword.'); + + const task4 = await got.post('https://api.x.com/1.1/onboarding/task.json', { + headers, + json: { + flow_token: task3.data.flow_token, + subtask_inputs: [ + { + check_logged_in_account: { + link: 'AccountDuplicationCheck_false', + }, + subtask_id: 'AccountDuplicationCheck', }, - subtask_id: 'AccountDuplicationCheck', - }, - ], - }, - }); - logger.debug('Twitter login 5 finished: AccountDuplicationCheck.'); - - for await (const subtask of task4.data?.subtasks || []) { - if (subtask.open_account) { - authentication = subtask.open_account; - break; - } else if (subtask.subtask_id === 'LoginTwoFactorAuthChallenge') { - const token = authenticator.generate(authenticationSecret); - - const task5 = await got.post('https://api.x.com/1.1/onboarding/task.json', { - headers, - json: { - flow_token: task4.data.flow_token, - subtask_inputs: [ - { - enter_text: { - suggestion_id: null, - text: token, - link: 'next_link', + ], + }, + }); + logger.debug('Twitter login 5 finished: AccountDuplicationCheck.'); + + for await (const subtask of task4.data?.subtasks || []) { + if (subtask.open_account) { + authentication = subtask.open_account; + break; + } else if (subtask.subtask_id === 'LoginTwoFactorAuthChallenge') { + const token = authenticator.generate(authenticationSecret); + + const task5 = await got.post('https://api.x.com/1.1/onboarding/task.json', { + headers, + json: { + flow_token: task4.data.flow_token, + subtask_inputs: [ + { + enter_text: { + suggestion_id: null, + text: token, + link: 'next_link', + }, + subtask_id: 'LoginTwoFactorAuthChallenge', }, - subtask_id: 'LoginTwoFactorAuthChallenge', - }, - ], - }, - }); - logger.debug('Twitter login 6 finished: LoginTwoFactorAuthChallenge.'); - - for (const subtask of task5.data?.subtasks || []) { - if (subtask.open_account) { - authentication = subtask.open_account; - break; + ], + }, + }); + logger.debug('Twitter login 6 finished: LoginTwoFactorAuthChallenge.'); + + for (const subtask of task5.data?.subtasks || []) { + if (subtask.open_account) { + authentication = subtask.open_account; + break; + } } + break; + } else { + logger.error(`Twitter login 6 failed: unknown subtask: ${subtask.subtask_id}`); } - break; } - } - if (authentication) { - logger.debug('Twitter login success.'); - } else { - logger.error(`Twitter login failed. ${JSON.stringify(task4.data?.subtasks, null, 2)}`); - } + if (authentication) { + logger.debug('Twitter login success.'); + } else { + logger.error(`Twitter login failed. ${JSON.stringify(task4.data?.subtasks, null, 2)}`); + } - return authentication; + return authentication; + } catch (error) { + logger.error(`Twitter username ${username} login failed:`, error); + } }, 60 * 60 * 24 * 30, // 30 days false diff --git a/lib/utils/request-rewriter/fetch.ts b/lib/utils/request-rewriter/fetch.ts index dd76324dbd6b19..b113b26e3dfccd 100644 --- a/lib/utils/request-rewriter/fetch.ts +++ b/lib/utils/request-rewriter/fetch.ts @@ -52,6 +52,7 @@ const wrappedFetch: typeof undici.fetch = async (input: RequestInfo, init?: Requ if (proxyRegex.test(request.url) && request.url.startsWith('http') && !(urlHandler && urlHandler.host === proxy.proxyUrlHandler?.host)) { options.dispatcher = proxy.dispatcher; + logger.debug(`Proxying request: ${request.url}`); } }