Blog/Components/Pages/Letterflixd.razor.js 3 K · 93 lines · raw · history

1 import { getById, resetLog, writeError, writeInfo, writeDebug, h } from "/common.module.js"
2
3 const form = getById("form");
4 const netflix_file_input = getById("netflix-file");
5
6 form.addEventListener("submit", submitForm);
7
8 /** @param {SubmitEvent} event */
9 function submitForm(event) {
10 event.preventDefault();
11 event.stopPropagation();
12
13 resetLog();
14 const files = netflix_file_input.files;
15 if (files.length !== 1) {
16 writeError("First select your viewing history file.");
17 return;
18 }
19
20 const netflix_file = files[0];
21
22 writeInfo("Checking metadata...");
23
24 if (!netflix_file.type.match('text/csv')) {
25 let detected_filetype = "";
26 if (netflix_file.type) {
27 detected_filetype = ", detected filetype: " + netflix_file.type;
28 }
29 writeError("Select a CSV file" + detected_filetype);
30 return;
31 }
32
33 handleFile(netflix_file);
34 }
35
36 /** @param {File} file */
37 function handleFile(file) {
38 writeInfo("Reading file...");
39 file.text()
40 .then(convertText);
41 }
42
43 const viewingHistoryPattern = /"(.*)","(\d{1,2})\/(\d{1,2})\/(\d+)"/;
44
45 /** @param {string} data */
46 function convertText(data) {
47 writeInfo("Checking header...");
48 const [header, ...lines] = data.split(/\r?\n|\r|\n/g);
49 if (header !== "Title,Date") {
50 writeError("Invalid Netflix viewing history file, expected header \"Title,Date\"");
51 return;
52 }
53 writeInfo("History count: " + lines.length);
54 let letterboxd_output = "Title,WatchedDate,Rewatch\n";
55 let watched_movies = new Set();
56
57 for (let line of lines) {
58 if (!line) continue;
59 if (line.includes(": Season")
60 || line.includes(": Limited Series:")
61 || line.includes(": Part")
62 || line.includes(": Chapter ")
63 || line.includes(": Volume ")
64 || line.includes(": Series ")
65 || line.includes(": Book ")) {
66 writeDebug("Skipping show episode: " + line);
67 continue;
68 }
69 if (line.startsWith(": ")) {
70 writeDebug("Skipping empty title entry")
71 }
72 const [_, title, day, month, year] = viewingHistoryPattern.exec(line);
73 if (title && day && month && year) {
74 const rewatch = watched_movies.has(title);
75 letterboxd_output += `"${title}",${year}-${month}-${day},${rewatch}\n`
76 if (rewatch) {
77 writeDebug("Rewatch of: " + title);
78 }
79 watched_movies.add(title);
80 }
81 else {
82 writeError("could not parse line: " + line);
83 }
84 }
85
86 let letterboxd_import = new Blob([letterboxd_output], { type: 'text/csv' });
87
88 const filename = "netflix-letterboxd-import.csv"
89 let download_button = h("a", {href: window.URL.createObjectURL(letterboxd_import)}, filename)
90 let download_text = h("span", "Download import file ==> ")
91 download_button.download = filename;
92 log.appendChild(h("div", {class: "info"}, [download_text, download_button]));
93 }