Merge pull request #80 from warengroup/develop

Version 0.3.12
This commit is contained in:
Christer Warén 2021-11-30 00:21:57 +02:00 committed by GitHub
commit 1d8ddc6084
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1129 additions and 1513 deletions

View File

@ -1,5 +1,5 @@
DISCORD_TOKEN= DISCORD_TOKEN=
RADIOX_STATIONSLISTURL=https://gitea.cwinfo.org/cwchristerw/radio/raw/branch/master/playlist.json RADIOX_STATIONSLISTURL=https://git.cwinfo.net/cwchristerw/radio/raw/branch/master/playlist.json
DEV_MODE=false DEV_MODE=false
DEBUG_MODE=false DEBUG_MODE=false
STREAMER_MODE=manual STREAMER_MODE=manual

View File

@ -10,7 +10,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: install node v16 - name: install node v16
uses: actions/setup-node@v2.4.0 uses: actions/setup-node@v2.4.1
with: with:
node-version: 16 node-version: 16
- name: npm install - name: npm install

View File

@ -1,8 +1,8 @@
# RadioX by EximiaBots # RadioX by EximiaBots
Internet Radio to your Discord guild Internet Radio to your Discord guild
## [Radio Stations List](https://gitea.cwinfo.org/cwchristerw/radio) ## [Radio Stations List](https://git.cwinfo.net/cwchristerw/radio)
This bot is using Gitea repo to get radio stations from [playlist.json](https://gitea.cwinfo.org/cwchristerw/radio/raw/branch/master/playlist.json) file. List is currently maintained by Christer Warén. You can use alternative list with same format when using RADIOX_STATIONSLISTURL environment variable. This bot is using Gitea repo to get radio stations from [playlist.json](https://git.cwinfo.net/cwchristerw/radio/raw/branch/master/playlist.json) file. List is currently maintained by Christer Warén. You can use alternative list with same format when using RADIOX_STATIONSLISTURL environment variable.
## Docker ## Docker
1. `docker build -t warengroup/eximiabots-radiox . --pull` 1. `docker build -t warengroup/eximiabots-radiox . --pull`

2427
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "eximiabots-radiox", "name": "eximiabots-radiox",
"version": "0.3.11", "version": "0.3.12",
"description": "Internet Radio to your Discord guild", "description": "Internet Radio to your Discord guild",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@ -18,31 +18,31 @@
"url": "https://github.com/warengroup/eximiabots-radiox/issues" "url": "https://github.com/warengroup/eximiabots-radiox/issues"
}, },
"dependencies": { "dependencies": {
"@discordjs/builders": "^0.6.0", "@discordjs/builders": "^0.8.2",
"@discordjs/opus": "^0.6.0", "@discordjs/opus": "^0.7.0",
"@discordjs/rest": "^0.1.1-canary.0", "@discordjs/rest": "^0.1.1-canary.0",
"@discordjs/voice": "^0.6.0", "@discordjs/voice": "^0.7.5",
"discord-api-types": "^0.23.1", "discord-api-types": "^0.24.0",
"discord.js": "^13.1.0", "discord.js": "^13.2.0",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"libsodium-wrappers": "^0.7.9", "libsodium-wrappers": "^0.7.9",
"node-fetch": "^3.0.0", "node-fetch": "^3.1.0",
"path": "^0.12.7" "path": "^0.12.7"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^16.9.1", "@types/node": "^16.11.10",
"@types/ws": "^7.4.7", "@types/ws": "^8.2.0",
"@typescript-eslint/eslint-plugin": "^4.31.1", "@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^4.31.1", "@typescript-eslint/parser": "^5.4.0",
"eslint": "^7.32.0", "eslint": "^8.3.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"nodemon": "^2.0.12", "nodemon": "^2.0.15",
"prettier": "^2.4.1", "prettier": "^2.5.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"ts-node": "^10.2.1", "ts-node": "^10.4.0",
"tsc-watch": "^4.5.0", "tsc-watch": "^4.5.0",
"typescript": "^4.4.2" "typescript": "^4.5.2"
}, },
"engines": { "engines": {
"node": ">=16.9.1", "node": ">=16.9.1",

View File

@ -41,9 +41,11 @@ module.exports = class Radio extends Map {
if(voiceChannel.members.filter(member => !member.user.bot).size === 0) return; if(voiceChannel.members.filter(member => !member.user.bot).size === 0) return;
const sstation = await client.stations.search(state.station.name); const sstation = await client.stations.search(state.station.name, "direct");
let station = sstation; let station = sstation;
if(!station) return;
const construct = { const construct = {
textChannel: client.channels.cache.get(state.channels.text), textChannel: client.channels.cache.get(state.channels.text),
voiceChannel: client.channels.cache.get(state.channels.voice), voiceChannel: client.channels.cache.get(state.channels.voice),

View File

@ -17,7 +17,11 @@ module.exports = class Stations extends Array {
if(list){ if(list){
this.length = 0; this.length = 0;
list.forEach(station => { list.forEach(station => {
this.push(station); try {
this.push(station);
} catch (error) {
}
}); });
if(options.show){ if(options.show){
@ -27,6 +31,16 @@ module.exports = class Stations extends Array {
}); });
console.log("\n"); console.log("\n");
} }
list.forEach(async station => {
try {
let stationTest = await fetch(station.stream[station.stream.default]);
if(stationTest.ok === true) return;
this.splice(this.indexOf(station),1);
} catch (error) {
this.splice(this.indexOf(station),1);
}
});
} }
this.logger('Stations', 'Successfully fetched list'); this.logger('Stations', 'Successfully fetched list');
@ -34,7 +48,7 @@ module.exports = class Stations extends Array {
this.logger('Stations', 'Fetching list failed'); this.logger('Stations', 'Fetching list failed');
console.error(error + "\n"); console.error(error + "\n");
this.fetch(options); if(this.length == 0) this.fetch(options);
} }
} }
@ -46,66 +60,79 @@ module.exports = class Stations extends Array {
} }
} }
search(key) { search(key, type) {
if (this === null) return false; if (this === null) return false;
let foundStations = [];
if (!key) return false; if (!key) return false;
if (key == "radio") return false; if (!type) return false;
this if(type == "direct"){
.filter( let foundStation;
x => x.name.toUpperCase().includes(key.toUpperCase()) || x === key this.forEach(station => {
) if(station.name != key) return false;
.forEach(x => foundStation = station;
foundStations.push({ station: x, name: x.name, probability: 100 }) });
);
return foundStation;
} else {
let foundStations = [];
if (key == "radio") return false;
if (key.startsWith("radio ")) key = key.slice(6);
const probabilityIncrement = 100 / key.split(" ").length / 2;
for (let i = 0; i < key.split(" ").length; i++) {
this this
.filter( .filter(
x => x.name.toUpperCase().includes(key.split(" ")[i].toUpperCase()) || x === key x => x.name.toUpperCase().includes(key.toUpperCase()) || x === key
) )
.forEach(x => .forEach(x =>
foundStations.push({ station: x, name: x.name, probability: probabilityIncrement }) foundStations.push({ station: x, name: x.name, probability: 100 })
); );
}
if (foundStations.length === 0) return false;
for (let i = 0; i < foundStations.length; i++) {
for (let j = 0; j < foundStations.length; j++) {
if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1);
}
}
for (let i = 0; i < foundStations.length; i++) {
if (foundStations[i].name.length > key.length) {
foundStations[i].probability -=
(foundStations[i].name.split(" ").length - key.split(" ").length) *
(probabilityIncrement * 0.5);
} else if (foundStations[i].name.length === key.length) {
foundStations[i].probability += probabilityIncrement * 0.9;
}
for (let j = 0; j < key.split(" ").length; j++) { if (key.startsWith("radio ")) key = key.slice(6);
if (!foundStations[i].name.toUpperCase().includes(key.toUpperCase().split(" ")[j])) { const probabilityIncrement = 100 / key.split(" ").length / 2;
foundStations[i].probability -= probabilityIncrement * 0.5; for (let i = 0; i < key.split(" ").length; i++) {
this
.filter(
x => x.name.toUpperCase().includes(key.split(" ")[i].toUpperCase()) || x === key
)
.forEach(x =>
foundStations.push({ station: x, name: x.name, probability: probabilityIncrement })
);
}
if (foundStations.length === 0) return false;
for (let i = 0; i < foundStations.length; i++) {
for (let j = 0; j < foundStations.length; j++) {
if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1);
} }
} }
} for (let i = 0; i < foundStations.length; i++) {
let highestProbabilityStation; if (foundStations[i].name.length > key.length) {
for (let i = 0; i < foundStations.length; i++) { foundStations[i].probability -=
if ( (foundStations[i].name.split(" ").length - key.split(" ").length) *
!highestProbabilityStation || (probabilityIncrement * 0.5);
highestProbabilityStation.probability < foundStations[i].probability } else if (foundStations[i].name.length === key.length) {
) foundStations[i].probability += probabilityIncrement * 0.9;
highestProbabilityStation = foundStations[i]; }
if (
highestProbabilityStation && for (let j = 0; j < key.split(" ").length; j++) {
highestProbabilityStation.probability === foundStations[i].probability if (!foundStations[i].name.toUpperCase().includes(key.toUpperCase().split(" ")[j])) {
) { foundStations[i].probability -= probabilityIncrement * 0.5;
highestProbabilityStation = foundStations[i].station; }
}
} }
let highestProbabilityStation;
for (let i = 0; i < foundStations.length; i++) {
if (
!highestProbabilityStation ||
highestProbabilityStation.probability < foundStations[i].probability
)
highestProbabilityStation = foundStations[i];
if (
highestProbabilityStation &&
highestProbabilityStation.probability === foundStations[i].probability
) {
highestProbabilityStation = foundStations[i].station;
}
}
return highestProbabilityStation;
} }
return highestProbabilityStation;
} }
}; };

View File

@ -49,12 +49,22 @@ module.exports = class {
play(station) { play(station) {
let audioPlayer = this.map.get(station.name); let audioPlayer = this.map.get(station.name);
if(!audioPlayer) { if(!audioPlayer) {
audioPlayer = createAudioPlayer({ if(this.mode == "auto"){
behaviors: { audioPlayer = createAudioPlayer({
noSubscriber: NoSubscriberBehavior.Play, behaviors: {
maxMissedFrames: Math.round(5000 / 20), noSubscriber: NoSubscriberBehavior.Play,
}, maxMissedFrames: Math.round(5000 / 20),
}); },
});
}
if(this.mode == "manual"){
audioPlayer = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Stop,
maxMissedFrames: Math.round(5000 / 20),
},
});
}
this.map.set(station.name, audioPlayer); this.map.set(station.name, audioPlayer);
} }
const url = station.stream[station.stream.default]; const url = station.stream[station.stream.default];
@ -63,15 +73,12 @@ module.exports = class {
resource.playStream resource.playStream
.on("readable", () => { .on("readable", () => {
this.logger('Streamer', station.name + " / " + "Readable"); this.logger('Streamer', station.name + " / " + "Readable");
this.map.set(station.name, audioPlayer);
}) })
.on("finish", () => { .on("finish", () => {
this.logger('Streamer', station.name + " / " + "Finished"); this.logger('Streamer', station.name + " / " + "Finished");
this.play(station);
}) })
.on("error", error => { .on("error", error => {
this.logger('Streamer', station.name + " / " + "Error"); this.logger('Streamer', station.name + " / " + "Error" + "\n" + error);
this.play(station);
}); });
audioPlayer audioPlayer
@ -80,21 +87,20 @@ module.exports = class {
}) })
.on('idle', () => { .on('idle', () => {
this.logger('Streamer', station.name + " / " + "Idle"); this.logger('Streamer', station.name + " / " + "Idle");
audioPlayer.removeAllListeners();
this.play(station);
}) })
.on('paused', () => { .on('paused', () => {
this.logger('Streamer', station.name + " / " + "Paused"); this.logger('Streamer', station.name + " / " + "Paused");
this.play(station);
}) })
.on('buffering', () => { .on('buffering', () => {
this.logger('Streamer', station.name + " / " + "Buffering"); this.logger('Streamer', station.name + " / " + "Buffering");
}) })
.on('autopaused', () => { .on('autopaused', () => {
this.logger('Streamer', station.name + " / " + "AutoPaused"); this.logger('Streamer', station.name + " / " + "AutoPaused");
this.play(station);
}) })
.on('error', error => { .on('error', error => {
this.logger('Streamer', station.name + " / " + "Error" + "\n" + error); this.logger('Streamer', station.name + " / " + "Error" + "\n" + error);
this.play(station);
}); });
return audioPlayer; return audioPlayer;
} }
@ -103,6 +109,7 @@ module.exports = class {
let audioPlayer = this.map.get(station.name); let audioPlayer = this.map.get(station.name);
if(audioPlayer){ if(audioPlayer){
this.logger('Streamer', station.name + " / " + "Stop"); this.logger('Streamer', station.name + " / " + "Stop");
audioPlayer.removeAllListeners();
audioPlayer.stop(); audioPlayer.stop();
} }
this.map.delete(station.name); this.map.delete(station.name);

View File

@ -84,7 +84,16 @@ module.exports = {
content: client.messageEmojis["error"] + client.messages.tooShortSearch, content: client.messageEmojis["error"] + client.messages.tooShortSearch,
ephemeral: true ephemeral: true
}); });
const sstation = await client.stations.search(query, client);
let type = "";
if(interaction.values?.[0]){
type = "direct";
} else {
type = "text";
}
const sstation = await client.stations.search(query, type);
if (!sstation) return interaction.reply({ if (!sstation) return interaction.reply({
content: client.messageEmojis["error"] + client.messages.noSearchResults, content: client.messageEmojis["error"] + client.messages.noSearchResults,
ephemeral: true ephemeral: true

View File

@ -6,7 +6,7 @@ module.exports = {
token: process.env.DISCORD_TOKEN, token: process.env.DISCORD_TOKEN,
//radio stations //radio stations
stationslistUrl: process.env.RADIOX_STATIONSLISTURL || "https://gitea.cwinfo.org/cwchristerw/radio/raw/branch/master/playlist.json", stationslistUrl: process.env.RADIOX_STATIONSLISTURL || "https://git.cwinfo.net/cwchristerw/radio/raw/branch/master/playlist.json",
//support //support
supportGuild: "https://discord.gg/rRA65Mn", supportGuild: "https://discord.gg/rRA65Mn",