commit 8e9398bd020ea292a25a5e8d8de88ccb5d35507d Author: Kai Moschcau Date: Sun Feb 18 15:00:07 2024 +0100 feat: initial version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ccbe46 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules/ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c1e532c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,30 @@ +{ + "name": "Downloads", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "exifreader": "^4.21.0" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/exifreader": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/exifreader/-/exifreader-4.21.0.tgz", + "integrity": "sha512-A/EjsCKdfzzF2lvi+iu2klTOZNYf3MrXJAYKX+NyJn35wlujGmbDGVvZ+21FYy3ZxsWHwf37VntgMrQXFuR5sA==", + "hasInstallScript": true, + "optionalDependencies": { + "@xmldom/xmldom": "^0.8.10" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..68c9e69 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "exifreader": "^4.21.0" + } +} diff --git a/update_ts.mjs b/update_ts.mjs new file mode 100644 index 0000000..999e8bf --- /dev/null +++ b/update_ts.mjs @@ -0,0 +1,79 @@ +import fs from "fs/promises"; +import ExifReader from "exifreader"; +import path from "path"; + +if (process.argv.length === 2) { + console.error("Expected exactly one argument"); + process.exit(1); +} +const dir = process.argv[2]; + +let fileNames; +try { + fileNames = await fs.readdir(dir); +} catch (error) { + console.error("Error reading directory.", error); + process.exit(2); +} + +/** + * @param fileName {string} + * @return {Date|null} + */ +function getDateFromFileName(fileName) { + const r = /(\d{4})-?(\d{2})-?(\d{2})[_\-](\d{2})-?(\d{2})-?(\d{2})/.exec( + fileName, + ); + if (!r) throw new Error("The file name did not match the pattern."); + + return new Date(`${r[1]}-${r[2]}-${r[3]}T${r[4]}:${r[5]}:${r[6]}`); +} + +/** + * @param filePath {string} + * @param fileName {string} + * @return {Promise} + */ +async function getDate(filePath, fileName) { + if (/\.mp4$/.test(fileName)) { + return getDateFromFileName(fileName); + } + + const tags = await ExifReader.load(filePath); + let timeString = tags.DateTime?.value[0]; + if (timeString === undefined) { + return getDateFromFileName(fileName); + } + + const exifDate = new Date( + timeString.replace( + /(\d{4}):(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})/, + "$1-$2-$3T$4:$5:$6", + ), + ); + + if (isNaN(exifDate.getTime()) || exifDate.getFullYear() < 2000) { + return getDateFromFileName(fileName); + } + + return exifDate; +} + +for (const fileName of fileNames) { + const filePath = path.resolve(dir, fileName); + + let date; + try { + date = await getDate(filePath, fileName); + } catch (error) { + console.error(filePath, error.message); + continue; + } + if (date === null) { + console.error(filePath, "Could not get a date."); + continue; + } + console.log(filePath, date); + + await fs.utimes(filePath, date, date); +}