This commit is contained in:
commit
264cc17904
24
.drone.yml
Normal file
24
.drone.yml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: deploy
|
||||||
|
image: docker/compose
|
||||||
|
volumes:
|
||||||
|
- name: docksock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo $DISCORD_BOT_TOKEN
|
||||||
|
- docker-compose -p discbot up -d --force-recreate --build
|
||||||
|
when:
|
||||||
|
branch: [master]
|
||||||
|
environment:
|
||||||
|
DISCORD_BOT_TOKEN:
|
||||||
|
from_secret: discord_api
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: docksock
|
||||||
|
host:
|
||||||
|
path: /var/run/docker.sock
|
2
.gitingore
Normal file
2
.gitingore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
./node_modules/
|
||||||
|
./package-lock.json
|
34
Dockerfile
Normal file
34
Dockerfile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
FROM archlinux:latest
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV UNAME user
|
||||||
|
|
||||||
|
RUN useradd -u 1001 -m -d /home/user -s /bin/sh user && \
|
||||||
|
usermod -aG audio user
|
||||||
|
RUN echo "user ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||||
|
RUN echo "root ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
|
||||||
|
RUN pacman -Syud --noconfirm \
|
||||||
|
base-devel git \
|
||||||
|
nodejs npm \
|
||||||
|
pulseaudio \
|
||||||
|
mpv rtmpdump aria2
|
||||||
|
|
||||||
|
RUN mkdir /opt/ytdl && chown user:user /opt/ytdl
|
||||||
|
USER user
|
||||||
|
RUN git clone https://aur.archlinux.org/yt-dlp.git /opt/ytdl && \
|
||||||
|
cd /opt/ytdl && makepkg -sci --noconfirm && sudo ln -s /usr/bin/yt-dlp /usr/bin/youtube-dl
|
||||||
|
USER root
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN chmod +x run.sh
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CMD [ "./run.sh" ]
|
14
docker-compose.yml
Normal file
14
docker-compose.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
version: "3.7"
|
||||||
|
|
||||||
|
services:
|
||||||
|
discbot:
|
||||||
|
build: ./
|
||||||
|
container_name: discbot
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=false"
|
||||||
|
environment:
|
||||||
|
- DISCORD_BOT_TOKEN=$DISCORD_BOT_TOKEN
|
||||||
|
devices:
|
||||||
|
- /dev/dri/renderD128:/dev/dri/renderD128
|
||||||
|
- /dev/dri/card0:/dev/dri/card0
|
||||||
|
restart: always
|
139
main.js
Normal file
139
main.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
const mpv = require('node-mpv');
|
||||||
|
const prism = require('prism-media');
|
||||||
|
const { Client, Intents, VoiceChannel} = require('discord.js');
|
||||||
|
const { joinVoiceChannel,
|
||||||
|
createAudioPlayer,
|
||||||
|
createAudioResource,
|
||||||
|
entersState,
|
||||||
|
NoSubscriberBehavior,
|
||||||
|
StreamType,
|
||||||
|
AudioPlayerStatus,
|
||||||
|
VoiceConnectionStatus, } = require('@discordjs/voice');
|
||||||
|
const delay = ms => new Promise(res => setTimeout(res, ms));
|
||||||
|
|
||||||
|
global.client = new Client({
|
||||||
|
intents: [
|
||||||
|
Intents.FLAGS.GUILDS,
|
||||||
|
Intents.FLAGS.GUILD_MEMBERS,
|
||||||
|
Intents.FLAGS.GUILD_MESSAGES,
|
||||||
|
Intents.FLAGS.GUILD_VOICE_STATES
|
||||||
|
],
|
||||||
|
disableMentions: 'everyone',
|
||||||
|
});
|
||||||
|
|
||||||
|
client.music = {title:undefined, duration: undefined, pos:-1, count:0, report:false};
|
||||||
|
client.on("ready", () => {
|
||||||
|
console.log(`${client.user.username} ready!`);
|
||||||
|
client.user.setActivity(`H C L`, { type: 'WATCHING' });
|
||||||
|
});
|
||||||
|
client.on("warn", (info) => console.log(info));
|
||||||
|
client.on("error", console.error);
|
||||||
|
client.login(process.env.DISCORD_BOT_TOKEN);
|
||||||
|
client.exec={};
|
||||||
|
client.exec.format_url= function (url) { return url.includes("://") ? url : 'ytdl://ytsearch:"'+url+'"'};
|
||||||
|
|
||||||
|
const mpvPlayer = new mpv({audio_only:true, "verbose": false,},['--audio-device=pulse/MPVSink', '--ytdl-format=bestaudio']);//, '--demuxer-readahead-secs=2',' --demuxer-max-bytes=500M']);
|
||||||
|
var channel = null;
|
||||||
|
mpvPlayer.start().then(e=>console.log("MPV Started")).catch(e=>console.error(e));
|
||||||
|
mpvPlayer.on('status', (status) => {
|
||||||
|
console.log(status);
|
||||||
|
if(status.property=='media-title'){
|
||||||
|
if(client.music.duration)
|
||||||
|
client.music.title = status.value;
|
||||||
|
}
|
||||||
|
if(status.property=='duration'){
|
||||||
|
client.music.duration = status.value;
|
||||||
|
}
|
||||||
|
if(status.property=='playlist-count'){
|
||||||
|
client.music.count = status.value;
|
||||||
|
client.music.report = false;
|
||||||
|
}else if(status.property=='playlist-pos'){
|
||||||
|
client.music.pos = status.value;
|
||||||
|
client.music.report = false
|
||||||
|
|
||||||
|
}else if(client.music.title && client.music.duration){
|
||||||
|
client.channels.fetch(channel).then(c=>{
|
||||||
|
if(client.music.title && client.music.duration && client.music.report==false){
|
||||||
|
c.send('Playing: '+client.music.title+" ("+Math.floor(client.music.duration/60)+":"+Math.floor(client.music.duration%60)+")");
|
||||||
|
client.music.report = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mpvPlayer.on('stopped', (e) => {
|
||||||
|
console.log(e)
|
||||||
|
if(channel && client.music.pos == -1)
|
||||||
|
client.channels.fetch(channel).then(c=>c.send('Finished playing... Gime more music UwU'));
|
||||||
|
});
|
||||||
|
|
||||||
|
const player = createAudioPlayer({
|
||||||
|
behaviors: {
|
||||||
|
noSubscriber: NoSubscriberBehavior.Play,
|
||||||
|
maxMissedFrames: 250,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const resource = createAudioResource(new prism.FFmpeg({
|
||||||
|
args: ['-analyzeduration','0','-loglevel','0',
|
||||||
|
'-f', 'pulse','-i', 'MPVSink.monitor',
|
||||||
|
'-acodec','libopus','-f','opus',
|
||||||
|
'-ar','48000','-ac','2',
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
{inputType: StreamType.OggOpus});
|
||||||
|
player.play(resource);
|
||||||
|
|
||||||
|
|
||||||
|
client.exec.play = async(message, url)=>{
|
||||||
|
if(channel == null){
|
||||||
|
const vchannel = message.member.voice.channel;
|
||||||
|
if (!vchannel) return message.reply("You are not currently in a voice channel");
|
||||||
|
const permissions = vchannel.permissionsFor(message.client.user);
|
||||||
|
if (!permissions.has("CONNECT")) return message.reply("I am not allowed to join voice T_T");
|
||||||
|
if (!permissions.has("SPEAK")) return message.reply("I am not allowed to speak T_T");
|
||||||
|
|
||||||
|
const vc = joinVoiceChannel({
|
||||||
|
channelId: message.member.voice.channel.id,
|
||||||
|
guildId: message.guild.id,
|
||||||
|
adapterCreator: message.guild.voiceAdapterCreator
|
||||||
|
})
|
||||||
|
vc.subscribe(player);
|
||||||
|
channel = message.channelId;
|
||||||
|
}
|
||||||
|
mpvPlayer.load(client.exec.format_url(url),'replace').catch(e=>{});
|
||||||
|
|
||||||
|
return entersState(player, AudioPlayerStatus.Playing, 10e5);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.exec.stop = (message)=>{
|
||||||
|
mpvPlayer.stop().catch(e=>{});
|
||||||
|
message.guild.me.voice.disconnect("Ended Playback");
|
||||||
|
channel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.exec.queue = (message)=>{
|
||||||
|
let url = message.content.slice(6);
|
||||||
|
if(channel){
|
||||||
|
mpvPlayer.load(client.exec.format_url(url),'append-play').catch(e=>{});
|
||||||
|
}else{
|
||||||
|
client.exec.play(message,url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.exec.skip = (message)=>{
|
||||||
|
if(channel)
|
||||||
|
mpvPlayer.next().catch(e=>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
client.on("message", async (message) => {
|
||||||
|
if (message.author.bot) return;
|
||||||
|
if (!message.guild) return;
|
||||||
|
|
||||||
|
if (message.content.indexOf("stop")==0){
|
||||||
|
client.exec.stop(message);
|
||||||
|
}else if (message.content.indexOf("play")==0){
|
||||||
|
client.exec.play(message, message.content.slice(5));
|
||||||
|
}else if (message.content.indexOf("queue")==0){
|
||||||
|
client.exec.queue(message);
|
||||||
|
}else if (message.content.indexOf("skip")==0){
|
||||||
|
client.exec.skip(message);
|
||||||
|
}
|
||||||
|
});
|
19
package.json
Normal file
19
package.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "discbot",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/opus": "^0.5.3",
|
||||||
|
"@discordjs/voice": "^0.6.0",
|
||||||
|
"discord.js": "^13.2.0",
|
||||||
|
"libsodium-wrappers": "^0.7.9",
|
||||||
|
"node-mpv": "git://github.com/j-holub/Node-MPV.git",
|
||||||
|
"prism-media": "^1.3.2"
|
||||||
|
}
|
||||||
|
}
|
13
run.sh
Normal file
13
run.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
su user
|
||||||
|
|
||||||
|
if test -z "$DBUS_SESSION_BUS_ADDRESS" ; then
|
||||||
|
eval `dbus-launch --sh-syntax`
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
rm -rf /root/.config/pulse/
|
||||||
|
pulseaudio -D --exit-idle-time=-1 --disallow-exit
|
||||||
|
sleep 2
|
||||||
|
pacmd load-module module-null-sink sink_name=MPVSink
|
||||||
|
sleep 1
|
||||||
|
node main.js
|
Loading…
x
Reference in New Issue
Block a user