diff --git a/.env.example b/.env.example
index d094725..b4c372f 100644
--- a/.env.example
+++ b/.env.example
@@ -1,8 +1,9 @@
BRANDING_NAME = "FixTweet / FixupX"
STANDARD_DOMAIN_LIST = "fxtwitter.com,fixupx.com,twittpr.com"
DIRECT_MEDIA_DOMAINS = "d.fxtwitter.com,dl.fxtwitter.com,d.pxtwitter.com,d.twittpr.com,dl.pxtwitter.com,dl.twittpr.com,d.fixupx.com,d.xfixup.com,dl.fixupx.com,dl.xfixup.com"
-TEXT_ONLY_DOMAINS = "t.fxtwitter.com,t.twittpr.com,t.fixupx.com,t.xfixup.com"
-INSTANT_VIEW_DOMAINS = "i.fxtwitter.com,i.twittpr.com,i.fixupx.com,i.xfixup.com"
+TEXT_ONLY_DOMAINS = "t.fxtwitter.com,t.twittpr.com,t.fixupx.com"
+INSTANT_VIEW_DOMAINS = "i.fxtwitter.com,i.twittpr.com,i.fixupx.com"
+GALLERY_DOMAINS = "g.fxtwitter.com,g.twittpr.com,g.fixupx.com"
DEPRECATED_DOMAIN_LIST = "pxtwitter.com,www.pxtwitter.com"
DEPRECATED_DOMAIN_EPOCH = "1559320000000000000"
MOSAIC_DOMAIN_LIST = "mosaic.fxtwitter.com"
diff --git a/esbuild.config.mjs b/esbuild.config.mjs
index a660407..9562607 100644
--- a/esbuild.config.mjs
+++ b/esbuild.config.mjs
@@ -37,6 +37,7 @@ let envVariables = [
'DIRECT_MEDIA_DOMAINS',
'TEXT_ONLY_DOMAINS',
'INSTANT_VIEW_DOMAINS',
+ 'GALLERY_DOMAINS',
'HOST_URL',
'REDIRECT_URL',
'EMBED_URL',
diff --git a/jestconfig.json b/jestconfig.json
index 7e51963..799557b 100644
--- a/jestconfig.json
+++ b/jestconfig.json
@@ -5,10 +5,11 @@
},
"globals": {
"BRANDING_NAME": "FixTweet",
- "TEXT_ONLY_DOMAINS": "t.fxtwitter.com,t.twittpr.com",
- "INSTANT_VIEW_DOMAINS": "i.fxtwitter.com,i.twittpr.com",
+ "TEXT_ONLY_DOMAINS": "t.fxtwitter.com,t.twittpr.com,t.fixupx.com",
+ "INSTANT_VIEW_DOMAINS": "i.fxtwitter.com,i.twittpr.com,i.fixupx.com",
+ "GALLERY_DOMAINS": "g.fxtwitter.com,g.twittpr.com,g.fixupx.com",
"STANDARD_DOMAIN_LIST": "fxtwitter.com,fixupx.com,twittpr.com",
- "DIRECT_MEDIA_DOMAINS": "d.fxtwitter.com,dl.fxtwitter.com",
+ "DIRECT_MEDIA_DOMAINS": "d.fxtwitter.com,dl.fxtwitter.com,d.fixupx.com,dl.fixupx.com",
"MOSAIC_DOMAIN_LIST": "mosaic.fxtwitter.com",
"DEPRECATED_DOMAIN_LIST": "pxtwitter.com,www.pxtwitter.com",
"DEPRECATED_DOMAIN_EPOCH": "1559320000000000000",
diff --git a/src/constants.ts b/src/constants.ts
index 0c2c911..cd8686f 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -5,6 +5,7 @@ export const Constants = {
DIRECT_MEDIA_DOMAINS: DIRECT_MEDIA_DOMAINS.split(','),
TEXT_ONLY_DOMAINS: TEXT_ONLY_DOMAINS.split(','),
INSTANT_VIEW_DOMAINS: INSTANT_VIEW_DOMAINS.split(','),
+ GALLERY_DOMAINS: GALLERY_DOMAINS.split(','),
DEPRECATED_DOMAIN_LIST: DEPRECATED_DOMAIN_LIST.split(','),
DEPRECATED_DOMAIN_EPOCH: BigInt(DEPRECATED_DOMAIN_EPOCH),
MOSAIC_DOMAIN_LIST: MOSAIC_DOMAIN_LIST.split(','),
diff --git a/src/embed/status.ts b/src/embed/status.ts
index ca50b7d..22dcc08 100644
--- a/src/embed/status.ts
+++ b/src/embed/status.ts
@@ -1,3 +1,4 @@
+import { Context } from 'hono';
import { Constants } from '../constants';
import { handleQuote } from '../helpers/quote';
import { formatNumber, sanitizeText, truncateWithEllipsis } from '../helpers/utils';
@@ -7,7 +8,6 @@ import { renderPhoto } from '../render/photo';
import { renderVideo } from '../render/video';
import { renderInstantView } from '../render/instantview';
import { constructTwitterThread } from '../providers/twitter/conversation';
-import { Context } from 'hono';
export const returnError = (c: Context, error: string): Response => {
return c.text(
@@ -148,6 +148,11 @@ export const handleStatus = async (
}
}
+ /* User requested gallery view, but this isn't a post with media */
+ if (flags.gallery && (tweet.media?.all?.length ?? 0) < 1) {
+ flags.gallery = false;
+ }
+
/* At this point, we know we're going to have to create a
regular embed because it's not an API or direct media request */
@@ -160,12 +165,17 @@ export const handleStatus = async (
const headers = [
``,
``,
- ``,
``,
``,
- ``
];
+ if (!flags.gallery) {
+ headers.push(
+ ``,
+ ``
+ );
+ }
+
/* This little thing ensures if by some miracle a FixTweet embed is loaded in a browser,
it will gracefully redirect to the destination instead of just seeing a blank screen.
@@ -389,14 +399,20 @@ export const handleStatus = async (
const useCard = tweet.embed_card === 'tweet' ? tweet.quote?.embed_card : tweet.embed_card;
+
/* Push basic headers relating to author, Tweet text, and site name */
headers.push(
``,
- ``,
- ``,
``
);
+ if (!flags.gallery) {
+ headers.push(
+ ``,
+ ``,
+ );
+ }
+
/* Special reply handling if authorText is not overriden */
if (tweet.replying_to && authorText === Strings.DEFAULT_AUTHOR_TEXT) {
authorText = `↪ Replying to @${tweet.replying_to.screen_name}`;
@@ -408,20 +424,22 @@ export const handleStatus = async (
authorText = `↪ A part of @${tweet.author.screen_name}'s thread`;
}
- /* The additional oembed is pulled by Discord to enable improved embeds.
- Telegram does not use this. */
- headers.push(
- ``.format(
- {
- base: Constants.HOST_URL,
- text: encodeURIComponent(truncateWithEllipsis(authorText, 255)),
- deprecatedFlag: flags?.deprecated ? '&deprecated=true' : '',
- status: encodeURIComponent(status),
- author: encodeURIComponent(tweet.author?.screen_name || ''),
- name: tweet.author.name || ''
- }
- )
- );
+ if (!flags.gallery) {
+ /* The additional oembed is pulled by Discord to enable improved embeds.
+ Telegram does not use this. */
+ headers.push(
+ ``.format(
+ {
+ base: Constants.HOST_URL,
+ text: encodeURIComponent(truncateWithEllipsis(authorText, 255)),
+ deprecatedFlag: flags?.deprecated ? '&deprecated=true' : '',
+ status: encodeURIComponent(status),
+ author: encodeURIComponent(tweet.author?.screen_name || ''),
+ name: tweet.author.name || ''
+ }
+ )
+ );
+ }
/* When dealing with a Tweet of unknown lang, fall back to en */
const lang = tweet.lang === null ? 'en' : tweet.lang || 'en';
diff --git a/src/realms/twitter/routes/status.ts b/src/realms/twitter/routes/status.ts
index 783f11a..9cb24bf 100644
--- a/src/realms/twitter/routes/status.ts
+++ b/src/realms/twitter/routes/status.ts
@@ -55,6 +55,9 @@ export const statusRequest = async (c: Context) => {
} else if (Constants.INSTANT_VIEW_DOMAINS.includes(url.hostname)) {
console.log('Forced instant view request');
flags.forceInstantView = true;
+ } else if (Constants.GALLERY_DOMAINS.includes(url.hostname)) {
+ console.log('Gallery embed request');
+ flags.gallery = true;
} else if (prefix === 'dl' || prefix === 'dir') {
console.log('Direct media request by path prefix');
flags.direct = true;
diff --git a/src/types/env.d.ts b/src/types/env.d.ts
index d38e132..d7af39a 100644
--- a/src/types/env.d.ts
+++ b/src/types/env.d.ts
@@ -3,6 +3,7 @@ declare const STANDARD_DOMAIN_LIST: string;
declare const DIRECT_MEDIA_DOMAINS: string;
declare const TEXT_ONLY_DOMAINS: string;
declare const INSTANT_VIEW_DOMAINS: string;
+declare const GALLERY_DOMAINS: string;
declare const DEPRECATED_DOMAIN_LIST: string;
declare const DEPRECATED_DOMAIN_EPOCH: string;
declare const HOST_URL: string;
diff --git a/src/types/types.d.ts b/src/types/types.d.ts
index e5eb0d2..17a5d8e 100644
--- a/src/types/types.d.ts
+++ b/src/types/types.d.ts
@@ -10,6 +10,7 @@ type InputFlags = {
isXDomain?: boolean;
forceInstantView?: boolean;
archive?: boolean;
+ gallery?: boolean;
};
interface StatusResponse {