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',
},
],