-
Notifications
You must be signed in to change notification settings - Fork 0
/
lister.ts
119 lines (101 loc) · 3.08 KB
/
lister.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import path from "path";
import fs from "fs";
import type { ScriptInfo, SupportedVideoTypes } from "./types";
type ListType = {
id: ScriptInfo["source"]["id"];
title: string;
};
type ListTypeList = Array<ListType>;
const directory = path.join(__dirname, "transcripts");
const files = fs.readdirSync(directory);
const listing: Partial<Record<SupportedVideoTypes, ListTypeList>> = {};
const recentlyAdded: ListTypeList = [];
function toSortedByProperty<T>(arr: T[], key: keyof T): T[]{
// @ts-expect-error: VSCode doesn't know about Array.toSorted
return arr.toSorted((left, right) => {
if(left[key] < right[key]){
return -1;
}
if(left[key] > right[key]){
return 1;
}
return 0;
});
}
const generateTitle = ({type, title, creator, seriesTitle, season, episode}: ScriptInfo["metadata"]) => {
switch(type){
case "television episode": {
if(seriesTitle && !isNaN(+(season ?? NaN)) && !isNaN(+(episode ?? NaN))){
return `${seriesTitle} S${season}E${episode}: ${title}`
}
}
case "other": {
if(creator){
return `[${creator}] ${title}`;
}
// Explicit fall-through
}
case "movie": {
// Explicit fall-through
}
case "music video": {
// Explicit fall-through
}
default: {
return title;
}
}
}
const cutOffPoint = new Date().valueOf() - (1000 * 60 * 60 * 24 * 7); // 7 days ago
files.forEach((f) => {
const stats = fs.statSync(path.join(directory, f));
if(stats.isDirectory()){
return;
}
const {source, metadata}: ScriptInfo = JSON.parse(fs.readFileSync(path.join(directory, f)).toString());
if(metadata.draft || metadata.requiresExtension){
return;
}
const metadataBundle = {
id: source.id,
title: generateTitle(metadata)
};
listing[metadata.type] ??= [];
listing[metadata.type]?.push(metadataBundle);
if(stats.birthtimeMs > cutOffPoint){
recentlyAdded.push(metadataBundle);
}
});
const title = "Description Listing";
const displayType: Record<SupportedVideoTypes, string> = {
"movie": "Movie",
"music video": "Music Video",
"other": "Other",
"television episode": "Television Episode"
};
const printListItems = (list: ListTypeList) => list.map(({id, title}) => {
return `<li><a href="./youtube_embed.html?id=${id}">${title}</a></li>`;
}).join("\n\t\t\t");
const html = `
<!doctype html>
<html>
<head>
<title>${title}</title>
</head>
<body>
<h1>${title}</h1>
<h2>Recently Added</h2>
<ul>
${printListItems(recentlyAdded)}
</ul>
${Object.entries(listing).map(([type, scripts]) => {
return `
<h2>${displayType[type as SupportedVideoTypes]}</h2>
<ul>
${printListItems(toSortedByProperty<ListType>(scripts, "title"))}
</ul>`;
}).join("\n\n")}
</body>
</html>
`;
fs.writeFileSync("./public/listing.html", html);