Extension to return old Twitter layout from 2015.
1// This script generates Firefox version of the extension and packs Chrome and Firefox versions to zip files.
2
3const fsp = require('fs').promises;
4const fs = require('fs');
5const path = require('path');
6const AdmZip = require('adm-zip');
7const args = process.argv.slice(2);
8
9async function copyDir(src, dest) {
10 const entries = await fsp.readdir(src, { withFileTypes: true });
11 await fsp.mkdir(dest);
12 for (let entry of entries) {
13 if(entry.name === '.git' || entry.name === '.github' || entry.name === '_metadata' || entry.name === 'node_modules') continue;
14 const srcPath = path.join(src, entry.name);
15 const destPath = path.join(dest, entry.name);
16 if (entry.isDirectory()) {
17 await copyDir(srcPath, destPath);
18 } else {
19 await fsp.copyFile(srcPath, destPath);
20 }
21 }
22}
23
24if(fs.existsSync('../OldTwitterTempChrome')) {
25 fs.rmSync('../OldTwitterTempChrome', { recursive: true });
26}
27if(fs.existsSync('../OldTwitterFirefox')) {
28 fs.rmSync('../OldTwitterFirefox', { recursive: true });
29}
30
31console.log("Copying...");
32copyDir('./', '../OldTwitterFirefox').then(async () => {
33 await copyDir('./', '../OldTwitterTempChrome');
34 console.log("Copied!");
35 console.log("Patching...");
36 let manifest = JSON.parse(fs.readFileSync('../OldTwitterFirefox/manifest.json', 'utf8'));
37 manifest.manifest_version = 2;
38 manifest.background.scripts = ['scripts/background.js'];
39 manifest.web_accessible_resources = manifest.web_accessible_resources[0].resources;
40 manifest.permissions = manifest.permissions.filter(p => p !== 'declarativeNetRequest' && p !== 'contextMenus' && p !== 'scripting');
41 manifest.permissions = [
42 ...manifest.permissions,
43 ...manifest.host_permissions,
44 "https://dimden.dev/*",
45 "https://raw.githubusercontent.com/*",
46 "webRequest",
47 "webRequestBlocking"
48 ];
49 delete manifest.host_permissions;
50 delete manifest.declarative_net_request;
51 delete manifest.background.service_worker;
52 delete manifest.action;
53 manifest.content_scripts = [
54 {
55 "matches": ["https://mobile.twitter.com/*", "https://twitter.com/*?*newtwitter=true*"],
56 "js": ["scripts/xIconRemove.js"],
57 "all_frames": true,
58 "run_at": "document_start"
59 },
60 {
61 "matches": ["https://mobile.twitter.com/*", "https://twitter.com/*?*newtwitter=true*"],
62 "js": ["scripts/newtwitter.js"],
63 "all_frames": true,
64 "run_at": "document_end"
65 },
66 {
67 "matches": ["https://twitter.com/*"],
68 "exclude_matches": ["https://twitter.com/*?*newtwitter=true*", "https://twitter.com/settings/download_your_data", "https://twitter.com/i/flow/login*"],
69 "js": ["scripts/config.js", "scripts/helpers.js", "scripts/apis.js", "scripts/injection.js", "libraries/parseCssColor.js", "libraries/twemoji.min.js", "libraries/custom-elements.min.js", "libraries/emojipicker.js"],
70 "all_frames": true,
71 "run_at": "document_start"
72 },
73 {
74 "matches": ["https://twitter.com/*"],
75 "exclude_matches": ["https://twitter.com/*?*newtwitter=true*", "https://twitter.com/settings/download_your_data", "https://twitter.com/i/flow/login*"],
76 "js": ["layouts/header/script.js", "scripts/tweetviewer.js", "libraries/gif.js", "libraries/viewer.min.js", "libraries/tinytoast.js"],
77 "css": ["libraries/viewer.min.css"],
78 "all_frames": true,
79 "run_at": "document_idle"
80 },
81 {
82 "matches": ["https://twitter.com/home", "https://twitter.com/home?*", "https://twitter.com/", "https://twitter.com/?*", "https://twitter.com/home/", "https://twitter.com/home/?*"],
83 "js": ["layouts/home/script.js"],
84 "all_frames": true,
85 "run_at": "document_idle"
86 },
87 {
88 "matches": [
89 "https://twitter.com/notifications", "https://twitter.com/notifications/", "https://twitter.com/notifications?*", "https://twitter.com/notifications/?*",
90 "https://twitter.com/notifications/mentions", "https://twitter.com/notifications/mentions?*", "https://twitter.com/notifications/mentions/", "https://twitter.com/notifications/mentions/?*"
91 ],
92 "js": ["layouts/notifications/script.js"],
93 "all_frames": true,
94 "run_at": "document_idle"
95 },
96 {
97 "matches": ["https://twitter.com/old/settings", "https://twitter.com/old/settings/", "https://twitter.com/old/settings?*", "https://twitter.com/old/settings/?*"],
98 "js": ["layouts/settings/script.js", "libraries/viewer.min.js"],
99 "all_frames": true,
100 "run_at": "document_idle"
101 },
102 {
103 "matches": ["https://twitter.com/search", "https://twitter.com/search?*", "https://twitter.com/search/", "https://twitter.com/search/?*"],
104 "js": ["layouts/search/script.js"],
105 "run_at": "document_idle",
106 "all_frames": true
107 },
108 {
109 "matches": [
110 "https://twitter.com/*/status/*", "https://twitter.com/*/status/*?*", "https://twitter.com/*/status/*/", "https://twitter.com/*/status/*/?*",
111 "https://twitter.com/*/status/*/likes", "https://twitter.com/*/status/*/likes/", "https://twitter.com/*/status/*/likes?*", "https://twitter.com/*/status/*/likes/?*",
112 "https://twitter.com/*/status/*/retweets", "https://twitter.com/*/status/*/retweets/", "https://twitter.com/*/status/*/retweets?*", "https://twitter.com/*/status/*/retweets/?*",
113 "https://twitter.com/*/status/*/retweets/with_comments", "https://twitter.com/*/status/*/retweets/with_comments/", "https://twitter.com/*/status/*/retweets/with_comments?*", "https://twitter.com/*/status/*/retweets/with_comments/?*"
114 ],
115 "js": ["layouts/tweet/script.js"],
116 "run_at": "document_idle",
117 "all_frames": true
118 },
119 {
120 "matches": [
121 "https://twitter.com/i/lists/*", "https://twitter.com/i/lists/*/", "https://twitter.com/i/lists/*?*", "https://twitter.com/i/lists/*/?*",
122 "https://twitter.com/i/lists/*/members", "https://twitter.com/i/lists/*/members/", "https://twitter.com/i/lists/*/members?*", "https://twitter.com/i/lists/*/members/?*",
123 "https://twitter.com/i/lists/*/followers", "https://twitter.com/i/lists/*/followers/", "https://twitter.com/i/lists/*/followers?*", "https://twitter.com/i/lists/*/followers/?*"
124 ],
125 "js": ["layouts/lists/script.js"],
126 "all_frames": true,
127 "run_at": "document_idle"
128 },
129 {
130 "matches": ["https://twitter.com/i/bookmarks", "https://twitter.com/i/bookmarks/", "https://twitter.com/i/bookmarks?*", "https://twitter.com/i/bookmarks/?*"],
131 "js": ["layouts/bookmarks/script.js"],
132 "all_frames": true,
133 "run_at": "document_idle"
134 },
135 {
136 "matches": ["https://twitter.com/i/topics/*", "https://twitter.com/i/topics/*/", "https://twitter.com/i/topics/*?*", "https://twitter.com/i/topics/*/?*"],
137 "js": ["layouts/topics/script.js"],
138 "all_frames": true,
139 "run_at": "document_idle"
140 },
141 {
142 "matches": ["https://twitter.com/old/history", "https://twitter.com/old/history/", "https://twitter.com/old/history?*", "https://twitter.com/old/history/?*"],
143 "js": ["layouts/history/script.js"],
144 "all_frames": true,
145 "run_at": "document_idle"
146 },
147 {
148 "matches": ["https://twitter.com/old/unfollows/*", "https://twitter.com/old/unfollows/*/", "https://twitter.com/old/unfollows/*?*", "https://twitter.com/old/unfollows/*/?*"],
149 "js": ["layouts/unfollows/script.js"],
150 "all_frames": true,
151 "run_at": "document_idle"
152 },
153 {
154 "matches": ["https://twitter.com/i/timeline", "https://twitter.com/i/timeline?*", "https://twitter.com/i/timeline/", "https://twitter.com/i/timeline/?*"],
155 "js": ["layouts/itl/script.js"],
156 "all_frames": true,
157 "run_at": "document_idle"
158 },
159 {
160 "matches": ["https://twitter.com/*", "https://twitter.com/*/", "https://twitter.com/*/with_replies", "https://twitter.com/*/with_replies/", "https://twitter.com/*/media", "https://twitter.com/*/likes", "https://twitter.com/*/following", "https://twitter.com/*/followers", "https://twitter.com/*/followers_you_follow", "https://twitter.com/*/followers_you_follow/", "https://twitter.com/*/media/", "https://twitter.com/*/likes/", "https://twitter.com/*/following/", "https://twitter.com/*/followers/"],
161 "exclude_matches": [
162 "https://twitter.com/",
163 "https://twitter.com/home",
164 "https://twitter.com/notifications",
165 "https://twitter.com/notifications/",
166 "https://twitter.com/messages",
167 "https://twitter.com/messages/",
168 "https://twitter.com/settings",
169 "https://twitter.com/settings/",
170 "https://twitter.com/explore",
171 "https://twitter.com/explore/",
172 "https://twitter.com/old/*",
173 "https://twitter.com/login",
174 "https://twitter.com/login/",
175 "https://twitter.com/register",
176 "https://twitter.com/register/",
177 "https://twitter.com/signin",
178 "https://twitter.com/signin/",
179 "https://twitter.com/signup",
180 "https://twitter.com/signup/",
181 "https://twitter.com/logout",
182 "https://twitter.com/logout/",
183 "https://twitter.com/i/*",
184 "https://twitter.com/*/status/*",
185 "https://twitter.com/*/status/*/",
186 "https://twitter.com/search?*",
187 "https://twitter.com/search",
188 "https://twitter.com/search/",
189 "https://twitter.com/search/?*",
190 "https://twitter.com/tos",
191 "https://twitter.com/privacy",
192 "https://twitter.com/*/tos",
193 "https://twitter.com/*/privacy"
194 ],
195 "js": ["layouts/profile/script.js"],
196 "run_at": "document_idle",
197 "all_frames": true
198 }
199 ];
200
201 let config = fs.readFileSync('../OldTwitterFirefox/scripts/config.js', 'utf8');
202 config = config.replace(/chrome\.storage\.sync\./g, "chrome.storage.local.");
203 let helpers = fs.readFileSync('../OldTwitterFirefox/scripts/helpers.js', 'utf8');
204 helpers = helpers.replace(/chrome\.storage\.sync\./g, "chrome.storage.local.");
205 let tweetviewer = fs.readFileSync('../OldTwitterFirefox/scripts/tweetviewer.js', 'utf8');
206 tweetviewer = tweetviewer.replace(/chrome\.storage\.sync\./g, "chrome.storage.local.");
207 let content = fs.readFileSync('../OldTwitterFirefox/scripts/injection.js', 'utf8');
208 content = content.replace(/chrome.runtime.sendMessage\(\{.+?\}\)/gs, "");
209 content = content.replace(/chrome\.storage\.sync\./g, "chrome.storage.local.");
210
211 let apis = fs.readFileSync('../OldTwitterFirefox/scripts/apis.js', 'utf8');
212 apis = apis.replace(/chrome\.storage\.sync\./g, "chrome.storage.local.");
213 if(apis.includes("&& true") || apis.includes("&& false") || apis.includes("|| true") || apis.includes("|| false") || apis.includes("&&true") || apis.includes("&&false") || apis.includes("||true") || apis.includes("||false")) {
214 if(args[0] === '-a') {
215 let line = apis.split("\n").findIndex(l => l.includes("&& true") || l.includes("&& false") || l.includes("|| true") || l.includes("|| false") || l.includes("&&true") || l.includes("&&false") || l.includes("||true") || l.includes("||false"));
216 console.warn("::warning file=scripts/api.js,line=" + (line+1) + "::Probably temporary boolean left in code.");
217 } else {
218 for(let i = 0; i < 3; i++) {
219 console.warn("\x1b[33m", "Warning: probably temporary boolean left in code.", '\x1b[0m');
220 }
221 }
222 }
223
224 let background = fs.readFileSync('../OldTwitterFirefox/scripts/background_v2.js', 'utf8');
225
226 fs.writeFileSync('../OldTwitterFirefox/manifest.json', JSON.stringify(manifest, null, 2));
227 fs.writeFileSync('../OldTwitterFirefox/scripts/injection.js', content);
228 fs.writeFileSync('../OldTwitterFirefox/scripts/helpers.js', helpers);
229 fs.writeFileSync('../OldTwitterFirefox/scripts/tweetviewer.js', tweetviewer);
230 fs.writeFileSync('../OldTwitterFirefox/scripts/config.js', config);
231 fs.writeFileSync('../OldTwitterFirefox/scripts/background.js', background);
232 fs.writeFileSync('../OldTwitterFirefox/scripts/apis.js', apis);
233 fs.unlinkSync('../OldTwitterFirefox/ruleset.json');
234 fs.unlinkSync('../OldTwitterFirefox/pack.js');
235 fs.unlinkSync('../OldTwitterTempChrome/pack.js');
236 fs.unlinkSync('../OldTwitterTempChrome/scripts/background_v2.js');
237 fs.unlinkSync('../OldTwitterFirefox/scripts/background_v2.js');
238 fs.unlinkSync('../OldTwitterFirefox/.gitignore');
239 fs.unlinkSync('../OldTwitterTempChrome/.gitignore');
240 fs.unlinkSync('../OldTwitterFirefox/test.js');
241 fs.unlinkSync('../OldTwitterTempChrome/test.js');
242 fs.unlinkSync('../OldTwitterFirefox/package.json');
243 fs.unlinkSync('../OldTwitterTempChrome/package.json');
244 fs.unlinkSync('../OldTwitterFirefox/package-lock.json');
245 fs.unlinkSync('../OldTwitterTempChrome/package-lock.json');
246
247 let layouts = fs.readdirSync('../OldTwitterFirefox/layouts');
248 for (let layout of layouts) {
249 let script = fs.readFileSync(`../OldTwitterFirefox/layouts/${layout}/script.js`, 'utf8');
250 script = script.replace(/chrome\.storage\.sync\./g, "chrome.storage.local.");
251 script = script.replace("https://chrome.google.com/webstore/detail/old-twitter-layout-2022/jgejdcdoeeabklepnkdbglgccjpdgpmf", "https://addons.mozilla.org/en-US/firefox/addon/old-twitter-layout-2022/");
252 fs.writeFileSync(`../OldTwitterFirefox/layouts/${layout}/script.js`, script);
253
254 let style = fs.readFileSync(`../OldTwitterFirefox/layouts/${layout}/style.css`, 'utf8');
255 style = style.replaceAll("chrome-extension://", "moz-extension://");
256 fs.writeFileSync(`../OldTwitterFirefox/layouts/${layout}/style.css`, style);
257
258 let html = fs.readFileSync(`../OldTwitterFirefox/layouts/${layout}/index.html`, 'utf8');
259 html = html.replaceAll("chrome-extension://", "moz-extension://");
260 fs.writeFileSync(`../OldTwitterFirefox/layouts/${layout}/index.html`, html);
261 }
262
263 console.log("Patched!");
264 if (fs.existsSync('../OldTwitterFirefox.zip')) {
265 console.log("Deleting old zip...");
266 fs.unlinkSync('../OldTwitterFirefox.zip');
267 console.log("Deleted old zip!");
268 }
269 console.log("Zipping Firefox version...");
270 try {
271 const zip = new AdmZip();
272 const outputDir = "../OldTwitterFirefox.zip";
273 zip.addLocalFolder("../OldTwitterFirefox");
274 zip.writeZip(outputDir);
275 } catch (e) {
276 console.log(`Something went wrong ${e}`);
277 }
278 console.log(`Zipped Firefox version into ${path.resolve('../OldTwitterFirefox.zip')}!`);
279 console.log("Zipping Chrome version...");
280 try {
281 const zip = new AdmZip();
282 const outputDir = "../OldTwitterChrome.zip";
283 zip.addLocalFolder("../OldTwitterTempChrome");
284 zip.writeZip(outputDir);
285 } catch (e) {
286 console.log(`Something went wrong ${e}`);
287 }
288 console.log(`Zipped Chrome version into ${path.resolve('../OldTwitterChrome.zip')}!`);
289 console.log("Deleting temporary folders...");
290 fs.rmSync('../OldTwitterTempChrome', { recursive: true });
291 fs.rmSync('../OldTwitterFirefox', { recursive: true });
292 console.log("Deleted!");
293});