Add files via upload

This commit is contained in:
Murat
2023-11-29 18:23:54 +03:00
committed by GitHub
parent bdb4e9d949
commit 119d0275bd
79 changed files with 23303 additions and 0 deletions

40
node_modules/eris/lib/voice/streams/BaseTransformer.js generated vendored Normal file
View File

@ -0,0 +1,40 @@
"use strict";
const util = require("util");
const Base = require("../../structures/Base");
const TransformStream = require("stream").Transform;
class BaseTransformer extends TransformStream {
constructor(options = {}) {
if(options.allowHalfOpen === undefined) {
options.allowHalfOpen = true;
}
if(options.highWaterMark === undefined) {
options.highWaterMark = 0;
}
super(options);
this.manualCB = false;
}
setTransformCB(cb) {
if(this.manualCB) {
this.transformCB();
this._transformCB = cb;
} else {
cb();
}
}
transformCB() {
if(this._transformCB) {
this._transformCB();
this._transformCB = null;
}
}
[util.inspect.custom]() {
return Base.prototype[util.inspect.custom].call(this);
}
}
module.exports = BaseTransformer;

View File

@ -0,0 +1,78 @@
"use strict";
const BaseTransformer = require("./BaseTransformer");
class DCAOpusTransformer extends BaseTransformer {
constructor(options = {}) {
super(options);
this._remainder = null;
}
process(buffer) {
if(buffer.length - buffer._index < 2) {
return true;
}
const opusLen = buffer.readInt16LE(buffer._index);
buffer._index += 2;
if(buffer.length - buffer._index < opusLen) {
return true;
}
buffer._index += opusLen;
this.push(buffer.subarray(buffer._index - opusLen, buffer._index));
}
_transform(chunk, enc, cb) {
if(this._remainder) {
chunk = Buffer.concat([this._remainder, chunk]);
this._remainder = null;
}
if(!this.head) {
if(chunk.length < 4) {
this._remainder = chunk;
return cb();
} else {
const dcaVersion = chunk.subarray(0, 4);
if(dcaVersion[0] !== 68 || dcaVersion[1] !== 67 || dcaVersion[2] !== 65) { // DCA0 or invalid
this.head = true; // Attempt to play as if it were a DCA0 file
} else if(dcaVersion[3] === 49) { // DCA1
if(chunk.length < 8) {
this._remainder = chunk;
return cb();
}
const jsonLength = chunk.subarray(4, 8).readInt32LE(0);
if(chunk.length < 8 + jsonLength) {
this._remainder = chunk;
return cb();
}
const jsonMetadata = chunk.subarray(8, 8 + jsonLength);
this.emit("debug", jsonMetadata);
chunk = chunk.subarray(8 + jsonLength);
this.head = true;
} else {
this.emit("error", new Error("Unsupported DCA version: " + dcaVersion.toString()));
}
}
}
chunk._index = 0;
while(chunk._index < chunk.length) {
const offset = chunk._index;
const ret = this.process(chunk);
if(ret) {
this._remainder = chunk.subarray(offset);
cb();
return;
}
}
this.setTransformCB(cb);
}
}
module.exports = DCAOpusTransformer;

199
node_modules/eris/lib/voice/streams/FFmpegDuplex.js generated vendored Normal file
View File

@ -0,0 +1,199 @@
"use strict";
const util = require("util");
const Base = require("../../structures/Base");
const ChildProcess = require("child_process");
const DuplexStream = require("stream").Duplex;
const PassThroughStream = require("stream").PassThrough;
const delegateEvents = {
readable: "_reader",
data: "_reader",
end: "_reader",
drain: "_writer",
finish: "_writer"
};
class FFmpegDuplex extends DuplexStream {
constructor(command, options = {}) {
if(options.highWaterMark === undefined) {
options.highWaterMark = 0;
}
super(options);
this.command = command;
this._reader = new PassThroughStream(options);
this._writer = new PassThroughStream(options);
this._onError = this.emit.bind(this, "error");
this._reader.on("error", this._onError);
this._writer.on("error", this._onError);
this._readableState = this._reader._readableState;
this._writableState = this._writer._writableState;
["on", "once", "removeListener", "removeListeners", "listeners"].forEach((method) => {
const og = DuplexStream.prototype[method];
this[method] = function(ev, fn) {
const substream = delegateEvents[ev];
if(substream) {
return this[substream][method](ev, fn);
} else {
return og.call(this, ev, fn);
}
};
});
}
destroy() {
}
end(chunk, enc, cb) {
return this._writer.end(chunk, enc, cb);
}
kill() {
}
noop() {
}
pipe(dest, opts) {
return this._reader.pipe(dest, opts);
}
read(size) {
return this._reader.read(size);
}
setEncoding(enc) {
return this._reader.setEncoding(enc);
}
spawn(args, options = {}) {
let ex, exited, killed, ended;
let stderr = [];
const onStdoutEnd = () => {
if(exited && !ended) {
ended = true;
this._reader.end();
setImmediate(this.emit.bind(this, "close"));
}
};
const onStderrData = (chunk) => {
stderr.push(chunk);
};
const cleanup = () => {
this._process =
this._stderr =
this._stdout =
this._stdin =
stderr =
ex =
killed = null;
this.kill =
this.destroy = this.noop;
};
const onExit = (code, signal) => {
if(exited) {
return;
}
exited = true;
if(killed) {
if(ex) {
this.emit("error", ex);
}
this.emit("close");
} else if(code === 0 && signal == null) {
// All is well
onStdoutEnd();
} else {
// Everything else
ex = new Error("Command failed: " + Buffer.concat(stderr).toString("utf8"));
ex.killed = this._process.killed || killed;
ex.code = code;
ex.signal = signal;
this.emit("error", ex);
this.emit("close");
}
cleanup();
};
const onError = (err) => {
ex = err;
this._stdout.destroy();
this._stderr.destroy();
onExit();
};
const kill = () => {
if(killed) {
return;
}
this._stdout.destroy();
this._stderr.destroy();
killed = true;
try {
this._process.kill(options.killSignal || "SIGTERM");
setTimeout(() => this._process && this._process.kill("SIGKILL"), 2000);
} catch(e) {
ex = e;
onExit();
}
};
this._process = ChildProcess.spawn(this.command, args, options);
this._stdin = this._process.stdin;
this._stdout = this._process.stdout;
this._stderr = this._process.stderr;
this._writer.pipe(this._stdin);
this._stdout.pipe(this._reader, {
end: false
});
this.kill = this.destroy = kill;
this._stderr.on("data", onStderrData);
// In some cases ECONNRESET can be emitted by stdin because the process is not interested in any
// more data but the _writer is still piping. Forget about errors emitted on stdin and stdout
this._stdin.on("error", this.noop);
this._stdout.on("error", this.noop);
this._stdout.on("end", onStdoutEnd);
this._process.once("close", onExit);
this._process.once("error", onError);
return this;
}
unpipe(dest) {
return this._reader.unpipe(dest) || this.kill();
}
write(chunk, enc, cb) {
return this._writer.write(chunk, enc, cb);
}
[util.inspect.custom]() {
return Base.prototype[util.inspect.custom].call(this);
}
}
FFmpegDuplex.prototype.addListener = FFmpegDuplex.prototype.on;
FFmpegDuplex.spawn = function(connection, args, options) {
return new FFmpegDuplex(connection, options).spawn(args, options);
};
module.exports = FFmpegDuplex;

View File

@ -0,0 +1,35 @@
"use strict";
const FFmpegDuplex = require("./FFmpegDuplex");
module.exports = function(options = {}) {
if(!options.command) {
throw new Error("Invalid converter command");
}
if(options.frameDuration === undefined) {
options.frameDuration = 60;
}
let inputArgs = [
"-analyzeduration", "0",
"-loglevel", "24"
].concat(options.inputArgs || []);
if(options.format === "pcm") {
inputArgs = inputArgs.concat(
"-f", "s16le",
"-ar", "48000",
"-ac", "2"
);
}
inputArgs = inputArgs.concat(
"-i", options.input || "-",
"-vn"
);
const outputArgs = [
"-c:a", "libopus",
"-vbr", "on",
"-frame_duration", "" + options.frameDuration,
"-f", "ogg",
"-"
];
return FFmpegDuplex.spawn(options.command, inputArgs.concat(options.encoderArgs || [], outputArgs));
};

View File

@ -0,0 +1,26 @@
"use strict";
const FFmpegDuplex = require("./FFmpegDuplex");
module.exports = function(options = {}) {
if(!options.command) {
throw new Error("Invalid converter command");
}
if(options.samplingRate === undefined) {
options.samplingRate = 48000;
}
const inputArgs = [
"-analyzeduration", "0",
"-loglevel", "24"
].concat(options.inputArgs || [],
"-i", options.input || "-",
"-vn"
);
const outputArgs = [
"-f", "s16le",
"-ar", "" + options.samplingRate,
"-ac", "2",
"-"
];
return FFmpegDuplex.spawn(options.command, inputArgs.concat(options.encoderArgs || [], outputArgs));
};

View File

@ -0,0 +1,107 @@
"use strict";
const BaseTransformer = require("./BaseTransformer");
class OggOpusTransformer extends BaseTransformer {
constructor(options = {}) {
super(options);
this._remainder = null;
this._bitstream = null;
}
process(buffer) {
if(buffer.length - buffer._index <= 26) {
return true;
}
if(buffer.toString("utf8", buffer._index, buffer._index + 4) !== "OggS") {
return new Error("Invalid OGG magic string: " + buffer.toString("utf8", buffer._index, buffer._index + 4));
}
const typeFlag = buffer.readUInt8(buffer._index + 5);
if(typeFlag === 1) {
return new Error("OGG continued page not supported");
}
const bitstream = buffer.readUInt32BE(buffer._index + 14);
buffer._index += 26;
const segmentCount = buffer.readUInt8(buffer._index);
if(buffer.length - buffer._index - 1 < segmentCount) {
return true;
}
const segments = [];
let size = 0;
let byte = 0;
let total = 0;
let i = 0;
for(; i < segmentCount; i++) {
byte = buffer.readUInt8(++buffer._index);
if(byte < 255) {
segments.push(size + byte);
size = 0;
} else {
size += byte;
}
total += byte;
}
++buffer._index;
if(buffer.length - buffer._index < total) {
return true;
}
for(let segment of segments) {
buffer._index += segment;
byte = (segment = buffer.subarray(buffer._index - segment, buffer._index)).toString("utf8", 0, 8);
if(this.head) {
if(byte === "OpusTags") {
this.emit("debug", segment.toString());
} else if(bitstream === this._bitstream) {
this.push(segment);
}
} else if(byte === "OpusHead") {
this._bitstream = bitstream;
this.emit("debug", (this.head = segment.toString()));
} else {
this.emit("debug", "Invalid codec: " + byte);
}
}
}
_final() {
if(!this._bitstream) {
this.emit("error", new Error("No Opus stream was found"));
}
}
_transform(chunk, enc, cb) {
if(this._remainder) {
chunk = Buffer.concat([this._remainder, chunk]);
this._remainder = null;
}
chunk._index = 0;
while(chunk._index < chunk.length) {
const offset = chunk._index;
const ret = this.process(chunk);
if(ret) {
this._remainder = chunk.subarray(offset);
if(ret instanceof Error) {
this.emit("error", ret);
}
cb();
return;
}
}
this.setTransformCB(cb);
}
}
module.exports = OggOpusTransformer;

View File

@ -0,0 +1,61 @@
"use strict";
const BaseTransformer = require("./BaseTransformer");
class PCMOpusTransformer extends BaseTransformer {
constructor(options = {}) {
super(options);
this.opus = options.opusFactory();
this.frameSize = options.frameSize || 2880;
this.pcmSize = options.pcmSize || 11520;
this._remainder = null;
}
_destroy(...args) {
if(this.opus.delete) {
this.opus.delete();
}
return super._destroy(...args);
}
_flush(cb) {
if(this._remainder) {
const buf = Buffer.allocUnsafe(this.pcmSize);
this._remainder.copy(buf);
buf.fill(0, this._remainder.length);
this.push(this.opus.encode(buf, this.frameSize));
this._remainder = null;
}
cb();
}
_transform(chunk, enc, cb) {
if(this._remainder) {
chunk = Buffer.concat([this._remainder, chunk]);
this._remainder = null;
}
if(chunk.length < this.pcmSize) {
this._remainder = chunk;
return cb();
}
chunk._index = 0;
while(chunk._index + this.pcmSize < chunk.length) {
chunk._index += this.pcmSize;
this.push(this.opus.encode(chunk.subarray(chunk._index - this.pcmSize, chunk._index), this.frameSize));
}
if(chunk._index < chunk.length) {
this._remainder = chunk.subarray(chunk._index);
}
this.setTransformCB(cb);
}
}
module.exports = PCMOpusTransformer;

View File

@ -0,0 +1,50 @@
"use strict";
const BaseTransformer = require("./BaseTransformer");
class VolumeTransformer extends BaseTransformer {
constructor(options = {}) {
super(options);
this._remainder = null;
this.setVolume(1.0);
}
setVolume(volume) {
if(isNaN(volume) || (volume = +volume) < 0) {
throw new Error("Invalid volume level: " + volume);
}
this.volume = volume;
this.db = 10 * Math.log(1 + this.volume) / 6.931471805599453;
}
_transform(chunk, enc, cb) {
if(this._remainder) {
chunk = Buffer.concat([this._remainder, chunk]);
this._remainder = null;
}
if(chunk.length < 2) {
return cb();
}
let buf;
if(chunk.length & 1) {
this._remainder = chunk.subarray(chunk.length - 1);
buf = Buffer.allocUnsafe(chunk.length - 1);
} else {
buf = Buffer.allocUnsafe(chunk.length);
}
for(let i = 0, num; i < buf.length - 1; i += 2) {
// Bind transformed chunk to to 16 bit
num = ~~(this.db * chunk.readInt16LE(i));
buf.writeInt16LE(num >= 32767 ? 32767 : num <= -32767 ? -32767 : num, i);
}
this.push(buf);
this.setTransformCB(cb);
}
}
module.exports = VolumeTransformer;

View File

@ -0,0 +1,258 @@
"use strict";
const BaseTransformer = require("./BaseTransformer");
// EBML VInt max value is (2 ^ 56 - 2), but JS only supports 2^53
// 45 = 53 - 8 - check before last 8 bytes
const MAX_SHIFTED_VINT = Math.pow(2, 45);
const STATE_CONTENT = 0;
const STATE_TAG = 1;
const TAG_TYPE_END = 0;
const TAG_TYPE_START = 1;
const TAG_TYPE_TAG = 2;
const TRACKTYPE_AUDIO = 2; // EBML spec: https://www.matroska.org/technical/specs/index.html#TrackType
class WebmOpusTransformer extends BaseTransformer {
constructor(options = {}) {
super(options);
this._tag_stack = [];
this._state = STATE_TAG;
this._total = 0;
}
getVIntLength(buffer, index) {
let length = 1;
for(; length <= 8; ++length) {
if(buffer[index] & (1 << (8 - length))) {
break;
}
}
if(length > 8) {
this.emit("debug", new Error(`VInt length ${length} | ${buffer.toString("hex", index, index + length)}`));
return null;
}
if(index + length > buffer.length) {
return null;
}
return length;
}
process(type, info) {
if(type === TAG_TYPE_TAG) {
if(info.name === "SimpleBlock" && (info.data.readUInt8(0) & 0xF) === this.firstAudioTrack.TrackNumber) {
this.push(info.data.subarray(4));
return;
}
if(info.name === "CodecPrivate") {
const head = info.data.toString("utf8", 0, 8);
if(head !== "OpusHead") {
this.emit("error", new Error("Invalid codec: " + head));
return;
}
this.codecData = {
version: info.data.readUInt8(8),
channelCount: info.data.readUInt8(9),
preSkip: info.data.readUInt16LE(10),
inputSampleRate: info.data.readUInt32LE(12),
outputGain: info.data.readUInt16LE(16),
mappingFamily: info.data.readUInt8(18)
};
return;
}
}
if(!this.firstAudioTrack) {
if(info.name === "TrackEntry") {
if(type === TAG_TYPE_START) {
this.parsingTrack = {};
} else if(type === TAG_TYPE_END) {
if(this.parsingTrack.TrackNumber && this.parsingTrack.TrackType === TRACKTYPE_AUDIO) {
this.firstAudioTrack = this.parsingTrack;
}
delete this.parsingTrack;
}
return;
}
if(this.parsingTrack) {
if(info.name === "TrackNumber") {
this.parsingTrack.TrackNumber = info.data[0];
return;
}
if(info.name === "TrackType") {
this.parsingTrack.TrackType = info.data[0];
return;
}
}
if(type === TAG_TYPE_END && info.name === "Tracks") {
this.emit("error", new Error("No audio track"));
return;
}
return;
}
}
readContent(buffer) {
const tagObj = this._tag_stack[this._tag_stack.length - 1];
if(tagObj.type === "m") {
this.process(TAG_TYPE_START, tagObj);
this._state = STATE_TAG;
return true;
}
if(buffer.length < buffer._index + tagObj.size) {
return false;
}
tagObj.data = buffer.subarray(buffer._index, buffer._index + tagObj.size);
buffer._index += tagObj.size;
this._total += tagObj.size;
this._state = STATE_TAG;
this._tag_stack.pop();
this.process(TAG_TYPE_TAG, tagObj);
while(this._tag_stack.length > 0) {
if(this._total < this._tag_stack[this._tag_stack.length - 1].end) {
break;
}
this.process(TAG_TYPE_END, this._tag_stack.pop());
}
return true;
}
readTag(buffer) {
const tagSize = this.getVIntLength(buffer, buffer._index);
if(tagSize === null) {
return false;
}
const size = this.getVIntLength(buffer, buffer._index + tagSize);
if(size === null) {
return false;
}
const tagStr = buffer.toString("hex", buffer._index, buffer._index + tagSize);
const tagObj = {
type: "unknown",
name: "unknown",
end: this._total + tagSize
};
if(schema[tagStr]) {
tagObj.type = schema[tagStr].type;
tagObj.name = schema[tagStr].name;
}
buffer._index += tagSize;
let value = buffer[buffer._index] & (1 << (8 - size)) - 1;
for(let i = 1; i < size; ++i) {
if(i === 7 && value >= MAX_SHIFTED_VINT && buffer[buffer._index + 7] > 0) {
tagObj.end = -1; // Special livestreaming int 0x1FFFFFFFFFFFFFF
break;
}
value = (value << 8) + buffer[buffer._index + i];
}
if(tagObj.end !== -1) {
tagObj.end += value + size;
}
tagObj.size = value;
buffer._index += size;
this._total += tagSize + size;
this._state = STATE_CONTENT;
this._tag_stack.push(tagObj);
return true;
}
_transform(chunk, enc, cb) {
if(this._remainder) {
chunk = Buffer.concat([this._remainder, chunk]);
this._remainder = null;
}
chunk._index = 0;
while(chunk._index < chunk.length) {
if(this._state === STATE_TAG && !this.readTag(chunk)) {
break;
}
if(this._state === STATE_CONTENT && !this.readContent(chunk)) {
break;
}
}
if(chunk._index < chunk.length) {
this._remainder = chunk.subarray(chunk._index);
}
this.setTransformCB(cb);
}
}
module.exports = WebmOpusTransformer;
const schema = {
ae: {
name: "TrackEntry",
type: "m"
},
d7: {
name: "TrackNumber",
type: "u"
},
"86": {
name: "CodecID",
type: "s"
},
"83": {
name: "TrackType",
type: "u"
},
"1654ae6b": {
name: "Tracks",
type: "m"
},
"63a2": {
name: "CodecPrivate",
type: "b"
},
a3: {
name: "SimpleBlock",
type: "b"
},
"1a45dfa3": {
name: "EBML",
type: "m"
},
"18538067": {
name: "Segment",
type: "m"
},
"114d9b74": {
name: "SeekHead",
type: "m"
},
"1549a966": {
name: "Info",
type: "m"
},
e1: {
name: "Audio",
type: "m"
},
"1f43b675": {
name: "Cluster",
type: "m"
}
};