|
| 1 | +/* eslint-disable */ |
| 2 | + |
| 3 | +type CVPair = { |
| 4 | + channelId: string; |
| 5 | + videoId: string; |
| 6 | +}; |
| 7 | +enum B64Type { |
| 8 | + B1 = "b1", |
| 9 | + B2 = "b2", |
| 10 | +} |
| 11 | + |
| 12 | +export function replayTimedContinuation( |
| 13 | + origin: CVPair, |
| 14 | + { top = false, seekMs = 0 }: { top?: boolean; seekMs?: number } = {} |
| 15 | +): string { |
| 16 | + const chatType = top ? 4 : 1; |
| 17 | + return b64e( |
| 18 | + ld(156074452, [ |
| 19 | + ld(3, hdt(origin)), |
| 20 | + vt(8, 1), |
| 21 | + ld(11, vt(2, seekMs)), |
| 22 | + ld(14, vt(1, chatType)), |
| 23 | + vt(15, 1), |
| 24 | + ]), |
| 25 | + B64Type.B1 |
| 26 | + ); |
| 27 | +} |
| 28 | + |
| 29 | +const _atob = globalThis.atob as ((data: string) => string) | undefined; |
| 30 | +const _btoa = globalThis.btoa as ((data: string) => string) | undefined; |
| 31 | +const b64tou8 = _atob |
| 32 | + ? (data: string) => Uint8Array.from(_atob(data), (c) => c.charCodeAt(0)) |
| 33 | + : (data: string) => { |
| 34 | + // @ts-ignore |
| 35 | + const buf = Buffer.from(data, "base64"); |
| 36 | + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); |
| 37 | + }; |
| 38 | + |
| 39 | +const u8tob64 = _btoa |
| 40 | + ? (data: Uint8Array) => _btoa(String.fromCharCode.apply(null, data as any)) |
| 41 | + : // @ts-ignore |
| 42 | + (data: Uint8Array) => Buffer.from(data).toString("base64"); |
| 43 | +function urlsafeB64e(payload: Uint8Array): string { |
| 44 | + return encodeURIComponent(u8tob64(payload)); |
| 45 | +} |
| 46 | + |
| 47 | +function urlsafeB64d(payload: string): Uint8Array { |
| 48 | + return b64tou8(decodeURIComponent(payload)); |
| 49 | +} |
| 50 | +function b64e(payload: Uint8Array, type: B64Type): string { |
| 51 | + switch (type) { |
| 52 | + case B64Type.B1: |
| 53 | + return urlsafeB64e(payload); |
| 54 | + case B64Type.B2: |
| 55 | + const urlsafe = urlsafeB64e(payload); |
| 56 | + const encoded = new TextEncoder().encode(urlsafe); |
| 57 | + return u8tob64(encoded); |
| 58 | + // return u8tob64(new TextEncoder().encode(urlsafeB64e(payload))); |
| 59 | + default: |
| 60 | + throw new Error(`Invalid b64type: ${type}`); |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +function ld( |
| 65 | + fid: bigint | number, |
| 66 | + payload: Uint8Array[] | Uint8Array | string |
| 67 | +): Uint8Array { |
| 68 | + const b = |
| 69 | + typeof payload === "string" |
| 70 | + ? new TextEncoder().encode(payload) |
| 71 | + : Array.isArray(payload) |
| 72 | + ? cc(payload) |
| 73 | + : payload; |
| 74 | + const bLen = b.byteLength; |
| 75 | + return cc([bitou8(pbh(fid, 2)), bitou8(encv(BigInt(bLen))), b]); |
| 76 | +} |
| 77 | + |
| 78 | +function vt(fid: bigint | number, payload: bigint | number): Uint8Array { |
| 79 | + return cc([bitou8(pbh(fid, 0)), bitou8(payload)]); |
| 80 | +} |
| 81 | + |
| 82 | +function pbh(fid: bigint | number, type: number): bigint { |
| 83 | + return encv((BigInt(fid) << 3n) | BigInt(type)); |
| 84 | +} |
| 85 | + |
| 86 | +function bitou8(n: bigint | number): Uint8Array { |
| 87 | + let hv = n.toString(16); |
| 88 | + hv = "".padStart(hv.length % 2, "0") + hv; |
| 89 | + return hextou8(hv); |
| 90 | +} |
| 91 | + |
| 92 | +function hextou8(data: string): Uint8Array { |
| 93 | + data = |
| 94 | + data.startsWith("0x") || data.startsWith("0X") ? data.substring(2) : data; |
| 95 | + const out = new Uint8Array(data.length / 2); |
| 96 | + for (let i = 0; i < out.length; ++i) { |
| 97 | + out[i] = parseInt(data.substr(i * 2, 2), 16); |
| 98 | + } |
| 99 | + return out; |
| 100 | +} |
| 101 | + |
| 102 | +const cc = concatu8; |
| 103 | + |
| 104 | +function concatu8(args: Uint8Array[]): Uint8Array { |
| 105 | + let totalLength = 0; |
| 106 | + for (let i = 0; i < args.length; ++i) { |
| 107 | + totalLength += args[i].length; |
| 108 | + } |
| 109 | + const out = new Uint8Array(totalLength); |
| 110 | + let offset = 0; |
| 111 | + for (let i = 0; i < args.length; ++i) { |
| 112 | + out.set(args[i], offset); |
| 113 | + offset += args[i].length; |
| 114 | + } |
| 115 | + return out; |
| 116 | +} |
| 117 | +function encv(n: bigint): bigint { |
| 118 | + let s = 0n; |
| 119 | + while (n >> 7n) { |
| 120 | + s = (s << 8n) | 0x80n | (n & 0x7fn); |
| 121 | + n >>= 7n; |
| 122 | + } |
| 123 | + s = (s << 8n) | n; |
| 124 | + return s; |
| 125 | +} |
| 126 | + |
| 127 | +function hdt(tgt: CVPair): string { |
| 128 | + return u8tob64( |
| 129 | + cc([ld(1, cvToken(tgt)), ld(3, ld(48687757, ld(1, tgt.videoId))), vt(4, 1)]) |
| 130 | + ); |
| 131 | +} |
| 132 | + |
| 133 | +function cvToken(p: CVPair) { |
| 134 | + return ld(5, [ld(1, p.channelId), ld(2, p.videoId)]); |
| 135 | +} |
0 commit comments