mtcute/packages/file-id/src/serialize.ts
Alina Tumanova f5976a2d74
ESM + end-to-end tests (#11)
* feat: moved tl-runtime to esm and native ArrayBuffers

* feat: migration to esm

* fix(core): web-related fixes

* test: finally, some good fucking e2e

* chore: fixed linters etc

* ci: added e2e to ci

* build(tl): fixed gen-code on node 20

* fix: codegen Uint8Array, not Buffer

never `git reset --hard` kids

* build: only do type-aware linting for `packages/*`

* build: ignore no-unresolved in ci for e2e

* fix: node 16 doesn't have subtle crypto apparently?

* fix(tests): use Uint8Array

for gods sake please can i just merge this already

* ci: don't parallel tasks in ci

because machines are utter garbage and it may just randomly break

* ci: pass secrets to e2e tests

* ci: separate cli command for ci

apparently im retarded

* fix: run codegen in e2e

im actually retarded

* ci: more fixes for e2e

* ci: debugging stuff

* ci: still debugging

* ci: hopefully fix ci???
2023-10-16 19:23:53 +03:00

108 lines
3.8 KiB
TypeScript

import { assertNever } from '@mtcute/core'
import { base64Encode, byteLengthUtf8, concatBuffers, TlBinaryWriter } from '@mtcute/core/utils.js'
import { tdFileId as td } from './types.js'
import { telegramRleEncode } from './utils.js'
const SUFFIX = new Uint8Array([td.CURRENT_VERSION, td.PERSISTENT_ID_VERSION])
/**
* Serialize an object with information about file
* to TDLib and Bot API compatible File ID
*
* @param location Information about file location
*/
export function toFileId(location: Omit<td.RawFullRemoteFileLocation, '_'>): string {
const loc = location.location
let type: number = location.type
if (loc._ === 'web') type |= td.WEB_LOCATION_FLAG
if (location.fileReference) type |= td.FILE_REFERENCE_FLAG
// overhead of the web file id:
// 8-16 bytes header,
// 8 bytes for access hash,
// up to 4 bytes for url
//
// longest file ids are around 80 bytes, so i guess
// we are safe with allocating 100 bytes
const writer = TlBinaryWriter.alloc(undefined, loc._ === 'web' ? byteLengthUtf8(loc.url) + 32 : 100)
writer.int(type)
writer.int(location.dcId)
if (location.fileReference) {
writer.bytes(location.fileReference)
}
switch (loc._) {
case 'web':
writer.string(loc.url)
writer.long(loc.accessHash)
break
case 'photo':
// todo: check how tdlib handles volume ids
writer.long(loc.id)
writer.long(loc.accessHash)
switch (loc.source._) {
case 'legacy':
writer.int(0)
writer.long(loc.source.secret)
break
case 'thumbnail':
writer.int(1)
writer.int(loc.source.fileType)
writer.int(loc.source.thumbnailType.charCodeAt(0))
break
case 'dialogPhoto':
writer.int(loc.source.big ? 3 : 2)
writer.int53(loc.source.id)
writer.long(loc.source.accessHash)
break
case 'stickerSetThumbnail':
writer.int(4)
writer.long(loc.source.id)
writer.long(loc.source.accessHash)
break
case 'fullLegacy':
writer.int(5)
writer.long(loc.source.volumeId)
writer.long(loc.source.secret)
writer.int(loc.source.localId)
break
case 'dialogPhotoLegacy':
writer.int(loc.source.big ? 7 : 6)
writer.int53(loc.source.id)
writer.long(loc.source.accessHash)
writer.long(loc.source.volumeId)
writer.int(loc.source.localId)
break
case 'stickerSetThumbnailLegacy':
writer.int(8)
writer.long(loc.source.id)
writer.long(loc.source.accessHash)
writer.long(loc.source.volumeId)
writer.int(loc.source.localId)
break
case 'stickerSetThumbnailVersion':
writer.int(9)
writer.long(loc.source.id)
writer.long(loc.source.accessHash)
writer.int(loc.source.version)
break
default:
assertNever(loc.source)
}
break
case 'common':
writer.long(loc.id)
writer.long(loc.accessHash)
break
default:
assertNever(loc)
}
return base64Encode(concatBuffers([telegramRleEncode(writer.result()), SUFFIX]), true)
}