Skip to content

Commit 280518e

Browse files
Essential Randomnessessential-randomness
authored andcommitted
add methods to fetch chapters
1 parent f90f6f4 commit 280518e

File tree

4 files changed

+102
-5
lines changed

4 files changed

+102
-5
lines changed

src/page-loaders.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,16 @@ export const loadUserProfilePage = async ({
7777
(await axios.get<string>(getUserProfileUrl({ username }))).data
7878
) as UserProfile;
7979
};
80+
81+
export interface ChapterIndexPage extends CheerioAPI {
82+
kind: "ChapterIndexPage";
83+
}
84+
export const loadChaptersIndexPage = async ({ workId }: { workId: string }) => {
85+
return load(
86+
(
87+
await axios.get<string>(
88+
`https://archiveofourown.org/works/${workId}/navigate`
89+
)
90+
).data
91+
) as ChapterIndexPage;
92+
};

src/works/chapter-getters.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Author, Chapter } from "types/entities";
2+
import { getWorkDetailsFromUrl, getWorkUrl } from "src/urls";
3+
4+
import { ChapterIndexPage } from "src/page-loaders";
5+
6+
const TITLE_SEPARATOR = ". ";
7+
export const getChaptersList = ($chapterIndexPage: ChapterIndexPage) => {
8+
const chapters: Chapter[] = [];
9+
$chapterIndexPage("ol.index > li").each((index, li) => {
10+
const link = $chapterIndexPage(li).find("a")[0];
11+
const chapterText = $chapterIndexPage(link).text();
12+
const { workId, chapterId } = getWorkDetailsFromUrl({
13+
url: link.attribs.href,
14+
});
15+
const title = chapterText.substring(
16+
chapterText.indexOf(TITLE_SEPARATOR) + TITLE_SEPARATOR.length
17+
);
18+
const dateNode = $chapterIndexPage(
19+
$chapterIndexPage(li).find(".datetime")[0]
20+
);
21+
22+
chapters.push({
23+
id: chapterId!,
24+
workId,
25+
index: index + 1,
26+
title,
27+
// Remove parenthesis from the date
28+
publishedAt: dateNode.text().replace(/[\(\)]/g, ""),
29+
// We rebuild the url so it gets the full path
30+
url: getWorkUrl({ workId, chapterId }),
31+
});
32+
});
33+
return chapters;
34+
};
35+
36+
export const getWorkTitle = ($chapterIndexPage: ChapterIndexPage) => {
37+
return $chapterIndexPage(".works-navigate h2 a[href^='/works/']").text();
38+
};
39+
40+
export const getWorkAuthors = ($chapterIndexPage: ChapterIndexPage) => {
41+
const authors: Author[] = [];
42+
const authorNode = $chapterIndexPage(".works-navigate h2 a[rel='author']");
43+
if (authorNode.text().trim() === "Anonymous") {
44+
return "Anonymous";
45+
}
46+
47+
if (authorNode.length !== 0) {
48+
authorNode.each((i, element) => {
49+
const url = element.attribs.href;
50+
const [, username, pseud] = url.match(/users\/(.+)\/pseuds\/(.+)/)!;
51+
52+
authors.push({ username: username, pseud: decodeURI(pseud) });
53+
});
54+
}
55+
return authors;
56+
};

src/works/index.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
import { LockedWorkSummary, WorkSummary } from "types/entities";
1+
import {
2+
Author,
3+
Chapter,
4+
LockedWorkSummary,
5+
WorkSummary,
6+
} from "types/entities";
7+
import {
8+
getChaptersList,
9+
getWorkAuthors as getWorkAuthorsFromChaptersIndex,
10+
getWorkTitle as getWorkTitleFromChaptersIndex,
11+
} from "./chapter-getters";
212
import {
313
getWorkAdditionalTags,
414
getWorkAuthors,
@@ -21,9 +31,8 @@ import {
2131
getWorkUpdateDate,
2232
getWorkWarnings,
2333
getWorkWordCount,
24-
} from "./getters";
25-
26-
import { loadWorkPage } from "../page-loaders";
34+
} from "./work-getters";
35+
import { loadChaptersIndexPage, loadWorkPage } from "../page-loaders";
2736

2837
export const getWork = async ({
2938
workId,
@@ -64,7 +73,6 @@ export const getWork = async ({
6473
total: totalChapters,
6574
},
6675
complete: totalChapters !== null && totalChapters === publishedChapters,
67-
6876
summary: getWorkSummary(workPage),
6977
stats: {
7078
bookmarks: getWorkBookmarkCount(workPage),
@@ -75,3 +83,23 @@ export const getWork = async ({
7583
locked: false,
7684
};
7785
};
86+
87+
export const getWorkWithChapters = async ({
88+
workId,
89+
}: {
90+
workId: string;
91+
}): Promise<{
92+
title: string;
93+
authors: "Anonymous" | Author[];
94+
workId: string;
95+
chapters: Chapter[];
96+
}> => {
97+
const page = await loadChaptersIndexPage({ workId });
98+
99+
return {
100+
title: getWorkTitleFromChaptersIndex(page),
101+
authors: getWorkAuthorsFromChaptersIndex(page),
102+
workId,
103+
chapters: getChaptersList(page),
104+
};
105+
};
File renamed without changes.

0 commit comments

Comments
 (0)