Init
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
choelzl 2021-10-12 02:44:33 +02:00
commit 264cc17904
Signed by: sora
GPG Key ID: A362EA0491E2EEA0
7 changed files with 245 additions and 0 deletions

24
.drone.yml Normal file
View 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
View File

@ -0,0 +1,2 @@
./node_modules/
./package-lock.json

34
Dockerfile Normal file
View 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
View 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
View 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
View 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
View 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