import * as hash from 'hash.js' ; import Long from 'long' ; import { AssetContent , ContentType , ConversationContent , LocationContent , TextContent } from '../conversation/content' ; export type AvailableMessageContent = AssetContent | LocationContent | TextContent ; export class MessageHashService { private readonly messageContent : AvailableMessageContent ; private readonly timestamp : number ; constructor ( messageContent , timestamp = Date . now ( ) ) { this . messageContent = messageContent ; const unixTimestamp = new Date ( timestamp ) . getTime ( ) ; this . timestamp = Math . floor ( unixTimestamp / 1e3 ) ; } private createSha256Hash ( buffer ) { const hashArray = hash . sha256 ( ) . update ( buffer ) . digest ( ) ; return Buffer . from ( hashArray ) ; } private convertToUtf16BE ( str ) { const BOMChar = '\uFEFF' ; str = `${ BOMChar }${ str }` ; const buffer = Buffer . from ( str , 'ucs2' ) ; for ( let index = 0 ; index < buffer . length ; index += 2 ) { const tempValue = buffer [ index ] ; buffer [ index ] = buffer [ index + 1 ] ; buffer [ index + 1 ] = tempValue ; } return buffer ; } private getAssetBytes ( content ) { if ( content . uploaded ) { const assetId = content . uploaded . assetId ; return this . convertToUtf16BE ( assetId ) ; } return Buffer . from ( [ ] ) ; } private getTimestampBuffer ( timestamp ) { const timestampBytes = Long . fromInt ( timestamp ) . toBytesBE ( ) ; return Buffer . from ( timestampBytes ) ; } private getLocationBytes ( content ) { const latitudeApproximate = Math . round ( content . latitude * 1000 ) ; const longitudeApproximate = Math . round ( content . longitude * 1000 ) ; const latitudeLong = Long . fromInt ( latitudeApproximate ) . toBytesBE ( ) ; const longitudeLong = Long . fromInt ( longitudeApproximate ) . toBytesBE ( ) ; const latitudeBuffer = Buffer . from ( latitudeLong ) ; const longitudeBuffer = Buffer . from ( longitudeLong ) ; return Buffer . concat ( [ latitudeBuffer , longitudeBuffer ] ) ; } private getTextBytes ( content ) { return this . convertToUtf16BE ( content . text ) ; } private getBytes ( content ) { let bytes ; if ( ContentType . isLocationContent ( content ) ) { bytes = this . getLocationBytes ( content ) ; } else if ( ContentType . isTextContent ( content ) ) { bytes = this . getTextBytes ( content ) ; } else if ( ContentType . isAssetContent ( content ) ) { bytes = this . getAssetBytes ( content ) ; } else { throw new Error ( `Unknown message type. ${ content }` ) ; } const timestampBuffer = this . getTimestampBuffer ( this . timestamp ) ; return Buffer . concat ( [ bytes , timestampBuffer ] ) ; } getHash ( ) { const buffer = this . getBytes ( this . messageContent ) ; return this . createSha256Hash ( buffer ) ; } }