Skip to content

Commit 8ec9bf1

Browse files
committed
Add series getters
1 parent 610a837 commit 8ec9bf1

File tree

1 file changed

+230
-0
lines changed

1 file changed

+230
-0
lines changed

src/series/getters.ts

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import { Author, Series, SeriesWorkSummary } from "types/entities";
2+
import { SeriesPage, WorkPage } from "../page-loaders";
3+
import { CheerioAPI, load } from "cheerio";
4+
import { getWorkDetailsFromUrl } from "src/urls";
5+
import {
6+
getWorkBookmarkCount,
7+
getWorkHits,
8+
getWorkKudosCount,
9+
getWorkLanguage,
10+
getWorkPublishedChapters,
11+
getWorkTotalChapters,
12+
getWorkWordCount,
13+
} from "src/works/work-getters";
14+
15+
const monthMap: { [month: string]: string } = {
16+
Jan: "01",
17+
Feb: "02",
18+
Mar: "03",
19+
Apr: "04",
20+
May: "05",
21+
Jun: "06",
22+
Jul: "07",
23+
Aug: "08",
24+
Sep: "09",
25+
Oct: "10",
26+
Nov: "11",
27+
Dec: "12",
28+
};
29+
30+
export const getSeriesTitle = ($seriesPage: SeriesPage): string => {
31+
return $seriesPage("h2.heading").text().trim();
32+
};
33+
34+
export const getSeriesAuthors = (
35+
$seriesPage: SeriesPage
36+
): Series["authors"] => {
37+
const authorLinks = $seriesPage("dl.series a[rel=author]");
38+
const authors: Author[] = [];
39+
40+
if (
41+
$seriesPage("dl.series dd:nth-of-type(1)").text().trim() === "Anonymous"
42+
) {
43+
return "Anonymous";
44+
}
45+
46+
if (authorLinks.length !== 0) {
47+
authorLinks.each((i, element) => {
48+
const url = element.attribs.href;
49+
const [, username, pseud] = url.match(/users\/(.+)\/pseuds\/(.+)/)!;
50+
51+
authors.push({ username: username, pseud: decodeURI(pseud) });
52+
});
53+
}
54+
55+
return authors;
56+
};
57+
58+
export const getSeriesDescription = (
59+
$seriesPage: SeriesPage
60+
): string | null => {
61+
const description = $seriesPage("dl.series blockquote.userstuff").html();
62+
return description ? description.trim() : null;
63+
};
64+
65+
export const getSeriesPublishDate = ($seriesPage: SeriesPage): string => {
66+
return $seriesPage("dl.series > dd:nth-of-type(2)").text().trim();
67+
};
68+
69+
export const getSeriesUpdateDate = ($seriesPage: SeriesPage): string => {
70+
return $seriesPage("dl.series > dd:nth-of-type(3)").text().trim();
71+
};
72+
73+
export const getSeriesWordCount = ($seriesPage: SeriesPage): number => {
74+
return parseInt(
75+
$seriesPage("dl.meta dl.stats dd:nth-of-type(1)")
76+
.text()
77+
.replaceAll(",", "")
78+
.trim()
79+
);
80+
};
81+
82+
export const getSeriesWorkCount = ($seriesPage: SeriesPage): number => {
83+
return parseInt(
84+
$seriesPage("dl.meta dl.stats dd:nth-of-type(2)")
85+
.text()
86+
.replaceAll(",", "")
87+
.trim()
88+
);
89+
};
90+
91+
export const getSeriesCompletionStatus = ($seriesPage: SeriesPage): boolean => {
92+
return $seriesPage("dl.stats dd:nth-of-type(3)").text().trim() === "Yes";
93+
};
94+
95+
export const getSeriesBookmarkCount = ($seriesPage: SeriesPage): number => {
96+
return parseInt(
97+
$seriesPage("dl.meta dl.stats dd:nth-of-type(4)")
98+
.text()
99+
.replaceAll(",", "")
100+
.trim()
101+
);
102+
};
103+
104+
export const getSeriesWorks = (
105+
$seriesPage: SeriesPage
106+
): SeriesWorkSummary[] => {
107+
const works: SeriesWorkSummary[] = [];
108+
109+
$seriesPage("ul.index > li.work").each((index, element) => {
110+
works[index] = getSeriesWork($seriesPage(element).html() as string);
111+
});
112+
113+
return works;
114+
};
115+
116+
// Helpers for series' works
117+
interface SeriesWork extends CheerioAPI {
118+
kind: "SeriesWork";
119+
}
120+
121+
const getSeriesWork = (workHtml: string): SeriesWorkSummary => {
122+
const work = load(workHtml);
123+
const $work = work as SeriesWork,
124+
$$work = work as WorkPage;
125+
126+
const totalChapters = getWorkTotalChapters($$work);
127+
const publishedChapters = getWorkPublishedChapters($$work);
128+
129+
const url = $work("a[href*='/works/']").attr("href") as string;
130+
131+
return {
132+
id: getWorkDetailsFromUrl({ url }).workId,
133+
title: getSeriesWorkTitle($work),
134+
updatedAt: getSeriesWorkUpdateDate($work),
135+
136+
summary: getSeriesWorkSummary($work),
137+
adult: false,
138+
fandoms: getSeriesWorkFandoms($work),
139+
tags: {
140+
characters: getSeriesWorkCharacters($work),
141+
relationships: getSeriesWorkRelationships($work),
142+
additional: getSeriesWorkAdditionalTags($work),
143+
},
144+
authors: getSeriesWorkAuthors($work),
145+
language: getWorkLanguage($$work),
146+
words: getWorkWordCount($$work),
147+
chapters: {
148+
published: publishedChapters,
149+
total: totalChapters,
150+
},
151+
complete: totalChapters !== null && totalChapters === publishedChapters,
152+
stats: {
153+
bookmarks: getWorkBookmarkCount($$work),
154+
kudos: getWorkKudosCount($$work),
155+
hits: getWorkHits($$work),
156+
},
157+
};
158+
};
159+
160+
const getSeriesWorkTitle = ($work: SeriesWork) => {
161+
return $work("h4.heading a[href*='/works/']").text().trim();
162+
};
163+
164+
const getSeriesWorkUpdateDate = ($work: SeriesWork) => {
165+
const [day, month, year] = $work("p.datetime").text().trim().split(" ");
166+
return `${year}-${monthMap[month]}-${day}`;
167+
};
168+
169+
const getSeriesWorkSummary = ($work: SeriesWork) => {
170+
const summary = $work("blockquote.summary").html();
171+
return summary ? summary.trim() : null;
172+
};
173+
174+
const getSeriesWorkFandoms = ($work: SeriesWork): string[] => {
175+
const fandoms: string[] = [];
176+
177+
$work("h5.fandoms a.tag").each(function (i, element) {
178+
fandoms[i] = $work(element).text().trim();
179+
});
180+
return fandoms;
181+
};
182+
183+
const getSeriesWorkCharacters = ($work: SeriesWork): string[] => {
184+
const characters: string[] = [];
185+
186+
$work("li.characters a.tag").each(function (i, character) {
187+
characters[i] = $work(character).text().trim();
188+
});
189+
return characters;
190+
};
191+
192+
const getSeriesWorkRelationships = ($work: SeriesWork): string[] => {
193+
const ships: string[] = [];
194+
195+
$work("li.relationships a.tag").each(function (i, ship) {
196+
ships[i] = $work(ship).text().trim();
197+
});
198+
return ships;
199+
};
200+
201+
const getSeriesWorkAdditionalTags = ($work: SeriesWork): string[] => {
202+
const tags: string[] = [];
203+
204+
$work("li.freeforms a.tag").each(function (i) {
205+
tags[i] = $work(this).text().trim();
206+
});
207+
return tags;
208+
};
209+
210+
const getSeriesWorkAuthors = (
211+
$work: SeriesWork
212+
): SeriesWorkSummary["authors"] => {
213+
const authorLinks = $work("h4.heading a[rel='author']");
214+
const authors: Author[] = [];
215+
216+
if ($work("h4.heading").text().split("by")[1].trim() === "Anonymous") {
217+
return "Anonymous";
218+
}
219+
220+
if (authorLinks.length !== 0) {
221+
authorLinks.each((i, element) => {
222+
const url = element.attribs.href;
223+
const [, username, pseud] = url.match(/users\/(.+)\/pseuds\/(.+)/)!;
224+
225+
authors.push({ username: username, pseud: decodeURI(pseud) });
226+
});
227+
}
228+
229+
return authors;
230+
};

0 commit comments

Comments
 (0)