From 4c312f083c5c86fd57a4f274343fcf29ad36caa1 Mon Sep 17 00:00:00 2001 From: Guantong Date: Thu, 10 Jul 2025 14:39:35 +0800 Subject: [PATCH 01/11] ListLatestTweetsTimeline count 40 --- lib/routes/twitter/api/web-api/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/routes/twitter/api/web-api/api.ts b/lib/routes/twitter/api/web-api/api.ts index 6d331a2049b4..8143d162d40d 100644 --- a/lib/routes/twitter/api/web-api/api.ts +++ b/lib/routes/twitter/api/web-api/api.ts @@ -163,7 +163,7 @@ const getList = async (id: string, params?: Record) => { ...params, listId: id, - count: 20, + count: 40, }, ['list', 'tweets_timeline', 'timeline'] ) From e0957efb0dcf2caef04234387673ab9df8c4b19e Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:20:56 +0800 Subject: [PATCH 02/11] CI --- .github/workflows/release.pubfi.yml | 96 +++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .github/workflows/release.pubfi.yml diff --git a/.github/workflows/release.pubfi.yml b/.github/workflows/release.pubfi.yml new file mode 100644 index 000000000000..6cf783976314 --- /dev/null +++ b/.github/workflows/release.pubfi.yml @@ -0,0 +1,96 @@ +name: 'Docker Release (Pubfi)' + +on: + push: + branches: + - pubfi + +jobs: + release: + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + packages: write + id-token: write + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Install cosign + if: github.event_name != 'pull_request' + uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1 + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + + - name: Log in to the Container registry + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata (ordinary version) + id: meta-ordinary + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + ghcr.io/${{ github.repository }} + tags: | + type=raw,value=latest,enable=true + type=raw,value={{date 'YYYY-MM-DD'}},enable=true + type=sha,format=long,prefix=,enable=true + flavor: latest=false + + - name: Build and push Docker image (ordinary version) + id: build-and-push + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + push: true + tags: ${{ steps.meta-ordinary.outputs.tags }} + labels: ${{ steps.meta-ordinary.outputs.labels }} + platforms: linux/amd64,linux/arm64 + cache-from: type=gha,scope=docker-release + cache-to: type=gha,mode=max,scope=docker-release + + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + COSIGN_EXPERIMENTAL: 'true' + run: echo "${{ steps.meta-ordinary.outputs.tags }}" | xargs -I {} cosign sign --yes {}@${{ steps.build-and-push.outputs.digest }} + + - name: Extract Docker metadata (Chromium-bundled version) + id: meta-chromium-bundled + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + ghcr.io/${{ github.repository }} + tags: | + type=raw,value=chromium-bundled,enable=true + type=raw,value=chromium-bundled-{{date 'YYYY-MM-DD'}},enable=true + type=sha,format=long,prefix=chromium-bundled-,enable=true + flavor: latest=false + + - name: Build and push Docker image (Chromium-bundled version) + id: build-and-push-chromium + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + build-args: PUPPETEER_SKIP_DOWNLOAD=0 + push: true + tags: ${{ steps.meta-chromium-bundled.outputs.tags }} + labels: ${{ steps.meta-chromium-bundled.outputs.labels }} + platforms: linux/amd64,linux/arm64 + cache-from: | + type=registry,ref=${{ secrets.DOCKER_USERNAME }}/rsshub:chromium-bundled + cache-to: type=inline,ref=${{ secrets.DOCKER_USERNAME }}/rsshub:chromium-bundled # inline cache is enough + + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + COSIGN_EXPERIMENTAL: 'true' + run: echo "${{ steps.meta-chromium-bundled.outputs.tags }}" | xargs -I {} cosign sign --yes {}@${{ steps.build-and-push-chromium.outputs.digest }} From 21ab9850c85ba8a6707316ae2fd59f56284aaed2 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Fri, 11 Jul 2025 01:00:53 +0800 Subject: [PATCH 03/11] CI --- .../build-assets.yml | 0 .../{workflows => bakup_workflows}/codeql.yml | 0 .../comment-on-issue.yml | 0 .../dependabot-fork.yml | 0 .../docker-release.yml | 0 .../docker-test-cont.yml | 0 .../docker-test.yml | 0 .../{workflows => bakup_workflows}/format.yml | 0 .../issue-command.yml | 0 .../{workflows => bakup_workflows}/lint.yml | 0 .../npm-publish.yml | 0 .github/bakup_workflows/release.pubfi.yml | 96 +++++++++++++++++++ .../semgrep.yml | 0 .../{workflows => bakup_workflows}/stale.yml | 0 .../test-full-routes.yml | 0 .../{workflows => bakup_workflows}/test.yml | 0 .github/workflows/release.pubfi.yml | 8 ++ 17 files changed, 104 insertions(+) rename .github/{workflows => bakup_workflows}/build-assets.yml (100%) rename .github/{workflows => bakup_workflows}/codeql.yml (100%) rename .github/{workflows => bakup_workflows}/comment-on-issue.yml (100%) rename .github/{workflows => bakup_workflows}/dependabot-fork.yml (100%) rename .github/{workflows => bakup_workflows}/docker-release.yml (100%) rename .github/{workflows => bakup_workflows}/docker-test-cont.yml (100%) rename .github/{workflows => bakup_workflows}/docker-test.yml (100%) rename .github/{workflows => bakup_workflows}/format.yml (100%) rename .github/{workflows => bakup_workflows}/issue-command.yml (100%) rename .github/{workflows => bakup_workflows}/lint.yml (100%) rename .github/{workflows => bakup_workflows}/npm-publish.yml (100%) create mode 100644 .github/bakup_workflows/release.pubfi.yml rename .github/{workflows => bakup_workflows}/semgrep.yml (100%) rename .github/{workflows => bakup_workflows}/stale.yml (100%) rename .github/{workflows => bakup_workflows}/test-full-routes.yml (100%) rename .github/{workflows => bakup_workflows}/test.yml (100%) diff --git a/.github/workflows/build-assets.yml b/.github/bakup_workflows/build-assets.yml similarity index 100% rename from .github/workflows/build-assets.yml rename to .github/bakup_workflows/build-assets.yml diff --git a/.github/workflows/codeql.yml b/.github/bakup_workflows/codeql.yml similarity index 100% rename from .github/workflows/codeql.yml rename to .github/bakup_workflows/codeql.yml diff --git a/.github/workflows/comment-on-issue.yml b/.github/bakup_workflows/comment-on-issue.yml similarity index 100% rename from .github/workflows/comment-on-issue.yml rename to .github/bakup_workflows/comment-on-issue.yml diff --git a/.github/workflows/dependabot-fork.yml b/.github/bakup_workflows/dependabot-fork.yml similarity index 100% rename from .github/workflows/dependabot-fork.yml rename to .github/bakup_workflows/dependabot-fork.yml diff --git a/.github/workflows/docker-release.yml b/.github/bakup_workflows/docker-release.yml similarity index 100% rename from .github/workflows/docker-release.yml rename to .github/bakup_workflows/docker-release.yml diff --git a/.github/workflows/docker-test-cont.yml b/.github/bakup_workflows/docker-test-cont.yml similarity index 100% rename from .github/workflows/docker-test-cont.yml rename to .github/bakup_workflows/docker-test-cont.yml diff --git a/.github/workflows/docker-test.yml b/.github/bakup_workflows/docker-test.yml similarity index 100% rename from .github/workflows/docker-test.yml rename to .github/bakup_workflows/docker-test.yml diff --git a/.github/workflows/format.yml b/.github/bakup_workflows/format.yml similarity index 100% rename from .github/workflows/format.yml rename to .github/bakup_workflows/format.yml diff --git a/.github/workflows/issue-command.yml b/.github/bakup_workflows/issue-command.yml similarity index 100% rename from .github/workflows/issue-command.yml rename to .github/bakup_workflows/issue-command.yml diff --git a/.github/workflows/lint.yml b/.github/bakup_workflows/lint.yml similarity index 100% rename from .github/workflows/lint.yml rename to .github/bakup_workflows/lint.yml diff --git a/.github/workflows/npm-publish.yml b/.github/bakup_workflows/npm-publish.yml similarity index 100% rename from .github/workflows/npm-publish.yml rename to .github/bakup_workflows/npm-publish.yml diff --git a/.github/bakup_workflows/release.pubfi.yml b/.github/bakup_workflows/release.pubfi.yml new file mode 100644 index 000000000000..6cf783976314 --- /dev/null +++ b/.github/bakup_workflows/release.pubfi.yml @@ -0,0 +1,96 @@ +name: 'Docker Release (Pubfi)' + +on: + push: + branches: + - pubfi + +jobs: + release: + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + packages: write + id-token: write + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Install cosign + if: github.event_name != 'pull_request' + uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1 + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + + - name: Log in to the Container registry + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata (ordinary version) + id: meta-ordinary + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + ghcr.io/${{ github.repository }} + tags: | + type=raw,value=latest,enable=true + type=raw,value={{date 'YYYY-MM-DD'}},enable=true + type=sha,format=long,prefix=,enable=true + flavor: latest=false + + - name: Build and push Docker image (ordinary version) + id: build-and-push + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + push: true + tags: ${{ steps.meta-ordinary.outputs.tags }} + labels: ${{ steps.meta-ordinary.outputs.labels }} + platforms: linux/amd64,linux/arm64 + cache-from: type=gha,scope=docker-release + cache-to: type=gha,mode=max,scope=docker-release + + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + COSIGN_EXPERIMENTAL: 'true' + run: echo "${{ steps.meta-ordinary.outputs.tags }}" | xargs -I {} cosign sign --yes {}@${{ steps.build-and-push.outputs.digest }} + + - name: Extract Docker metadata (Chromium-bundled version) + id: meta-chromium-bundled + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + ghcr.io/${{ github.repository }} + tags: | + type=raw,value=chromium-bundled,enable=true + type=raw,value=chromium-bundled-{{date 'YYYY-MM-DD'}},enable=true + type=sha,format=long,prefix=chromium-bundled-,enable=true + flavor: latest=false + + - name: Build and push Docker image (Chromium-bundled version) + id: build-and-push-chromium + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + build-args: PUPPETEER_SKIP_DOWNLOAD=0 + push: true + tags: ${{ steps.meta-chromium-bundled.outputs.tags }} + labels: ${{ steps.meta-chromium-bundled.outputs.labels }} + platforms: linux/amd64,linux/arm64 + cache-from: | + type=registry,ref=${{ secrets.DOCKER_USERNAME }}/rsshub:chromium-bundled + cache-to: type=inline,ref=${{ secrets.DOCKER_USERNAME }}/rsshub:chromium-bundled # inline cache is enough + + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + COSIGN_EXPERIMENTAL: 'true' + run: echo "${{ steps.meta-chromium-bundled.outputs.tags }}" | xargs -I {} cosign sign --yes {}@${{ steps.build-and-push-chromium.outputs.digest }} diff --git a/.github/workflows/semgrep.yml b/.github/bakup_workflows/semgrep.yml similarity index 100% rename from .github/workflows/semgrep.yml rename to .github/bakup_workflows/semgrep.yml diff --git a/.github/workflows/stale.yml b/.github/bakup_workflows/stale.yml similarity index 100% rename from .github/workflows/stale.yml rename to .github/bakup_workflows/stale.yml diff --git a/.github/workflows/test-full-routes.yml b/.github/bakup_workflows/test-full-routes.yml similarity index 100% rename from .github/workflows/test-full-routes.yml rename to .github/bakup_workflows/test-full-routes.yml diff --git a/.github/workflows/test.yml b/.github/bakup_workflows/test.yml similarity index 100% rename from .github/workflows/test.yml rename to .github/bakup_workflows/test.yml diff --git a/.github/workflows/release.pubfi.yml b/.github/workflows/release.pubfi.yml index 6cf783976314..db203efaffcc 100644 --- a/.github/workflows/release.pubfi.yml +++ b/.github/workflows/release.pubfi.yml @@ -94,3 +94,11 @@ jobs: env: COSIGN_EXPERIMENTAL: 'true' run: echo "${{ steps.meta-chromium-bundled.outputs.tags }}" | xargs -I {} cosign sign --yes {}@${{ steps.build-and-push-chromium.outputs.digest }} + + - name: Deploy + uses: tarasyarema/dokploy-deploy-action@main + with: + auth_token: ${{ secrets.DOKPLOY_TOKEN }} + application_id: xRDUMgJGh52qvtaJakCAq + dokploy_url: ${{ secrets.DOKPLOY_URL }} + wait_for_completion: true From 8fa71df0aeaca8598108f592ca611563d8146e7d Mon Sep 17 00:00:00 2001 From: Guantong Date: Wed, 23 Jul 2025 10:50:22 +0800 Subject: [PATCH 04/11] Update graphql prefix for ListLatestTweetsTimeline --- lib/routes/twitter/api/web-api/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index aecefd1ab4ca..59151dbe5db3 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -9,7 +9,7 @@ const graphQLEndpointsPlain = [ '/graphql/dexO_2tohK86JDudXXG3Yw/UserMedia', '/graphql/Qw77dDjp9xCpUY-AXwt-yQ/UserByRestId', '/graphql/UN1i3zUiCWa-6r-Uaho4fw/SearchTimeline', - '/graphql/Pa45JvqZuKcW1plybfgBlQ/ListLatestTweetsTimeline', + '/graphql/l411pL-GRg-AKo_a2rmYjg/ListLatestTweetsTimeline', '/graphql/QuBlQ6SxNAQCt6-kBiCXCQ/TweetDetail', ]; From 09e733086fc24e8429dd2e78aefeecc6e9be62c9 Mon Sep 17 00:00:00 2001 From: Guantong Date: Wed, 23 Jul 2025 12:09:07 +0800 Subject: [PATCH 05/11] Try fix X list 400 --- lib/routes/twitter/api/web-api/constants.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index 59151dbe5db3..3fae7a08fbb8 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -55,6 +55,18 @@ const gqlFeatureFeed = { longform_notetweets_rich_text_read_enabled: true, longform_notetweets_inline_media_enabled: true, responsive_web_enhance_cards_enabled: false, + rweb_video_screen_enabled: false, + payments_enabled: false, + profile_label_improvements_pcf_label_in_post_enabled: true, + premium_content_api_read_enabled: false, + responsive_web_grok_analyze_button_fetch_trends_enabled: false, + responsive_web_grok_analyze_post_followups_enabled: true, + responsive_web_jetfuel_frame: true, + responsive_web_grok_share_attachment_enabled: true, + responsive_web_grok_show_grok_translated_post: false, + responsive_web_grok_analysis_button_from_backend: true, + responsive_web_grok_image_annotation_enabled: true, + responsive_web_grok_community_note_auto_translation_is_enabled: false, }; const TweetDetailFeatures = { From 2dd7c3187eb9b297bee8193e0ba83a3f923fd43a Mon Sep 17 00:00:00 2001 From: Guantong Date: Wed, 23 Jul 2025 17:37:58 +0800 Subject: [PATCH 06/11] No retry --- lib/routes/twitter/api/web-api/api.ts | 2 +- lib/routes/twitter/api/web-api/utils.ts | 5 +++-- lib/utils/ofetch.ts | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/routes/twitter/api/web-api/api.ts b/lib/routes/twitter/api/web-api/api.ts index 8143d162d40d..6d331a2049b4 100644 --- a/lib/routes/twitter/api/web-api/api.ts +++ b/lib/routes/twitter/api/web-api/api.ts @@ -163,7 +163,7 @@ const getList = async (id: string, params?: Record) => { ...params, listId: id, - count: 40, + count: 20, }, ['list', 'tweets_timeline', 'timeline'] ) diff --git a/lib/routes/twitter/api/web-api/utils.ts b/lib/routes/twitter/api/web-api/utils.ts index 02653eacff39..ab29de2943e8 100644 --- a/lib/routes/twitter/api/web-api/utils.ts +++ b/lib/routes/twitter/api/web-api/utils.ts @@ -58,8 +58,9 @@ const getAuth = async (retry: number) => { const lock = await cache.get(`${lockPrefix}${token}`, false); if (lock) { logger.debug(`twitter debug: twitter cookie for token ${token} is locked, retry: ${retry}`); - await new Promise((resolve) => setTimeout(resolve, Math.random() * 500 + 500)); - return await getAuth(retry - 1); + // await new Promise((resolve) => setTimeout(resolve, Math.random() * 500 + 500)); + // return await getAuth(retry - 1); + return; } else { logger.debug(`twitter debug: lock twitter cookie for token ${token}`); await cache.set(`${lockPrefix}${token}`, '1', 20); diff --git a/lib/utils/ofetch.ts b/lib/utils/ofetch.ts index bb3443183698..34a901825d06 100644 --- a/lib/utils/ofetch.ts +++ b/lib/utils/ofetch.ts @@ -7,7 +7,7 @@ config.enableRemoteDebugging && process.env.NODE_ENV === 'dev' && register(); const rofetch = createFetch().create({ retryStatusCodes: [400, 408, 409, 425, 429, 500, 502, 503, 504], - retry: config.requestRetry, + retry: 0, retryDelay: 1000, // timeout: config.requestTimeout, onResponseError({ request, response, options }) { From 3a16ef71c486994d0580fa254bc317550178d3da Mon Sep 17 00:00:00 2001 From: Guantong Date: Wed, 30 Jul 2025 17:21:37 +0800 Subject: [PATCH 07/11] proxyUris for each X auth token --- lib/config.ts | 4 ++++ lib/routes/twitter/api/web-api/utils.ts | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/config.ts b/lib/config.ts index 2834a3d8899d..b7fdb761c243 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -361,6 +361,7 @@ export type Config = { authenticationSecret?: string[]; phoneOrEmail?: string[]; authToken?: string[]; + proxyUris?: string[]; thirdPartyApi?: string; }; uestc: { @@ -823,6 +824,9 @@ const calculateValue = () => { authenticationSecret: envs.TWITTER_AUTHENTICATION_SECRET?.split(','), phoneOrEmail: envs.TWITTER_PHONE_OR_EMAIL?.split(','), authToken: envs.TWITTER_AUTH_TOKEN?.split(','), + proxyUris: envs.TWITTER_PROXY_URIS?.split(',') + .map((uri) => uri.trim()) + .filter(Boolean), thirdPartyApi: envs.TWITTER_THIRD_PARTY_API, }, uestc: { diff --git a/lib/routes/twitter/api/web-api/utils.ts b/lib/routes/twitter/api/web-api/utils.ts index ab29de2943e8..79c060bdf45a 100644 --- a/lib/routes/twitter/api/web-api/utils.ts +++ b/lib/routes/twitter/api/web-api/utils.ts @@ -13,7 +13,7 @@ import login from './login'; let authTokenIndex = 0; -const token2Cookie = async (token) => { +const token2Cookie = async (token, proxyUri?) => { const c = await cache.get(`twitter:cookie:${token}`); if (c) { return c; @@ -21,10 +21,11 @@ const token2Cookie = async (token) => { const jar = new CookieJar(); await jar.setCookie(`auth_token=${token}`, 'https://x.com'); try { - const agent = proxy.proxyUri + const effectiveProxyUri = proxyUri || proxy.proxyUri; + const agent = effectiveProxyUri ? new ProxyAgent({ factory: (origin, opts) => new CookieClient(origin as string, { ...opts, cookies: { jar } }), - uri: proxy.proxyUri, + uri: effectiveProxyUri, }) : new CookieAgent({ cookies: { jar } }); if (token) { @@ -66,6 +67,7 @@ const getAuth = async (retry: number) => { await cache.set(`${lockPrefix}${token}`, '1', 20); return { token, + proxyUri: config.twitter.proxyUris?.[index], username: config.twitter.username?.[index], password: config.twitter.password?.[index], authenticationSecret: config.twitter.authenticationSecret?.[index], @@ -89,7 +91,7 @@ export const twitterGot = async ( const requestUrl = `${url}?${queryString.stringify(params)}`; - let cookie: string | Record | null | undefined = await token2Cookie(auth?.token); + let cookie: string | Record | null | undefined = await token2Cookie(auth?.token, auth?.proxyUri); if (!cookie && auth) { cookie = await login({ username: auth.username, @@ -109,14 +111,15 @@ export const twitterGot = async ( cookie = JSON.parse(cookie); } const jar = CookieJar.deserializeSync(cookie as any); - const agent = proxy.proxyUri + const effectiveProxyUri = auth?.proxyUri || proxy.proxyUri; + const agent = effectiveProxyUri ? new ProxyAgent({ factory: (origin, opts) => new CookieClient(origin as string, { ...opts, cookies: { jar } }), - uri: proxy.proxyUri, + uri: effectiveProxyUri, }) : new CookieAgent({ cookies: { jar } }); - if (proxy.proxyUri) { - logger.debug(`twitter debug: Proxying request: ${requestUrl}`); + if (effectiveProxyUri) { + logger.info(`twitter info: Proxying request: ${requestUrl} via ${effectiveProxyUri}`); } dispatchers = { jar, From fed731457de76e6b3e4053037cbfa41167fcb0cc Mon Sep 17 00:00:00 2001 From: Guantong Date: Fri, 1 Aug 2025 10:31:34 +0800 Subject: [PATCH 08/11] log proxy --- lib/routes/twitter/api/web-api/utils.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/routes/twitter/api/web-api/utils.ts b/lib/routes/twitter/api/web-api/utils.ts index 79c060bdf45a..14e6ff21efbf 100644 --- a/lib/routes/twitter/api/web-api/utils.ts +++ b/lib/routes/twitter/api/web-api/utils.ts @@ -22,6 +22,9 @@ const token2Cookie = async (token, proxyUri?) => { await jar.setCookie(`auth_token=${token}`, 'https://x.com'); try { const effectiveProxyUri = proxyUri || proxy.proxyUri; + if (effectiveProxyUri) { + logger.info(`twitter token2Cookie via proxy: ${effectiveProxyUri}`); + } const agent = effectiveProxyUri ? new ProxyAgent({ factory: (origin, opts) => new CookieClient(origin as string, { ...opts, cookies: { jar } }), @@ -91,6 +94,11 @@ export const twitterGot = async ( const requestUrl = `${url}?${queryString.stringify(params)}`; + const effectiveProxyUri = auth?.proxyUri || proxy.proxyUri; + if (effectiveProxyUri) { + logger.info(`twitter request via proxy: ${effectiveProxyUri}`); + } + let cookie: string | Record | null | undefined = await token2Cookie(auth?.token, auth?.proxyUri); if (!cookie && auth) { cookie = await login({ From 9d769aceb4e2bb1a19a7e6f21e1747d276057913 Mon Sep 17 00:00:00 2001 From: Guantong Date: Fri, 15 Aug 2025 10:19:14 +0800 Subject: [PATCH 09/11] Update list graphql --- lib/routes/twitter/api/web-api/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index 3fae7a08fbb8..3b9d844439ba 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -9,7 +9,7 @@ const graphQLEndpointsPlain = [ '/graphql/dexO_2tohK86JDudXXG3Yw/UserMedia', '/graphql/Qw77dDjp9xCpUY-AXwt-yQ/UserByRestId', '/graphql/UN1i3zUiCWa-6r-Uaho4fw/SearchTimeline', - '/graphql/l411pL-GRg-AKo_a2rmYjg/ListLatestTweetsTimeline', + '/graphql/06JtmwM8k_1cthpFZITVVA/ListLatestTweetsTimeline', '/graphql/QuBlQ6SxNAQCt6-kBiCXCQ/TweetDetail', ]; From 9ab8520c108149a1cd71fb17d308f35c4b082087 Mon Sep 17 00:00:00 2001 From: Guantong Date: Fri, 15 Aug 2025 10:56:43 +0800 Subject: [PATCH 10/11] Try fix X list 400 --- lib/routes/twitter/api/web-api/constants.ts | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index 3b9d844439ba..83bd6750b346 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -32,14 +32,22 @@ const gqlFeatureUser = { responsive_web_graphql_timeline_navigation_enabled: true, }; const gqlFeatureFeed = { + rweb_video_screen_enabled: false, + payments_enabled: false, + rweb_xchat_enabled: false, + profile_label_improvements_pcf_label_in_post_enabled: true, rweb_tipjar_consumption_enabled: true, - responsive_web_graphql_exclude_directive_enabled: true, verified_phone_label_enabled: false, creator_subscriptions_tweet_preview_api_enabled: true, responsive_web_graphql_timeline_navigation_enabled: true, responsive_web_graphql_skip_user_profile_image_extensions_enabled: false, + premium_content_api_read_enabled: false, communities_web_enable_tweet_community_results_fetch: true, c9s_tweet_anatomy_moderator_badge_enabled: true, + responsive_web_grok_analyze_button_fetch_trends_enabled: false, + responsive_web_grok_analyze_post_followups_enabled: true, + responsive_web_jetfuel_frame: true, + responsive_web_grok_share_attachment_enabled: true, articles_preview_enabled: true, responsive_web_edit_tweet_api_enabled: true, graphql_is_translatable_rweb_tweet_is_translatable_enabled: true, @@ -47,26 +55,18 @@ const gqlFeatureFeed = { longform_notetweets_consumption_enabled: true, responsive_web_twitter_article_tweet_consumption_enabled: true, tweet_awards_web_tipping_enabled: false, + responsive_web_grok_show_grok_translated_post: false, + responsive_web_grok_analysis_button_from_backend: false, creator_subscriptions_quote_tweet_preview_enabled: false, freedom_of_speech_not_reach_fetch_enabled: true, standardized_nudges_misinfo: true, tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true, - rweb_video_timestamps_enabled: true, longform_notetweets_rich_text_read_enabled: true, longform_notetweets_inline_media_enabled: true, - responsive_web_enhance_cards_enabled: false, - rweb_video_screen_enabled: false, - payments_enabled: false, - profile_label_improvements_pcf_label_in_post_enabled: true, - premium_content_api_read_enabled: false, - responsive_web_grok_analyze_button_fetch_trends_enabled: false, - responsive_web_grok_analyze_post_followups_enabled: true, - responsive_web_jetfuel_frame: true, - responsive_web_grok_share_attachment_enabled: true, - responsive_web_grok_show_grok_translated_post: false, - responsive_web_grok_analysis_button_from_backend: true, responsive_web_grok_image_annotation_enabled: true, + responsive_web_grok_imagine_annotation_enabled: true, responsive_web_grok_community_note_auto_translation_is_enabled: false, + responsive_web_enhance_cards_enabled: false, }; const TweetDetailFeatures = { From b999c06a5daf3404b6e66f663c8a4be264f2fea1 Mon Sep 17 00:00:00 2001 From: Guantong Date: Tue, 2 Sep 2025 21:23:34 +0800 Subject: [PATCH 11/11] update graphql for ListLatestTweetsTimeline --- lib/routes/twitter/api/web-api/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index 83bd6750b346..087e277308f3 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -9,7 +9,7 @@ const graphQLEndpointsPlain = [ '/graphql/dexO_2tohK86JDudXXG3Yw/UserMedia', '/graphql/Qw77dDjp9xCpUY-AXwt-yQ/UserByRestId', '/graphql/UN1i3zUiCWa-6r-Uaho4fw/SearchTimeline', - '/graphql/06JtmwM8k_1cthpFZITVVA/ListLatestTweetsTimeline', + '/graphql/nXOf2bJbJBtuzgtKxOqJ-A/ListLatestTweetsTimeline', '/graphql/QuBlQ6SxNAQCt6-kBiCXCQ/TweetDetail', ];