Improve stream handling
This commit is contained in:
parent
08f6951ffc
commit
a745e28eb9
82
index.ts
82
index.ts
@ -11,6 +11,7 @@ import {
|
||||
} from 'discord.js';
|
||||
import { joinVoiceChannel, VoiceConnection, createAudioPlayer, createAudioResource, AudioPlayerStatus, PlayerSubscription, StreamType } from '@discordjs/voice';
|
||||
import * as Duration from 'tinyduration';
|
||||
import axios from 'axios';
|
||||
|
||||
// @ts-ignore - Regardless of what TS says, we cannot import yargs-parser as a default import
|
||||
import * as parser from 'yargs-parser';
|
||||
@ -59,6 +60,7 @@ const client = new Client({
|
||||
let ytdlp: YTDlpWrap;
|
||||
const player = createAudioPlayer();
|
||||
const yt = new YouTube(config.youtubeApiKey);
|
||||
const httpClient = axios.create();
|
||||
|
||||
/**
|
||||
* Bot state
|
||||
@ -69,7 +71,6 @@ let voiceConnection: VoiceConnection;
|
||||
let playerSubscription: PlayerSubscription;
|
||||
let volume = config.defaultVolume;
|
||||
let ffmpegProcess = null;
|
||||
let keepStreamActive = false;
|
||||
|
||||
function logError(message: string | Object)
|
||||
{
|
||||
@ -190,7 +191,6 @@ async function newVoiceConnection(destroy: boolean = false) : Promise<VoiceConne
|
||||
async function playNext(message: Message | null = null, words: string[] = [])
|
||||
{
|
||||
if (currentSong && currentSong.isStream) {
|
||||
keepStreamActive = false;
|
||||
killFfmpeg();
|
||||
player.pause();
|
||||
}
|
||||
@ -240,16 +240,9 @@ player.on('stateChange', (oldState, newState) => {
|
||||
});
|
||||
|
||||
player.on(AudioPlayerStatus.Idle, () => {
|
||||
if (!keepStreamActive) {
|
||||
killFfmpeg();
|
||||
log('Player idle, playing next song');
|
||||
playNext();
|
||||
return;
|
||||
}
|
||||
|
||||
log('Player idle, keeping stream active, triggering new stream');
|
||||
const { message, words, options } = currentSong.botMeta;
|
||||
stream(message, words, options);
|
||||
killFfmpeg();
|
||||
log('Player idle, playing next song');
|
||||
playNext();
|
||||
});
|
||||
|
||||
player.on('error', (error) => {
|
||||
@ -287,6 +280,26 @@ async function stream(message: Message, words: string[], options: Object | undef
|
||||
return false;
|
||||
}
|
||||
|
||||
const response = await httpClient.head(url);
|
||||
const headers = response.headers;
|
||||
const contentType = (headers['content-type'] || '').trim().toLowerCase();
|
||||
|
||||
console.log('Content type:', contentType);
|
||||
|
||||
if (contentType === 'audio/x-mpegurl') {
|
||||
const getRequest = await httpClient.get(url);
|
||||
const newUrl = getRequest.data.trim();
|
||||
options['_'] = [newUrl];
|
||||
|
||||
log('Calling stream() with new URL: ' + newUrl);
|
||||
return await stream(message, words, options);
|
||||
}
|
||||
|
||||
if (!contentType.includes('audio')) {
|
||||
channel.send(`Invalid content type: ${headers['content-type']}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
url = parsed.href;
|
||||
const songMeta = {
|
||||
title: parsed.hostname,
|
||||
@ -313,13 +326,6 @@ async function stream(message: Message, words: string[], options: Object | undef
|
||||
|
||||
ffmpegProcess.on('close', (code) => {
|
||||
console.log(`FFmpeg process closed with code ${code}`);
|
||||
if (code === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (keepStreamActive) {
|
||||
setTimeout(() => stream(message, words), 5000);
|
||||
}
|
||||
});
|
||||
|
||||
const audioResource = createAudioResource(ffmpegProcess.stdout, {
|
||||
@ -329,25 +335,20 @@ async function stream(message: Message, words: string[], options: Object | undef
|
||||
|
||||
audioResource.volume.setVolume(volume);
|
||||
|
||||
// Don't add the stream to the queue if it's an automatic trigger, as it's already in the queue
|
||||
if (!keepStreamActive) {
|
||||
songQueue.push({
|
||||
url: url,
|
||||
path: url,
|
||||
message: message,
|
||||
audioResource: audioResource,
|
||||
isStream: true,
|
||||
videoInfo: null,
|
||||
songMeta: songMeta,
|
||||
botMeta: {
|
||||
message,
|
||||
words,
|
||||
options,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
keepStreamActive = true;
|
||||
songQueue.push({
|
||||
url: url,
|
||||
path: url,
|
||||
message: message,
|
||||
audioResource: audioResource,
|
||||
isStream: true,
|
||||
videoInfo: null,
|
||||
songMeta: songMeta,
|
||||
botMeta: {
|
||||
message,
|
||||
words,
|
||||
options,
|
||||
}
|
||||
});
|
||||
|
||||
if (!currentSong) {
|
||||
log('Nothing currently playing, triggering playNext()');
|
||||
@ -801,6 +802,10 @@ client.on('messageCreate', async (message: Message) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result === 'noreact') {
|
||||
return;
|
||||
}
|
||||
|
||||
await addReaction(message, '✅');
|
||||
});
|
||||
|
||||
@ -851,6 +856,7 @@ async function shutdown()
|
||||
}
|
||||
|
||||
process.on('SIGINT', shutdown);
|
||||
process.on('SIGTERM', shutdown);
|
||||
|
||||
async function init()
|
||||
{
|
||||
|
100
package-lock.json
generated
100
package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@discordjs/opus": "^0.8.0",
|
||||
"@discordjs/voice": "^0.14.0",
|
||||
"axios": "^1.7.7",
|
||||
"bufferutil": "^4.0.8",
|
||||
"discord.js": "^14.16.3",
|
||||
"erlpack": "github:discord/erlpack",
|
||||
@ -368,6 +369,23 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.7.7",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
|
||||
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@ -490,6 +508,18 @@
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@ -551,6 +581,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
@ -698,6 +737,40 @@
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
@ -1137,6 +1210,27 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@ -1360,6 +1454,12 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
||||
|
@ -15,6 +15,7 @@
|
||||
"dependencies": {
|
||||
"@discordjs/opus": "^0.8.0",
|
||||
"@discordjs/voice": "^0.14.0",
|
||||
"axios": "^1.7.7",
|
||||
"bufferutil": "^4.0.8",
|
||||
"discord.js": "^14.16.3",
|
||||
"erlpack": "github:discord/erlpack",
|
||||
|
Loading…
Reference in New Issue
Block a user