Skip to content

Commit a030516

Browse files
authored
Adds support for use with other OTW archives
Allow changing the archive URL at runtime, and add tests for superlove
2 parents b3f2d1d + 334d369 commit a030516

85 files changed

Lines changed: 9111 additions & 7077 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"coverage": "vitest run --coverage",
4040
"encode-mock-files": "ts-node-esm tests/mocks/scripts/encode-mock-files.mts",
4141
"redownload": "tsx tests/mocks/scripts/redownload-articles.mts",
42-
"download": "tsx tests/mocks/scripts/download-ao3-url.mts"
42+
"download": "tsx tests/mocks/scripts/download-archive-url.mts"
4343
},
4444
"repository": {
4545
"type": "git",

src/urls.ts

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,26 @@ import {
55
} from "./utils";
66
import { WorkSummary } from "types/entities";
77

8-
const ARCHIVE_BASE_URL =
9-
process.env.ARCHIVE_BASE_URL ?? "https://archiveofourown.org";
8+
declare global {
9+
var archiveBaseUrl: string;
10+
}
11+
12+
const DEFAULT_BASE_URL =
13+
import.meta.env.ARCHIVE_BASE_URL ?? "https://archiveofourown.org";
14+
15+
globalThis.archiveBaseUrl = DEFAULT_BASE_URL;
16+
17+
export const setArchiveBaseUrl = (url: string) => {
18+
globalThis.archiveBaseUrl = url;
19+
};
20+
21+
export const getArchiveBaseUrl = () => {
22+
return globalThis.archiveBaseUrl;
23+
};
24+
25+
export const resetArchiveBaseUrl = () => {
26+
globalThis.archiveBaseUrl = DEFAULT_BASE_URL;
27+
};
1028

1129
export const getWorkUrl = ({
1230
workId,
@@ -38,33 +56,42 @@ export const getWorkUrl = ({
3856
workPath += `/chapters/${chapterId}`;
3957
}
4058

41-
return new URL(workPath, ARCHIVE_BASE_URL).href;
59+
return new URL(workPath, getArchiveBaseUrl()).href;
4260
};
4361

4462
export const getWorkIndexUrl = ({ workId }: { workId: string | number }) => {
4563
if (!isValidArchiveId(workId)) {
4664
throw new Error(`${workId} is not a valid work id`);
4765
}
48-
49-
return new URL(`works/${workId}/navigate`, ARCHIVE_BASE_URL).href;
66+
return new URL(`works/${workId}/navigate`, getArchiveBaseUrl()).href;
5067
};
5168

5269
export const getSeriesUrl = ({ seriesId }: { seriesId: string | number }) => {
5370
if (!isValidArchiveId(seriesId)) {
5471
throw new Error(`${seriesId} is not a valid series id`);
5572
}
5673

57-
return new URL(`series/${seriesId}`, ARCHIVE_BASE_URL).href;
74+
return new URL(`series/${seriesId}`, getArchiveBaseUrl()).href;
5875
};
5976

60-
export const getAsShortUrl = ({ url }: { url: string }) => {
61-
if (!url.includes("archiveofourown")) {
62-
throw new Error("We only support short URLs for AO3");
77+
export const getAsShortUrl = ({ url }: { url: string | URL }) => {
78+
const longUrl = new URL(url);
79+
if (longUrl.hostname !== "archiveofourown.org") {
80+
throw new Error(
81+
`Short URLs are only supported for AO3 (found: ${longUrl.hostname})`
82+
);
6383
}
6484

65-
return url.replace(/archiveofourown/, "ao3");
85+
longUrl.host = "ao3.org";
86+
return longUrl.href;
6687
};
6788

89+
/**
90+
* Gets the download URLs for a work.
91+
*
92+
* Warning: while this method will return the download URLs for locked works,
93+
* people may not be able to download them.
94+
*/
6895
export const getDownloadUrls = ({
6996
id,
7097
title,
@@ -75,7 +102,8 @@ export const getDownloadUrls = ({
75102
| Pick<WorkSummary, "id" | "title" | "updatedAt" | "publishedAt">
76103
| WorkSummary) => {
77104
const timestamp = new Date(updatedAt ?? publishedAt).valueOf();
78-
const downloadLinkBase = new URL(`downloads/${id}/`, ARCHIVE_BASE_URL).href;
105+
const downloadLinkBase = new URL(`downloads/${id}/`, getArchiveBaseUrl())
106+
.href;
79107
const urlSafeTitle = title.replaceAll(/\s/g, "_");
80108

81109
return {
@@ -88,7 +116,7 @@ export const getDownloadUrls = ({
88116
};
89117

90118
export const getUserProfileUrl = ({ username }: { username: string }) =>
91-
new URL(`/users/${encodeURI(username)}/profile`, ARCHIVE_BASE_URL).href;
119+
new URL(`/users/${encodeURI(username)}/profile`, getArchiveBaseUrl()).href;
92120

93121
const TOKEN_REPLACEMENTS_MAP = {
94122
"/": "*s*",
@@ -128,14 +156,14 @@ export const getTagUrl = (tagName: string) =>
128156
(char: string) =>
129157
isReplaceableToken(char) ? TOKEN_REPLACEMENTS_MAP[char] : char
130158
)}/`,
131-
ARCHIVE_BASE_URL
159+
getArchiveBaseUrl()
132160
).href;
133161

134162
export const getTagWorksFeedUrl = (tagName: string) =>
135163
new URL(`works`, getTagUrl(tagName)).href;
136164

137165
export const getTagWorksFeedAtomUrl = (tagId: string) =>
138-
new URL(`tags/${tagId}/feed.atom`, ARCHIVE_BASE_URL).href;
166+
new URL(`tags/${tagId}/feed.atom`, getArchiveBaseUrl()).href;
139167

140168
export const getWorkDetailsFromUrl = ({
141169
url,

tests/mocks/data/series/1728802/index.html renamed to tests/mocks/data/ao3/series/1728802/index.html

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<script src="/javascripts/livevalidation_standalone.js"></script>
3434

3535
<meta name="csrf-param" content="authenticity_token" />
36-
<meta name="csrf-token" content="GQRPbM2AGgehAcOGV1gGAGAnMa541tjABraViOEQxyHPFxoEmn_vzlhTVxGcefUdywJPTJtXP8opgOy7JAlYGw" />
36+
<meta name="csrf-token" content="D9ixzuNWg9CQlL0P9ecIvSzdPhqOvoGXJtVEqcLdUoiZI2VAD-mdC4tTRBDF41Y-nDPND9rdV-yXMk0DT1lR7A" />
3737

3838

3939
</head>
@@ -56,7 +56,7 @@ <h1 class="heading">
5656
<a id="login-dropdown" href="/users/login">Log In</a>
5757
</p>
5858
<div id="small_login" class="simple login">
59-
<form class="new_user" id="new_user_session_small" action="/users/login" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="D7bxQsKav-3k9z4m76o9mdCYXqxWK2YV1vUz8tSJGZoohFcERHYrTAuGRZMyQp2geHM96yDnqJaX-K95qYNfsQ" autocomplete="off" />
59+
<form class="new_user" id="new_user_session_small" action="/users/login" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="XYVBrUY1h41nf1NMdTl7VY8KShe5VlITL9_fFXv4YjFJ9oUolvrUJGQSAdgBpicS9r8uShR40ozlMSWlQP8ONA" autocomplete="off" />
6060
<dl>
6161
<dt><label for="user_session_login_small">Username or email:</label></dt>
6262
<dd><input autocomplete="on" id="user_session_login_small" type="text" name="user[login]" /></dd>
@@ -137,7 +137,7 @@ <h1 class="heading">
137137
<p>
138138
<label class="landmark" for="site_search">Work Search</label>
139139
<input class="text" id="site_search" aria-describedby="site_search_tooltip" type="text" name="work_search[query]" />
140-
<span class="tip" role="tooltip" id="site_search_tooltip">tip: hetalia f/f sort:kudos</span>
140+
<span class="tip" role="tooltip" id="site_search_tooltip">tip: &quot;uchiha sasuke/uzumaki naruto&quot; angst kudos&gt;10</span>
141141
<span class="submit actions"><input type="submit" value="Search" class="button" /></span>
142142
</p>
143143
</fieldset>
@@ -237,7 +237,7 @@ <h5 class="fandoms heading">
237237
<!--required tags-->
238238
<ul class="required-tags">
239239
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="rating-notrated rating" title="Not Rated"><span class="text">Not Rated</span></span></a></li>
240-
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="warning-choosenotto warnings" title="Choose Not To Use Archive Warnings"><span class="text">Choose Not To Use Archive Warnings</span></span></a></li>
240+
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="warning-choosenotto warnings" title="Creator Chose Not To Use Archive Warnings"><span class="text">Creator Chose Not To Use Archive Warnings</span></span></a></li>
241241
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="category-gen category" title="Gen"><span class="text">Gen</span></span></a></li>
242242
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="complete-yes iswip" title="Complete Work"><span class="text">Complete Work</span></span></a></li>
243243
</ul>
@@ -281,13 +281,13 @@ <h6 class="landmark heading">Series</h6>
281281
<dd class="comments"><a href="/works/23977417?show_comments=true#comments">27</a></dd>
282282

283283
<dt class="kudos">Kudos:</dt>
284-
<dd class="kudos"><a href="/works/23977417#kudos">548</a></dd>
284+
<dd class="kudos"><a href="/works/23977417#kudos">551</a></dd>
285285

286286
<dt class="bookmarks">Bookmarks:</dt>
287287
<dd class="bookmarks"><a href="/works/23977417/bookmarks">79</a></dd>
288288

289289
<dt class="hits">Hits:</dt>
290-
<dd class="hits">8,055</dd>
290+
<dd class="hits">8,072</dd>
291291

292292
</dl>
293293

@@ -320,7 +320,7 @@ <h5 class="fandoms heading">
320320
<!--required tags-->
321321
<ul class="required-tags">
322322
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="rating-notrated rating" title="Not Rated"><span class="text">Not Rated</span></span></a></li>
323-
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="warning-choosenotto warnings" title="Choose Not To Use Archive Warnings"><span class="text">Choose Not To Use Archive Warnings</span></span></a></li>
323+
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="warning-choosenotto warnings" title="Creator Chose Not To Use Archive Warnings"><span class="text">Creator Chose Not To Use Archive Warnings</span></span></a></li>
324324
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="category-het category" title="F/M"><span class="text">F/M</span></span></a></li>
325325
<li> <a class="help symbol question modal" title="Symbols key" href="/help/symbols-key.html"><span class="complete-yes iswip" title="Complete Work"><span class="text">Complete Work</span></span></a></li>
326326
</ul>
@@ -364,13 +364,13 @@ <h6 class="landmark heading">Series</h6>
364364
<dd class="comments"><a href="/works/24121558?show_comments=true#comments">20</a></dd>
365365

366366
<dt class="kudos">Kudos:</dt>
367-
<dd class="kudos"><a href="/works/24121558#kudos">412</a></dd>
367+
<dd class="kudos"><a href="/works/24121558#kudos">413</a></dd>
368368

369369
<dt class="bookmarks">Bookmarks:</dt>
370370
<dd class="bookmarks"><a href="/works/24121558/bookmarks">98</a></dd>
371371

372372
<dt class="hits">Hits:</dt>
373-
<dd class="hits">7,724</dd>
373+
<dd class="hits">7,755</dd>
374374

375375
</dl>
376376

@@ -447,13 +447,13 @@ <h6 class="landmark heading">Series</h6>
447447
<dd class="comments"><a href="/works/24597715?show_comments=true#comments">17</a></dd>
448448

449449
<dt class="kudos">Kudos:</dt>
450-
<dd class="kudos"><a href="/works/24597715#kudos">1,091</a></dd>
450+
<dd class="kudos"><a href="/works/24597715#kudos">1,094</a></dd>
451451

452452
<dt class="bookmarks">Bookmarks:</dt>
453453
<dd class="bookmarks"><a href="/works/24597715/bookmarks">118</a></dd>
454454

455455
<dt class="hits">Hits:</dt>
456-
<dd class="hits">11,323</dd>
456+
<dd class="hits">11,354</dd>
457457

458458
</dl>
459459

@@ -499,7 +499,7 @@ <h4 class="heading">Contact Us</h4>
499499
<h4 class="heading">Development</h4>
500500
<ul class="menu">
501501
<li>
502-
<a href="https://github.com/otwcode/otwarchive/commits/v0.9.427.1">otwarchive v0.9.427.1</a>
502+
<a href="https://github.com/otwcode/otwarchive/commits/v0.9.429.1">otwarchive v0.9.429.1</a>
503503
</li>
504504
<li><a href="/known_issues">Known Issues</a></li>
505505
<li>
@@ -589,5 +589,5 @@ <h4 class="heading">Development</h4>
589589
</script>
590590

591591

592-
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97c130c4697f7ede',t:'MTc1NzM2MzI4Ny4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
592+
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'983c9e6f887f27d8',t:'MTc1ODY1NzUzNy4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
593593
</html>

0 commit comments

Comments
 (0)