google-photos-migrate
Version:
A tool to fix EXIF data and recover filenames from a Google Photos takeout.
80 lines (79 loc) • 3.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyMetaFile = applyMetaFile;
const promises_1 = require("fs/promises");
const ts_1 = require("../ts");
const MetaType_1 = require("./MetaType");
const apply_meta_errors_1 = require("./apply-meta-errors");
async function applyMetaFile(mediaFile, migCtx) {
const metaJson = (await (0, promises_1.readFile)(mediaFile.jsonPath)).toString();
const meta = JSON.parse(metaJson);
// time
const timeTakenTimestamp = meta?.photoTakenTime?.timestamp;
if (timeTakenTimestamp === undefined)
return new apply_meta_errors_1.MissingMetaError(mediaFile, 'photoTakenTime');
const timeTaken = new Date(parseInt(timeTakenTimestamp) * 1000);
// always UTC as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
const timeTakenUTC = timeTaken.toISOString();
const tags = {};
switch (mediaFile.ext.metaType) {
case MetaType_1.MetaType.EXIF:
tags.SubSecDateTimeOriginal = timeTakenUTC;
tags.SubSecCreateDate = timeTakenUTC;
tags.SubSecModifyDate = timeTakenUTC;
break;
case MetaType_1.MetaType.QUICKTIME:
tags.DateTimeOriginal = timeTakenUTC;
tags.CreateDate = timeTakenUTC;
tags.ModifyDate = timeTakenUTC;
tags.TrackCreateDate = timeTakenUTC;
tags.TrackModifyDate = timeTakenUTC;
tags.MediaCreateDate = timeTakenUTC;
tags.MediaModifyDate = timeTakenUTC;
break;
case MetaType_1.MetaType.NONE:
break;
default:
(0, ts_1.exhaustiveCheck)(mediaFile.ext.metaType);
}
tags.ModifyDate = timeTakenUTC;
// description
const description = meta?.description;
tags.Description = description;
tags['Caption-Abstract'] = description;
tags.ImageDescription = description;
// gps
const [alt, lat, lon] = [
meta?.geoData?.altitude,
meta?.geoData?.latitude,
meta?.geoData?.longitude,
];
if (![alt, lat, lon].some((axis) => axis === undefined)) {
tags.GPSAltitude = alt;
tags.GPSAltitudeRef = `${alt}`;
tags.GPSLatitude = lat;
tags.GPSLatitudeRef = `${lat}`;
tags.GPSLongitude = lon;
tags.GPSLongitudeRef = `${lon}`;
}
try {
await migCtx.exiftool.write(mediaFile.path, tags, {
writeArgs: migCtx.exiftoolArgs,
});
// Set file modification times to the photo taken timestamp
await (0, promises_1.utimes)(mediaFile.path, timeTaken, timeTaken);
}
catch (e) {
if (e instanceof Error) {
const wrongExtMatch = e.message.match(/Not a valid (?<current>\w+) \(looks more like a (?<actual>\w+)\)/);
const current = wrongExtMatch?.groups?.['current'];
const actual = wrongExtMatch?.groups?.['actual'];
if (current !== undefined && actual !== undefined) {
return new apply_meta_errors_1.WrongExtensionError(mediaFile, `.${current.toLowerCase()}`, `.${actual.toLowerCase()}`);
}
return new apply_meta_errors_1.ExifToolError(mediaFile, e);
}
return new apply_meta_errors_1.ExifToolError(mediaFile, new Error(`${e}`));
}
return null;
}