diff --git a/docs/en/social-media.md b/docs/en/social-media.md index 205a195a1ef05..9df242e322743 100644 --- a/docs/en/social-media.md +++ b/docs/en/social-media.md @@ -444,16 +444,16 @@ Due to Telegram restrictions, some channels involving pornography, copyright, an ### User timeline - -cd . + + Specify options (in the format of query string) in parameter `routeParams` to control some extra features for threads | Key | Description | Accepts | Defaults to | |---------------------------------|--------------------------------------------------------------------------------------------------------------------------------| ---------------------- |-------------| | `showAuthorInTitle` | Show author name in title | `0`/`1`/`true`/`false` | `true` | | `showAuthorInDesc` | Show author name in description (RSS body) | `0`/`1`/`true`/`false` | `true` | -| `showQuotedAuthorAvatarInDesc` | Show avatar of quoted author in description (RSS body) (Not recommended if your RSS reader extracts images from description) | `0`/`1`/`true`/`false` | `true` | -| `showAuthorAvatarInDesc` | Show avatar of author in description (RSS body) (Not recommended if your RSS reader extracts images from description) | `0`/`1`/`true`/`false` | `true` | +| `showQuotedAuthorAvatarInDesc` | Show avatar of quoted author in description (RSS body) (Not recommended if your RSS reader extracts images from description) | `0`/`1`/`true`/`false` | `false` | +| `showAuthorAvatarInDesc` | Show avatar of author in description (RSS body) (Not recommended if your RSS reader extracts images from description) | `0`/`1`/`true`/`false` | `falseP` | | `showEmojiForQuotesAndReply` | Use "🔁" instead of "QT", "↩ī¸" instead of "Re" | `0`/`1`/`true`/`false` | `true` | | `showQuotedInTitle` | Show quoted tweet in title | `0`/`1`/`true`/`false` | `true` | | `replies` | Show replies | `0`/`1`/`true`/`false` | `true` | @@ -463,6 +463,7 @@ Specify different option values than default values to improve readability. The ``` https://rsshub.app/threads/zuck/showAuthorInTitle=1&showAuthorInDesc=1&showQuotedAuthorAvatarInDesc=1&showAuthorAvatarInDesc=1&showEmojiForQuotesAndReply=1&showQuotedInTitle=1 ``` + ## TikTok diff --git a/lib/v2/threads/index.js b/lib/v2/threads/index.js index 6effdae92237b..abf4719020141 100644 --- a/lib/v2/threads/index.js +++ b/lib/v2/threads/index.js @@ -8,6 +8,7 @@ const threadUrl = (code) => `https://www.threads.net/t/${code}`; const apiUrl = 'https://www.threads.net/api/graphql'; const THREADS_QUERY = 6232751443445612; const REPLIES_QUERY = 6307072669391286; +const USER_AGENT = 'Barcelona 289.0.0.77.109 Android'; const load = async (url) => { // user id fetching needs puppeteer @@ -21,16 +22,13 @@ const load = async (url) => { waitUntil: 'domcontentloaded', }); const response = await page.content(); - page.close(); + browser.close(); return cheerio.load(response); }; const extractTokens = async (user, ctx) => { const $ = await load(profileUrl(user)); - const appId = $('script:contains("APP_ID"):first') - .html() - .match(/,"APP_ID":"(\d+)",/)?.[1]; const lsd = $('script:contains("LSD"):first') .html() .match(/"LSD",\[],\{"token":"([a-zA-Z0-9@_-]+)"},/)?.[1]; @@ -40,32 +38,20 @@ const extractTokens = async (user, ctx) => { .html() .match(/"user_id":"(\d+)"/)?.[1]; - ctx.state.json = { appId, lsd, userId }; - return { appId, lsd, userId }; + ctx.state.json = { lsd, userId }; + return { lsd, userId }; }; -const makeHeader = (user, appId, lsd) => ({ +const makeHeader = (user, lsd) => ({ Accept: 'application/json', Host: 'www.threads.net', - 'Content-Type': 'application/x-www-form-urlencoded', Origin: 'https://www.threads.net', Referer: `https://www.threads.net/@${user}`, - 'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html) Chrome/83.0.4103.122 Safari/537.36', + 'User-Agent': USER_AGENT, 'X-FB-LSD': lsd, - 'X-IG-App-ID': appId, + 'X-IG-App-ID': '238260118697367', }); -const makeBody = (body) => { - let output = ''; - Object.entries(body).forEach(([key, value], index) => { - output += `${key}=${value}`; - if (index < Object.keys(body).length - 1) { - output += '&'; - } - }); - return output; -}; - const hasMedia = (post) => post.image_versions2 || post.carousel_media || post.video_versions; const buildMedia = (post) => { let html = ''; @@ -158,7 +144,7 @@ const buildContent = (item, options) => { module.exports = async (ctx) => { const { user, routeParams } = ctx.params; - const { appId, lsd, userId } = await extractTokens(user, ctx); + const { lsd, userId } = await extractTokens(user, ctx); const params = new URLSearchParams(routeParams); ctx.state.json.params = routeParams; @@ -166,23 +152,21 @@ module.exports = async (ctx) => { const options = { showAuthorInTitle: params.get('showAuthorInTitle') ?? true, showAuthorInDesc: params.get('showAuthorInDesc') ?? true, - showAuthorAvatarInDesc: params.get('showAuthorAvatarInDesc') ?? true, + showAuthorAvatarInDesc: params.get('showAuthorAvatarInDesc') ?? false, showQuotedInTitle: params.get('showQuotedInTitle') ?? true, - showQuotedAuthorAvatarInDesc: params.get('showQuotedAuthorAvatarInDesc') ?? true, + showQuotedAuthorAvatarInDesc: params.get('showQuotedAuthorAvatarInDesc') ?? false, showEmojiForQuotesAndReply: params.get('showEmojiForQuotesAndReply') ?? true, replies: params.get('replies') ?? false, }; - const headers = makeHeader(user, appId, lsd); - const body = makeBody({ - lsd, - variables: encodeURIComponent(JSON.stringify({ userID: userId })), - doc_id: options.replies ? REPLIES_QUERY : THREADS_QUERY, - }); - + const headers = makeHeader(user, lsd); const resp = await got.post(apiUrl, { headers, - body, + form: { + lsd, + variables: JSON.stringify({ userID: userId }), + doc_id: options.replies ? REPLIES_QUERY : THREADS_QUERY, + }, }); ctx.state.json.request = { @@ -190,7 +174,7 @@ module.exports = async (ctx) => { body: resp.request.options.body, }; - const responseBody = JSON.parse(resp.body); + const responseBody = resp.data; const threads = responseBody?.data?.mediaData?.threads || []; const items = threads.flatMap((thread) => diff --git a/lib/v2/threads/maintainer.js b/lib/v2/threads/maintainer.js index db9e21138d597..f56a62efb1c30 100644 --- a/lib/v2/threads/maintainer.js +++ b/lib/v2/threads/maintainer.js @@ -1,3 +1,3 @@ module.exports = { - '/:user?': ['ninboy'], + '/:user/:routeParams?': ['ninboy'], }; diff --git a/lib/v2/threads/radar.js b/lib/v2/threads/radar.js index 7c40dbcda27a1..8355a067543bd 100644 --- a/lib/v2/threads/radar.js +++ b/lib/v2/threads/radar.js @@ -5,7 +5,7 @@ module.exports = { { title: 'Threads', docs: 'https://docs.rsshub.app/social-media.html#threads', - source: ['/:user'], + source: ['/@:user'], target: '/threads/:user', }, ],