mirror of
https://github.com/CompeyDev/fxtwitter-docker.git
synced 2025-04-05 18:40:56 +01:00
Merge pull request #230 from FixTweet/analytics-engine
Merge Cloudflare Analytics Engine
This commit is contained in:
commit
d3e255d911
4 changed files with 42 additions and 8 deletions
|
@ -143,17 +143,45 @@ const populateTweetProperties = async (
|
||||||
return apiTweet;
|
return apiTweet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const writeDataPoint = (event: FetchEvent, language: string | undefined, nsfw: boolean, returnCode: string, flags?: InputFlags) => {
|
||||||
|
console.log('Writing data point...');
|
||||||
|
if (typeof AnalyticsEngine !== 'undefined') {
|
||||||
|
const flagString = Object.keys(flags || {})
|
||||||
|
// @ts-expect-error - TypeScript doesn't like iterating over the keys, but that's OK
|
||||||
|
.filter(flag => flags?.[flag])[0] || 'standard';
|
||||||
|
|
||||||
|
console.log(flagString)
|
||||||
|
|
||||||
|
AnalyticsEngine.writeDataPoint({
|
||||||
|
blobs: [
|
||||||
|
event.request.cf?.colo as string, /* Datacenter location */
|
||||||
|
event.request.cf?.country as string, /* Country code */
|
||||||
|
event.request.headers.get('user-agent') ?? '', /* User agent (for aggregating bots calling) */
|
||||||
|
returnCode, /* Return code */
|
||||||
|
flagString, /* Type of request */
|
||||||
|
language ?? '', /* For translate feature */
|
||||||
|
],
|
||||||
|
doubles: [
|
||||||
|
nsfw ? 1 : 0 /* NSFW media = 1, No NSFW Media = 0 */
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* API for Twitter statuses (Tweets)
|
/* API for Twitter statuses (Tweets)
|
||||||
Used internally by FixTweet's embed service, or
|
Used internally by FixTweet's embed service, or
|
||||||
available for free using api.fxtwitter.com. */
|
available for free using api.fxtwitter.com. */
|
||||||
export const statusAPI = async (
|
export const statusAPI = async (
|
||||||
status: string,
|
status: string,
|
||||||
language: string | undefined,
|
language: string | undefined,
|
||||||
event: FetchEvent
|
event: FetchEvent,
|
||||||
|
flags?: InputFlags
|
||||||
): Promise<APIResponse> => {
|
): Promise<APIResponse> => {
|
||||||
let conversation = await fetchConversation(status, event);
|
let conversation = await fetchConversation(status, event);
|
||||||
let tweet = conversation?.globalObjects?.tweets?.[status] || {};
|
let tweet = conversation?.globalObjects?.tweets?.[status] || {};
|
||||||
|
|
||||||
|
let wasMediaBlockedNSFW = false;
|
||||||
|
|
||||||
if (tweet.retweeted_status_id_str) {
|
if (tweet.retweeted_status_id_str) {
|
||||||
tweet = conversation?.globalObjects?.tweets?.[tweet.retweeted_status_id_str] || {};
|
tweet = conversation?.globalObjects?.tweets?.[tweet.retweeted_status_id_str] || {};
|
||||||
}
|
}
|
||||||
|
@ -170,6 +198,7 @@ export const statusAPI = async (
|
||||||
|
|
||||||
if (typeof tweet.full_text !== 'undefined') {
|
if (typeof tweet.full_text !== 'undefined') {
|
||||||
console.log('Successfully loaded Tweet using elongator');
|
console.log('Successfully loaded Tweet using elongator');
|
||||||
|
wasMediaBlockedNSFW = true;
|
||||||
} else if (
|
} else if (
|
||||||
typeof tweet.full_text === 'undefined' &&
|
typeof tweet.full_text === 'undefined' &&
|
||||||
conversation.timeline?.instructions?.length > 0
|
conversation.timeline?.instructions?.length > 0
|
||||||
|
@ -177,20 +206,24 @@ export const statusAPI = async (
|
||||||
console.log(
|
console.log(
|
||||||
'Tweet could not be accessed with elongator, must be private/suspended'
|
'Tweet could not be accessed with elongator, must be private/suspended'
|
||||||
);
|
);
|
||||||
|
writeDataPoint(event, language, wasMediaBlockedNSFW, 'PRIVATE_TWEET', flags);
|
||||||
return { code: 401, message: 'PRIVATE_TWEET' };
|
return { code: 401, message: 'PRIVATE_TWEET' };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* {"errors":[{"code":34,"message":"Sorry, that page does not exist."}]} */
|
/* {"errors":[{"code":34,"message":"Sorry, that page does not exist."}]} */
|
||||||
if (conversation.errors?.[0]?.code === 34) {
|
if (conversation.errors?.[0]?.code === 34) {
|
||||||
|
writeDataPoint(event, language, wasMediaBlockedNSFW, 'NOT_FOUND', flags);
|
||||||
return { code: 404, message: 'NOT_FOUND' };
|
return { code: 404, message: 'NOT_FOUND' };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tweets object is completely missing, smells like API failure */
|
/* Tweets object is completely missing, smells like API failure */
|
||||||
if (typeof conversation?.globalObjects?.tweets === 'undefined') {
|
if (typeof conversation?.globalObjects?.tweets === 'undefined') {
|
||||||
|
writeDataPoint(event, language, wasMediaBlockedNSFW, 'API_FAIL', flags);
|
||||||
return { code: 500, message: 'API_FAIL' };
|
return { code: 500, message: 'API_FAIL' };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have no idea what happened then just return API error */
|
/* If we have no idea what happened then just return API error */
|
||||||
|
writeDataPoint(event, language, wasMediaBlockedNSFW, 'API_FAIL', flags);
|
||||||
return { code: 500, message: 'API_FAIL' };
|
return { code: 500, message: 'API_FAIL' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,5 +250,7 @@ export const statusAPI = async (
|
||||||
/* Finally, staple the Tweet to the response and return it */
|
/* Finally, staple the Tweet to the response and return it */
|
||||||
response.tweet = apiTweet;
|
response.tweet = apiTweet;
|
||||||
|
|
||||||
|
writeDataPoint(event, language, wasMediaBlockedNSFW, 'OK', flags);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const handleStatus = async (
|
||||||
): Promise<StatusResponse> => {
|
): Promise<StatusResponse> => {
|
||||||
console.log('Direct?', flags?.direct);
|
console.log('Direct?', flags?.direct);
|
||||||
|
|
||||||
const api = await statusAPI(status, language, event as FetchEvent);
|
const api = await statusAPI(status, language, event as FetchEvent, flags);
|
||||||
const tweet = api?.tweet as APITweet;
|
const tweet = api?.tweet as APITweet;
|
||||||
|
|
||||||
/* Catch this request if it's an API response */
|
/* Catch this request if it's an API response */
|
||||||
|
|
8
src/types/env.d.ts
vendored
8
src/types/env.d.ts
vendored
|
@ -15,9 +15,5 @@ declare const RELEASE_NAME: string;
|
||||||
|
|
||||||
declare const TEST: boolean | undefined;
|
declare const TEST: boolean | undefined;
|
||||||
|
|
||||||
declare const TwitterProxy: {
|
declare const TwitterProxy: Fetcher;
|
||||||
fetch: (
|
declare const AnalyticsEngine: AnalyticsEngineDataset;
|
||||||
input: RequestInfo<unknown, CfProperties<unknown>>,
|
|
||||||
init?: RequestInit<RequestInitCfProperties> | undefined
|
|
||||||
) => Promise<Response>;
|
|
||||||
};
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ send_metrics = false
|
||||||
services = [
|
services = [
|
||||||
{ binding = "TwitterProxy", service = "elongator" }
|
{ binding = "TwitterProxy", service = "elongator" }
|
||||||
]
|
]
|
||||||
|
analytics_engine_datasets = [
|
||||||
|
{ binding = "AnalyticsEngine" }
|
||||||
|
]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
command = "npm run build"
|
command = "npm run build"
|
||||||
|
|
Loading…
Add table
Reference in a new issue