From 71e3e879c0616882ee82a0e44f8c2e5ee9698a3e Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 2 Dec 2022 14:47:21 +0100 Subject: Support reinjecting token in private m3u8 playlist --- server/helpers/stream-replacer.ts | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 server/helpers/stream-replacer.ts (limited to 'server/helpers/stream-replacer.ts') diff --git a/server/helpers/stream-replacer.ts b/server/helpers/stream-replacer.ts new file mode 100644 index 000000000..4babab418 --- /dev/null +++ b/server/helpers/stream-replacer.ts @@ -0,0 +1,58 @@ +import { Transform, TransformCallback } from 'stream' + +// Thanks: https://stackoverflow.com/a/45126242 +class StreamReplacer extends Transform { + private pendingChunk: Buffer + + constructor (private readonly replacer: (line: string) => string) { + super() + } + + _transform (chunk: Buffer, _encoding: BufferEncoding, done: TransformCallback) { + try { + this.pendingChunk = this.pendingChunk?.length + ? Buffer.concat([ this.pendingChunk, chunk ]) + : chunk + + let index: number + + // As long as we keep finding newlines, keep making slices of the buffer and push them to the + // readable side of the transform stream + while ((index = this.pendingChunk.indexOf('\n')) !== -1) { + // The `end` parameter is non-inclusive, so increase it to include the newline we found + const line = this.pendingChunk.slice(0, ++index) + + // `start` is inclusive, but we are already one char ahead of the newline -> all good + this.pendingChunk = this.pendingChunk.slice(index) + + // We have a single line here! Prepend the string we want + this.push(this.doReplace(line)) + } + + return done() + } catch (err) { + return done(err) + } + } + + _flush (done: TransformCallback) { + // If we have any remaining data in the cache, send it out + if (!this.pendingChunk?.length) return done() + + try { + return done(null, this.doReplace(this.pendingChunk)) + } catch (err) { + return done(err) + } + } + + private doReplace (buffer: Buffer) { + const line = this.replacer(buffer.toString('utf8')) + + return Buffer.from(line, 'utf8') + } +} + +export { + StreamReplacer +} -- cgit v1.2.3