From 5c8e5421e2aa7467f20dbb27aff52aa26af45e60 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Tue, 30 Jan 2024 00:37:12 +0800 Subject: [PATCH] feat: add TWITTER_AUTHENTICATION_SECRET --- lib/config.js | 1 + lib/v2/twitter/web-api/login.js | 30 ++++++++++++ package.json | 1 + pnpm-lock.yaml | 49 +++++++++++++++++++ website/docs/install/config.md | 3 +- .../current/install/config.md | 3 +- 6 files changed, 85 insertions(+), 2 deletions(-) diff --git a/lib/config.js b/lib/config.js index 2fdae694a..fa051d5d9 100644 --- a/lib/config.js +++ b/lib/config.js @@ -299,6 +299,7 @@ const calculateValue = () => { oauthTokenSecrets: envs.TWITTER_OAUTH_TOKEN_SECRET?.split(','), username: envs.TWITTER_USERNAME, password: envs.TWITTER_PASSWORD, + authenticationSecret: envs.TWITTER_AUTHENTICATION_SECRET, }, weibo: { app_key: envs.WEIBO_APP_KEY, diff --git a/lib/v2/twitter/web-api/login.js b/lib/v2/twitter/web-api/login.js index bdc5c3360..9d3fd3f03 100644 --- a/lib/v2/twitter/web-api/login.js +++ b/lib/v2/twitter/web-api/login.js @@ -5,10 +5,12 @@ const got = require('@/utils/got'); const crypto = require('crypto'); const config = require('@/config').value; const { v5: uuidv5 } = require('uuid'); +const { authenticator } = require('otplib'); const NAMESPACE = 'd41d092b-b007-48f7-9129-e9538d2d8fe9'; const username = config.twitter.username; const password = config.twitter.password; +const authenticationSecret = config.twitter.authenticationSecret; let authentication = null; @@ -124,6 +126,34 @@ async function login() { if (subtask.open_account) { authentication = subtask.open_account; break; + } else if (subtask.subtask_id === 'LoginTwoFactorAuthChallenge') { + const token = authenticator.generate(authenticationSecret); + + // eslint-disable-next-line no-await-in-loop + const task5 = await got.post('https://api.twitter.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', + }, + ], + }, + }); + + for (const subtask of task5.data?.subtasks || []) { + if (subtask.open_account) { + authentication = subtask.open_account; + break; + } + } + break; } } diff --git a/package.json b/package.json index 5e58744ac..ea2d2ec71 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "module-alias": "2.2.3", "notion-to-md": "3.1.1", "oauth-1.0a": "2.2.6", + "otplib": "12.0.1", "pac-proxy-agent": "7.0.1", "plist": "3.1.0", "proxy-chain": "2.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ee45eced..2b41b66ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -140,6 +140,9 @@ dependencies: oauth-1.0a: specifier: 2.2.6 version: 2.2.6 + otplib: + specifier: 12.0.1 + version: 12.0.1 pac-proxy-agent: specifier: 7.0.1 version: 7.0.1 @@ -1193,6 +1196,39 @@ packages: - encoding dev: false + /@otplib/core@12.0.1: + resolution: {integrity: sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==} + dev: false + + /@otplib/plugin-crypto@12.0.1: + resolution: {integrity: sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==} + dependencies: + '@otplib/core': 12.0.1 + dev: false + + /@otplib/plugin-thirty-two@12.0.1: + resolution: {integrity: sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==} + dependencies: + '@otplib/core': 12.0.1 + thirty-two: 1.0.2 + dev: false + + /@otplib/preset-default@12.0.1: + resolution: {integrity: sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==} + dependencies: + '@otplib/core': 12.0.1 + '@otplib/plugin-crypto': 12.0.1 + '@otplib/plugin-thirty-two': 12.0.1 + dev: false + + /@otplib/preset-v11@12.0.1: + resolution: {integrity: sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==} + dependencies: + '@otplib/core': 12.0.1 + '@otplib/plugin-crypto': 12.0.1 + '@otplib/plugin-thirty-two': 12.0.1 + dev: false + /@pkgr/utils@2.4.2: resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -7386,6 +7422,14 @@ packages: engines: {node: '>=0.10.0'} dev: true + /otplib@12.0.1: + resolution: {integrity: sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==} + dependencies: + '@otplib/core': 12.0.1 + '@otplib/preset-default': 12.0.1 + '@otplib/preset-v11': 12.0.1 + dev: false + /p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} @@ -9004,6 +9048,11 @@ packages: any-promise: 1.3.0 dev: false + /thirty-two@1.0.2: + resolution: {integrity: sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==} + engines: {node: '>=0.2.6'} + dev: false + /thread-stream@2.4.0: resolution: {integrity: sha512-xZYtOtmnA63zj04Q+F9bdEay5r47bvpo1CaNqsKi7TpoJHcotUez8Fkfo2RJWpW91lnnaApdpRbVwCWsy+ifcw==} dependencies: diff --git a/website/docs/install/config.md b/website/docs/install/config.md index 513c42495..c7fb67804 100644 --- a/website/docs/install/config.md +++ b/website/docs/install/config.md @@ -488,10 +488,11 @@ For user data related routes ### Twitter -Please use an account without two-step verification enabled, and it is recommended to use a non-important account. +It is recommended to use a non-important account. - `TWITTER_USERNAME`: Twitter username - `TWITTER_PASSWORD`: Twitter password +- `TWITTER_AUTHENTICATION_SECRET`: Twitter Two-factor authentication -> Authentication app -> Secret part in `otpauth://totp/Twitter:@_RSSHub?secret=xxxxxxxxxxxxxxxx&issuer=Twitter` ### Wordpress diff --git a/website/i18n/zh/docusaurus-plugin-content-docs/current/install/config.md b/website/i18n/zh/docusaurus-plugin-content-docs/current/install/config.md index abd5087f6..1cbf08d35 100644 --- a/website/i18n/zh/docusaurus-plugin-content-docs/current/install/config.md +++ b/website/i18n/zh/docusaurus-plugin-content-docs/current/install/config.md @@ -467,10 +467,11 @@ RSSHub 支持使用访问密钥 / 码,允许清单和拒绝清单三种方式 ### Twitter -请使用未开启两步验证的账号,并建议使用非重要账号 +建议使用非重要账号 - `TWITTER_USERNAME`: Twitter 用户名 - `TWITTER_PASSWORD`: Twitter 密码 +- `TWITTER_AUTHENTICATION_SECRET`: Twitter 两步验证 -> 认证应用 -> `otpauth://totp/Twitter:@_RSSHub?secret=xxxxxxxxxxxxxxxx&issuer=Twitter` 中的 secret 部分 ### Wordpress