import { BufferResolvable } from '@src/utils/interfaces/BufferResolvable' ; import { ResolveBufferOptions } from '@src/utils/interfaces/ResolveBufferOptions' ; import { request } from 'undici' ; import { DiscordooError } from '@src/utils/DiscordooError' ; import { promisify } from 'util' ; import fs from 'fs' ; import path from 'path' ; import { MessageAttachmentResolvable } from '@src/api' ; import { Base64Resolvable } from '@src/utils/interfaces/Base64Resolvable' ; const read = promisify ( fs . readFile ) ; export class DataResolver { static async resolveBuffer ( buffer , options ? ) { if ( Buffer . isBuffer ( buffer ) || buffer instanceof ArrayBuffer ) return buffer ; if ( typeof buffer === 'object' && typeof buffer . pipe === 'function' ) { return new Promise < Buffer > ( ( resolve , reject ) => { const _buf = [ ] ; buffer . on ( 'data' , chunk => _buf . push ( chunk ) ) ; buffer . on ( 'end' , ( ) => resolve ( Buffer . concat ( _buf ) ) ) ; buffer . on ( 'error' , err => reject ( `error converting stream - ${ err }` ) ) ; } ) ; } if ( typeof buffer === 'string' ) { if ( options ?. fetch ) { if ( buffer . startsWith ( 'https://' ) || buffer . startsWith ( 'http://' ) ) { return request ( buffer , options . fetchOptions ) . then ( r => r . body . arrayBuffer ( ) ) ; } } const filePath = path . resolve ( buffer ) ; return read ( filePath ) ; } throw new DiscordooError ( 'DataResolver' , 'do not know how to resolve buffer from:' , typeof buffer ) ; } static async resolveBase64 ( resolvable ) { if ( ! resolvable ) { throw new DiscordooError ( 'DataResolver' , 'do not know how to resolve base64 from' , resolvable ) ; } if ( typeof resolvable === 'string' && resolvable . startsWith ( 'data:' ) ) { return resolvable ; } const buffer = await this . resolveBuffer ( resolvable ) ; return `data:image/png;base64,${ buffer instanceof ArrayBuffer ? this . arrayBufferToBase64 ( buffer ) : buffer . toString ( 'base64' ) }` ; } static arrayBufferToBase64 ( arrayBuffer ) { let base64 = '' ; const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ; const bytes = new Uint8Array ( arrayBuffer ) ; const byteLength = bytes . byteLength ; const byteRemainder = byteLength % 3 ; const mainLength = byteLength - byteRemainder ; let a , b , c , d ; let chunk ; for ( let i = 0 ; i < mainLength ; i = i + 3 ) { chunk = ( bytes [ i ] << 16 ) | ( bytes [ i + 1 ] << 8 ) | bytes [ i + 2 ] ; a = ( chunk & 16515072 ) >> 18 ; b = ( chunk & 258048 ) >> 12 ; c = ( chunk & 4032 ) >> 6 ; d = chunk & 63 ; base64 += encodings [ a ] + encodings [ b ] + encodings [ c ] + encodings [ d ] ; } if ( byteRemainder == 1 ) { chunk = bytes [ mainLength ] ; a = ( chunk & 252 ) >> 2 ; b = ( chunk & 3 ) << 4 ; base64 += encodings [ a ] + encodings [ b ] + '==' ; } else if ( byteRemainder == 2 ) { chunk = ( bytes [ mainLength ] << 8 ) | bytes [ mainLength + 1 ] ; a = ( chunk & 64512 ) >> 10 ; b = ( chunk & 1008 ) >> 4 ; c = ( chunk & 15 ) << 2 ; base64 += encodings [ a ] + encodings [ b ] + encodings [ c ] + '=' ; } return base64 ; } static isBufferResolvable ( resolvable ) { if ( Buffer . isBuffer ( resolvable ) || resolvable instanceof ArrayBuffer ) return true ; if ( typeof resolvable === 'object' && typeof resolvable . pipe === 'function' ) return true ; return typeof resolvable === 'string' && ( resolvable . startsWith ( 'https://' ) || resolvable . startsWith ( 'http://' ) ) ; } static isMessageAttachmentResolvable ( resolvable ) { if ( typeof resolvable !== 'object' ) return false ; if ( 'file' in resolvable ) { return DataResolver . isBufferResolvable ( resolvable . file ) ; } if ( 'url' in resolvable ) { if ( resolvable . url ?. startsWith ( 'https://' ) ) return true ; } if ( 'id' in resolvable ) { return typeof resolvable . id === 'string' ! ; } return false ; } }