import fs from 'fs' ; import { Buffer } from 'buffer' ; import fileType from 'file-type' ; import jpeg from 'jpeg-js' ; import { PNG } from 'pngjs' ; import request from 'request' ; import { URL } from 'url' ; import blockhash from './block-hash' ; const processPNG = ( data , bits , method , cb ) => { try { const png = PNG . sync . read ( data ) ; const res = blockhash ( png , bits , method ? 2 : 1 ) ; cb ( null , res ) ; } catch ( e ) { cb ( e ) ; } } ; const processJPG = ( data , bits , method , cb ) => { try { const decoded = jpeg . decode ( data ) ; const res = blockhash ( decoded , bits , method ? 2 : 1 ) ; cb ( null , res ) ; } catch ( e ) { cb ( e ) ; } } ; const isUrlRequestObject = ( obj ) : obj is UrlRequestObject => { const casted = ( obj as UrlRequestObject ) ; return casted . url && casted . url . length > 0 ; } ; const isBufferObject = ( obj ) : obj is BufferObject => { const casted = ( obj as BufferObject ) ; return Buffer . isBuffer ( casted . data ) || ( Buffer . isBuffer ( casted . data ) && ( casted . ext && casted . ext . length > 0 ) ) ; } ; export interface UrlRequestObject { encoding ? : string | null ; url : string | null ; } export interface BufferObject { ext ? : string ; data : Buffer ; name ? : string ; } export const imageHash = ( oldSrc , bits , method , cb ) => { const src = oldSrc ; const getFileType = async ( data ) => { if ( typeof src !== 'string' && isBufferObject ( src ) && src . ext ) { return { mime : src . ext , } ; } try { if ( Buffer . isBuffer ( data ) ) { return await fileType . fromBuffer ( data ) ; } if ( typeof src === 'string' ) { return await fileType . fromFile ( src ) ; } return '' ; } catch ( err ) { throw err ; } } ; const checkFileType = ( name , data ) => { getFileType ( data ) . then ( ( type ) => { if ( ! type ) { cb ( new Error ( 'Mime type not found' ) ) ; return ; } if ( name && name . lastIndexOf ( '.' ) > 0 ) { const ext = name . split ( '.' ) . pop ( ) . toLowerCase ( ) ; if ( ext === 'png' && type . mime === 'image/png' ) { processPNG ( data , bits , method , cb ) ; } else if ( ( ext === 'jpg' || ext === 'jpeg' ) && type . mime === 'image/jpeg' ) { processJPG ( data , bits , method , cb ) ; } else { cb ( new Error ( `Unrecognized file extension, mime type or mismatch, ext: ${ ext } / mime: ${ type }` ) ) ; } } else { console . warn ( 'No file extension found, attempting mime typing.' ) ; if ( type . mime === 'image/png' ) { processPNG ( data , bits , method , cb ) ; } else if ( type . mime === 'image/jpeg' ) { processJPG ( data , bits , method , cb ) ; } else { cb ( new Error ( `Unrecognized mime type: ${ type }` ) ) ; } } } ) . catch ( ( err ) => { cb ( err ) ; } ) ; } ; const handleRequest = ( err , res ) => { if ( err ) { cb ( new Error ( err ) ) ; } else { const url = new URL ( res . request . uri . href ) ; const name = url . pathname ; checkFileType ( name , res . body ) ; } } ; const handleReadFile = ( err , res ) => { if ( err ) { cb ( new Error ( err ) ) ; return ; } checkFileType ( src , res ) ; } ; if ( src === undefined ) { cb ( new Error ( 'No image source provided' ) ) ; return ; } if ( typeof src === 'string' && ( src . indexOf ( 'http' ) === 0 || src . indexOf ( 'https' ) === 0 ) ) { const req = { url : src , encoding : null , } ; request ( req , handleRequest ) ; } else if ( typeof src !== 'string' && isBufferObject ( src ) ) { checkFileType ( src . name , src . data ) ; } else if ( typeof src !== 'string' && isUrlRequestObject ( src ) ) { src . encoding = null ; request ( src , handleRequest ) ; } else { fs . readFile ( src , handleReadFile ) ; } } ;