refactor code

This commit is contained in:
Abhinav 2023-04-11 17:03:59 +05:30
parent 4b653a3f2f
commit bcd05b04c3
3 changed files with 80 additions and 73 deletions

View file

@ -1,82 +1,45 @@
import { import {
EXIFLESS_FORMATS, EXIFLESS_FORMATS,
EXIF_LIBRARY_UNSUPPORTED_FORMATS, EXIF_LIBRARY_UNSUPPORTED_FORMATS,
NULL_EXTRACTED_METADATA,
NULL_LOCATION, NULL_LOCATION,
} from 'constants/upload'; } from 'constants/upload';
import { ElectronFile, Location } from 'types/upload'; import { Location } from 'types/upload';
import exifr from 'exifr'; import exifr from 'exifr';
import piexif from 'piexifjs'; import piexif from 'piexifjs';
import { FileTypeInfo } from 'types/upload'; import { FileTypeInfo } from 'types/upload';
import { logError } from 'utils/sentry'; import { logError } from 'utils/sentry';
import { ParsedExtractedMetadata } from 'types/upload';
import { getUnixTimeInMicroSeconds } from 'utils/time'; import { getUnixTimeInMicroSeconds } from 'utils/time';
import { CustomError } from 'utils/error'; import { CustomError } from 'utils/error';
const EXIF_TAGS_NEEDED = [ type ParsedEXIFData = Record<string, any> &
'DateTimeOriginal', Partial<{
'CreateDate', DateTimeOriginal: Date;
'ModifyDate', CreateDate: Date;
'GPSLatitude', ModifyDate: Date;
'GPSLongitude', latitude: number;
'GPSLatitudeRef', longitude: number;
'GPSLongitudeRef', }>;
];
interface Exif {
DateTimeOriginal?: Date;
CreateDate?: Date;
ModifyDate?: Date;
GPSLatitude?: number;
GPSLongitude?: number;
GPSLatitudeRef?: number;
GPSLongitudeRef?: number;
}
export async function getImageMetadata( type RawEXIFData = Record<string, any> &
receivedFile: File | ElectronFile, Partial<{
fileTypeInfo: FileTypeInfo DateTimeOriginal: string;
): Promise<ParsedExtractedMetadata> { CreateDate: string;
let imageMetadata = NULL_EXTRACTED_METADATA; ModifyDate: string;
try { latitude: number;
if (!(receivedFile instanceof File)) { longitude: number;
receivedFile = new File( }>;
[await receivedFile.blob()],
receivedFile.name,
{
lastModified: receivedFile.lastModified,
}
);
}
const exifData = await getParsedExifData(
receivedFile,
fileTypeInfo,
EXIF_TAGS_NEEDED
);
if (!exifData) {
return imageMetadata;
}
imageMetadata = {
location: getEXIFLocation(exifData),
creationTime: getEXIFTime(exifData),
};
} catch (e) {
logError(e, 'getExifData failed');
}
return imageMetadata;
}
export async function getParsedExifData( export async function getParsedExifData(
receivedFile: File, receivedFile: File,
fileTypeInfo: FileTypeInfo, fileTypeInfo: FileTypeInfo,
tags?: string[] tags?: string[]
) { ): Promise<Partial<ParsedEXIFData>> {
try { try {
const exifData = await exifr.parse(receivedFile, { const exifData: RawEXIFData = await exifr.parse(receivedFile, {
reviveValues: false, reviveValues: false,
pick: tags, pick: tags,
}); });
const parsedExif = parseExifData(exifData); return parseExifData(exifData);
return parsedExif;
} catch (e) { } catch (e) {
if (!EXIFLESS_FORMATS.includes(fileTypeInfo.mimeType)) { if (!EXIFLESS_FORMATS.includes(fileTypeInfo.mimeType)) {
if ( if (
@ -91,20 +54,23 @@ export async function getParsedExifData(
}); });
} }
} }
throw e;
} }
} }
function parseExifData(exifData: Record<string, any>) { function parseExifData(exifData: RawEXIFData): ParsedEXIFData {
const parsedExif = { if (!exifData) {
...exifData, throw new Error(CustomError.EXIF_DATA_NOT_FOUND);
}; }
if (exifData.DateTimeOriginal) { const { DateTimeOriginal, CreateDate, ModifyDate, ...rest } = exifData;
const parsedExif: ParsedEXIFData = { ...rest };
if (DateTimeOriginal) {
parsedExif.DateTimeOriginal = parseEXIFDate(exifData.DateTimeOriginal); parsedExif.DateTimeOriginal = parseEXIFDate(exifData.DateTimeOriginal);
} }
if (exifData.CreateDate) { if (CreateDate) {
parsedExif.CreateDate = parseEXIFDate(exifData.CreateDate); parsedExif.CreateDate = parseEXIFDate(exifData.CreateDate);
} }
if (exifData.ModifyDate) { if (ModifyDate) {
parsedExif.ModifyDate = parseEXIFDate(exifData.ModifyDate); parsedExif.ModifyDate = parseEXIFDate(exifData.ModifyDate);
} }
return parsedExif; return parsedExif;
@ -147,14 +113,14 @@ function parseEXIFDate(dataTimeString: string) {
} }
} }
export function getEXIFLocation(exifData): Location { export function getEXIFLocation(exifData: ParsedEXIFData): Location {
if (!exifData.latitude || !exifData.longitude) { if (!exifData.latitude || !exifData.longitude) {
return NULL_LOCATION; return NULL_LOCATION;
} }
return { latitude: exifData.latitude, longitude: exifData.longitude }; return { latitude: exifData.latitude, longitude: exifData.longitude };
} }
function getEXIFTime(exifData: Exif) { export function getEXIFTime(exifData: ParsedEXIFData): number {
const dateTime = const dateTime =
exifData.DateTimeOriginal ?? exifData.CreateDate ?? exifData.ModifyDate; exifData.DateTimeOriginal ?? exifData.CreateDate ?? exifData.ModifyDate;
if (!dateTime) { if (!dateTime) {
@ -197,12 +163,6 @@ async function convertImageToDataURL(reader: FileReader, blob: Blob) {
return dataURL; return dataURL;
} }
function convertToExifDateFormat(date: Date) {
return `${date.getFullYear()}:${
date.getMonth() + 1
}:${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
}
function dataURIToBlob(dataURI) { function dataURIToBlob(dataURI) {
// convert base64 to raw binary data held in a string // convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
@ -226,3 +186,9 @@ function dataURIToBlob(dataURI) {
const blob = new Blob([ab], { type: mimeString }); const blob = new Blob([ab], { type: mimeString });
return blob; return blob;
} }
function convertToExifDateFormat(date: Date) {
return `${date.getFullYear()}:${
date.getMonth() + 1
}:${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
}

View file

@ -1,6 +1,6 @@
import { FILE_TYPE } from 'constants/file'; import { FILE_TYPE } from 'constants/file';
import { logError } from 'utils/sentry'; import { logError } from 'utils/sentry';
import { getImageMetadata } from './exifService'; import { getEXIFLocation, getEXIFTime, getParsedExifData } from './exifService';
import { import {
Metadata, Metadata,
ParsedMetadataJSON, ParsedMetadataJSON,
@ -31,6 +31,16 @@ const NULL_PARSED_METADATA_JSON: ParsedMetadataJSON = {
...NULL_LOCATION, ...NULL_LOCATION,
}; };
const EXIF_TAGS_NEEDED = [
'DateTimeOriginal',
'CreateDate',
'ModifyDate',
'GPSLatitude',
'GPSLongitude',
'GPSLatitudeRef',
'GPSLongitudeRef',
];
export async function extractMetadata( export async function extractMetadata(
worker: Remote<DedicatedCryptoWorker>, worker: Remote<DedicatedCryptoWorker>,
receivedFile: File | ElectronFile, receivedFile: File | ElectronFile,
@ -59,6 +69,36 @@ export async function extractMetadata(
return metadata; return metadata;
} }
export async function getImageMetadata(
receivedFile: File | ElectronFile,
fileTypeInfo: FileTypeInfo
): Promise<ParsedExtractedMetadata> {
let imageMetadata = NULL_EXTRACTED_METADATA;
try {
if (!(receivedFile instanceof File)) {
receivedFile = new File(
[await receivedFile.blob()],
receivedFile.name,
{
lastModified: receivedFile.lastModified,
}
);
}
const exifData = await getParsedExifData(
receivedFile,
fileTypeInfo,
EXIF_TAGS_NEEDED
);
imageMetadata = {
location: getEXIFLocation(exifData),
creationTime: getEXIFTime(exifData),
};
} catch (e) {
logError(e, 'getExifData failed');
}
return imageMetadata;
}
export const getMetadataJSONMapKey = ( export const getMetadataJSONMapKey = (
collectionID: number, collectionID: number,

View file

@ -59,6 +59,7 @@ export const CustomError = {
EXPORT_FOLDER_DOES_NOT_EXIST: 'export folder does not exist', EXPORT_FOLDER_DOES_NOT_EXIST: 'export folder does not exist',
NO_INTERNET_CONNECTION: 'no internet connection', NO_INTERNET_CONNECTION: 'no internet connection',
AUTH_KEY_NOT_FOUND: 'auth key not found', AUTH_KEY_NOT_FOUND: 'auth key not found',
EXIF_DATA_NOT_FOUND: 'exif data not found',
}; };
export function parseUploadErrorCodes(error) { export function parseUploadErrorCodes(error) {