mirror of
https://github.com/CompeyDev/fxtwitter-docker.git
synced 2025-04-07 03:20:55 +01:00
Guest token caching (doesn't seem to work?)
This commit is contained in:
parent
66147807ac
commit
1a84aff39f
5 changed files with 53 additions and 15 deletions
|
@ -45,8 +45,9 @@ export const Constants = {
|
||||||
'allow': 'OPTIONS, GET, PURGE, HEAD',
|
'allow': 'OPTIONS, GET, PURGE, HEAD',
|
||||||
'content-type': 'text/html;charset=UTF-8',
|
'content-type': 'text/html;charset=UTF-8',
|
||||||
'x-powered-by': '🏳️⚧️ Trans Rights',
|
'x-powered-by': '🏳️⚧️ Trans Rights',
|
||||||
'cache-control': 'max-age=3600'
|
'cache-control': 'max-age=3600' // Can be overriden in some cases, like poll tweets
|
||||||
},
|
},
|
||||||
|
POLL_TWEET_CACHE: 'max-age=60',
|
||||||
DEFAULT_COLOR: '#10A3FF',
|
DEFAULT_COLOR: '#10A3FF',
|
||||||
ROBOTS_TXT: `User-agent: *
|
ROBOTS_TXT: `User-agent: *
|
||||||
Allow: /$
|
Allow: /$
|
||||||
|
|
59
src/fetch.ts
59
src/fetch.ts
|
@ -1,7 +1,28 @@
|
||||||
import { Constants } from './constants';
|
import { Constants } from './constants';
|
||||||
|
|
||||||
export const fetchUsingGuest = async (status: string): Promise<TimelineBlobPartial> => {
|
export const fetchUsingGuest = async (status: string, event: FetchEvent): Promise<TimelineBlobPartial> => {
|
||||||
let apiAttempts = 0;
|
let apiAttempts = 0;
|
||||||
|
let cachedTokenFailed = false;
|
||||||
|
|
||||||
|
const tokenHeaders: { [header: string]: string } = {
|
||||||
|
Authorization: Constants.GUEST_BEARER_TOKEN,
|
||||||
|
...Constants.BASE_HEADERS
|
||||||
|
};
|
||||||
|
|
||||||
|
const guestTokenRequest = new Request(
|
||||||
|
`${Constants.TWITTER_API_ROOT}/1.1/guest/activate.json`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: tokenHeaders,
|
||||||
|
cf: {
|
||||||
|
cacheEverything: true,
|
||||||
|
cacheTtl: 600
|
||||||
|
},
|
||||||
|
body: ''
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const cache = caches.default;
|
||||||
|
|
||||||
while (apiAttempts < 10) {
|
while (apiAttempts < 10) {
|
||||||
const csrfToken = crypto.randomUUID().replace(/-/g, ''); // Generate a random CSRF token, this doesn't matter, Twitter just cares that header and cookie match
|
const csrfToken = crypto.randomUUID().replace(/-/g, ''); // Generate a random CSRF token, this doesn't matter, Twitter just cares that header and cookie match
|
||||||
|
@ -13,19 +34,28 @@ export const fetchUsingGuest = async (status: string): Promise<TimelineBlobParti
|
||||||
|
|
||||||
apiAttempts++;
|
apiAttempts++;
|
||||||
|
|
||||||
/* If all goes according to plan, we have a guest token we can use to call API
|
let activate: Response | null = null;
|
||||||
AFAIK there is no limit to how many guest tokens you can request.
|
|
||||||
|
|
||||||
This can effectively mean virtually unlimited (read) access to Twitter's API,
|
if (!cachedTokenFailed) {
|
||||||
which is very funny. */
|
let cachedResponse = await cache.match(guestTokenRequest);
|
||||||
const activate = await fetch(
|
|
||||||
`${Constants.TWITTER_API_ROOT}/1.1/guest/activate.json`,
|
if (cachedResponse) {
|
||||||
{
|
console.log('Token cache hit');
|
||||||
method: 'POST',
|
activate = cachedResponse;
|
||||||
headers: headers,
|
|
||||||
body: ''
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
console.log('Token cache miss');
|
||||||
|
cachedTokenFailed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedTokenFailed || activate === null) {
|
||||||
|
/* If all goes according to plan, we have a guest token we can use to call API
|
||||||
|
AFAIK there is no limit to how many guest tokens you can request.
|
||||||
|
|
||||||
|
This can effectively mean virtually unlimited (read) access to Twitter's API,
|
||||||
|
which is very funny. */
|
||||||
|
activate = await fetch(guestTokenRequest);
|
||||||
|
}
|
||||||
|
|
||||||
/* Let's grab that guest_token so we can use it */
|
/* Let's grab that guest_token so we can use it */
|
||||||
let activateJson: { guest_token: string };
|
let activateJson: { guest_token: string };
|
||||||
|
@ -71,6 +101,7 @@ export const fetchUsingGuest = async (status: string): Promise<TimelineBlobParti
|
||||||
/* We'll usually only hit this if we get an invalid response from Twitter.
|
/* We'll usually only hit this if we get an invalid response from Twitter.
|
||||||
It's rare, but it happens */
|
It's rare, but it happens */
|
||||||
console.error('Unknown error while fetching conversation from API');
|
console.error('Unknown error while fetching conversation from API');
|
||||||
|
cachedTokenFailed = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,9 +111,13 @@ export const fetchUsingGuest = async (status: string): Promise<TimelineBlobParti
|
||||||
conversation.errors?.[0]?.code === 239)
|
conversation.errors?.[0]?.code === 239)
|
||||||
) {
|
) {
|
||||||
console.log('Failed to fetch conversation, got', conversation);
|
console.log('Failed to fetch conversation, got', conversation);
|
||||||
|
cachedTokenFailed = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Once we've confirmed we have a working guest token, let's cache it! */
|
||||||
|
// event.waitUntil(cache.put(guestTokenRequest, activate.clone()));
|
||||||
|
|
||||||
return conversation;
|
return conversation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { linkFixer } from './linkFixer';
|
||||||
import { Strings } from './strings';
|
import { Strings } from './strings';
|
||||||
|
|
||||||
export const handleQuote = (quote: TweetPartial): string | null => {
|
export const handleQuote = (quote: TweetPartial): string | null => {
|
||||||
console.log('quote tweet: ', quote);
|
console.log('Quoting status ', quote.id_str);
|
||||||
|
|
||||||
let str = `\n`;
|
let str = `\n`;
|
||||||
str += Strings.QUOTE_TEXT.format({
|
str += Strings.QUOTE_TEXT.format({
|
||||||
|
|
|
@ -26,6 +26,7 @@ const statusRequest = async (request: any, event: FetchEvent, flags: InputFlags
|
||||||
let response: Response;
|
let response: Response;
|
||||||
|
|
||||||
let statusResponse = await handleStatus(
|
let statusResponse = await handleStatus(
|
||||||
|
event,
|
||||||
id.match(/\d{2,20}/)?.[0],
|
id.match(/\d{2,20}/)?.[0],
|
||||||
parseInt(mediaNumber || 1),
|
parseInt(mediaNumber || 1),
|
||||||
userAgent,
|
userAgent,
|
||||||
|
|
|
@ -20,13 +20,14 @@ export const returnError = (error: string): StatusResponse => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleStatus = async (
|
export const handleStatus = async (
|
||||||
|
event: FetchEvent,
|
||||||
status: string,
|
status: string,
|
||||||
mediaNumber?: number,
|
mediaNumber?: number,
|
||||||
userAgent?: string,
|
userAgent?: string,
|
||||||
flags?: InputFlags
|
flags?: InputFlags
|
||||||
): Promise<StatusResponse> => {
|
): Promise<StatusResponse> => {
|
||||||
console.log('Direct?', flags?.direct);
|
console.log('Direct?', flags?.direct);
|
||||||
const conversation = await fetchUsingGuest(status);
|
const conversation = await fetchUsingGuest(status, event);
|
||||||
|
|
||||||
const tweet = conversation?.globalObjects?.tweets?.[status] || {};
|
const tweet = conversation?.globalObjects?.tweets?.[status] || {};
|
||||||
/* With v2 conversation API we re-add the user object ot the tweet because
|
/* With v2 conversation API we re-add the user object ot the tweet because
|
||||||
|
|
Loading…
Add table
Reference in a new issue