From df5c044ed8122e545bf81d1b4bd3e0f49a527ef7 Mon Sep 17 00:00:00 2001 From: Keisuke Horota Date: Tue, 27 Aug 2024 23:01:38 +0900 Subject: [PATCH] feat(twitter): add twitter getHomeLatestTimeline (#16549) --- lib/routes/twitter/api/index.ts | 2 + lib/routes/twitter/api/web-api/api.ts | 18 +++++++ lib/routes/twitter/api/web-api/constants.ts | 2 + lib/routes/twitter/home-latest.ts | 60 +++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 lib/routes/twitter/home-latest.ts diff --git a/lib/routes/twitter/api/index.ts b/lib/routes/twitter/api/index.ts index ed1acd069..a8389eb69 100644 --- a/lib/routes/twitter/api/index.ts +++ b/lib/routes/twitter/api/index.ts @@ -18,6 +18,7 @@ let api: { getSearch: ApiItem; getList: ApiItem; getHomeTimeline: ApiItem; + getHomeLatestTimeline: ApiItem; } = { init: () => { throw new ConfigNotFoundError('Twitter API is not configured'); @@ -31,6 +32,7 @@ let api: { getSearch: () => null, getList: () => null, getHomeTimeline: () => null, + getHomeLatestTimeline: () => null, }; if (enableWebApi) { diff --git a/lib/routes/twitter/api/web-api/api.ts b/lib/routes/twitter/api/web-api/api.ts index 2e2b1723e..779a02c36 100644 --- a/lib/routes/twitter/api/web-api/api.ts +++ b/lib/routes/twitter/api/web-api/api.ts @@ -184,6 +184,23 @@ const getHomeTimeline = async (id: string, params?: Record) => ) ); +const getHomeLatestTimeline = async (id: string, params?: Record) => + gatherLegacyFromData( + await paginationTweets( + 'HomeLatestTimeline', + undefined, + { + ...params, + count: 20, + includePromotedContent: true, + latestControlAvailable: true, + requestContext: 'launch', + withCommunity: true, + }, + ['home', 'home_timeline_urt'] + ) + ); + export default { getUser, getUserTweets, @@ -194,5 +211,6 @@ export default { getSearch, getList, getHomeTimeline, + getHomeLatestTimeline, init: () => {}, }; diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index dc4a2f2a8..6fdc7ec0a 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -4,6 +4,7 @@ const graphQLEndpointsPlain = [ '/graphql/eS7LO5Jy3xgmd3dbL044EA/UserTweets', '/graphql/k5XapwcSikNsEsILW5FvgA/UserByScreenName', '/graphql/k3YiLNE_MAy5J-NANLERdg/HomeTimeline', + '/graphql/DiTkXJgLqBBxCs7zaYsbtA/HomeLatestTimeline', '/graphql/3GeIaLmNhTm1YsUmxR57tg/UserTweetsAndReplies', '/graphql/TOU4gQw8wXIqpSzA4TYKgg/UserMedia', '/graphql/B8I_QCljDBVfin21TTWMqA/Likes', @@ -87,6 +88,7 @@ const gqlFeatures = { SearchTimeline: gqlFeatureFeed, ListLatestTweetsTimeline: gqlFeatureFeed, HomeTimeline: gqlFeatureFeed, + HomeLatestTimeline: TweetDetailFeatures, TweetDetail: TweetDetailFeatures, Likes: gqlFeatureFeed, }; diff --git a/lib/routes/twitter/home-latest.ts b/lib/routes/twitter/home-latest.ts new file mode 100644 index 000000000..40e44ef82 --- /dev/null +++ b/lib/routes/twitter/home-latest.ts @@ -0,0 +1,60 @@ +import { Route } from '@/types'; +import utils from './utils'; +import api from './api'; + +export const route: Route = { + path: '/home_latest/:routeParams?', + categories: ['social-media'], + example: '/twitter/home_latest', + features: { + requireConfig: [ + { + name: 'TWITTER_USERNAME', + description: 'Please see above for details.', + }, + { + name: 'TWITTER_PASSWORD', + description: 'Please see above for details.', + }, + { + name: 'TWITTER_AUTH_TOKEN', + description: 'Please see above for details.', + }, + ], + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + name: 'Home latest timeline', + maintainers: ['DIYgod', 'CaoMeiYouRen'], + handler, + radar: [ + { + source: ['x.com/home'], + target: '/home_latest', + }, + ], +}; + +async function handler(ctx) { + // For compatibility + const { count, include_rts } = utils.parseRouteParams(ctx.req.param('routeParams')); + const params = count ? { count } : {}; + + await api.init(); + let data = await api.getHomeLatestTimeline('', params); + if (!include_rts) { + data = utils.excludeRetweet(data); + } + + return { + title: `Twitter following timeline`, + link: `https://x.com/home`, + // description: userInfo?.description, + item: utils.ProcessFeed(ctx, { + data, + }), + }; +}