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
|
import { getById, resetLog, writeError, writeInfo, writeDebug, a, span, div, addClass } from "/common.module.js"
let netflix_file_input = undefined;
export function onLoad() {
const form = getById("form");
netflix_file_input = getById("netflix-file");
form.addEventListener("submit", submitForm);
}
/** @param {SubmitEvent} event */
function submitForm(event) {
event.preventDefault();
event.stopPropagation();
resetLog();
const files = netflix_file_input.files;
if (files.length !== 1) {
writeError("First select your viewing history file.");
return;
}
const netflix_file = files[0];
writeInfo("Checking metadata...");
if (!netflix_file.type.match('text/csv')) {
let detected_filetype = "";
if (netflix_file.type) {
detected_filetype = ", detected filetype: " + netflix_file.type;
}
writeError("Select a CSV file" + detected_filetype);
return;
}
handleFile(netflix_file);
}
/** @param {File} file */
function handleFile(file) {
writeInfo("Reading file...");
file.text()
.then(convertText);
}
const viewingHistoryPattern = /"(.*)","(\d{1,2})\/(\d{1,2})\/(\d+)"/;
/** @param {string} data */
function convertText(data) {
writeInfo("Checking header...");
const [header, ...lines] = data.split(/\r?\n|\r|\n/g);
if (header !== "Title,Date") {
writeError("Invalid Netflix viewing history file, expected header \"Title,Date\"");
return;
}
writeInfo("History count: " + lines.length);
let letterboxd_output = "Title,WatchedDate,Rewatch\n";
let watched_movies = new Set();
for (let line of lines) {
if (!line) continue;
if (line.includes(": Season")
|| line.includes(": Limited Series:")
|| line.includes(": Part")
|| line.includes(": Chapter ")
|| line.includes(": Volume ")
|| line.includes(": Series ")
|| line.includes(": Book ")) {
writeDebug("Skipping show episode: " + line);
continue;
}
if (line.startsWith(": ")) {
writeDebug("Skipping empty title entry")
}
const [_, title, day, month, year] = viewingHistoryPattern.exec(line);
if (title && day && month && year) {
const rewatch = watched_movies.has(title);
letterboxd_output += `"${title}",${year}-${month}-${day},${rewatch}\n`
if (rewatch) {
writeDebug("Rewatch of: " + title);
}
watched_movies.add(title);
}
else {
writeError("could not parse line: " + line);
}
}
let letterboxd_import = new Blob([letterboxd_output], { type: 'text/csv' });
const filename = "netflix-letterboxd-import.csv"
let download_button = a(window.URL.createObjectURL(letterboxd_import), filename)
let download_text = span("Download import file ==> ")
download_button.download = filename;
log.appendChild(div(addClass(download_text, "info"), download_button));
}
|