mirror of
https://github.com/warengroup/eximiabots-radiox.git
synced 2024-11-13 00:50:19 +00:00
commit
1d8ddc6084
@ -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
|
||||||
|
2
.github/workflows/typescript-build.yml
vendored
2
.github/workflows/typescript-build.yml
vendored
@ -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
|
||||||
|
@ -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
2427
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
32
package.json
32
package.json
@ -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",
|
||||||
|
@ -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),
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user