diff --git a/mumbledj/config.lua b/mumbledj/config.lua index 8c0dcb1..63b6dc1 100644 --- a/mumbledj/config.lua +++ b/mumbledj/config.lua @@ -37,6 +37,10 @@ config.USER_SOUND_PAUSE_TARGET = 1 -- DEFAULT VALUE: 0.25 config.VOLUME = 0.25 +-- Ratio that must be met or exceeded to trigger a song skip. +-- DEFAULT VALUE: 0.5 +config.SKIP_RATIO = 0.5 + ----------------------- -- ADMIN CONFIGURATION @@ -124,6 +128,18 @@ config.CHANNEL_DOES_NOT_EXIST_MSG = "The channel you specified does not exist." -- DEFAULT VALUE: "The URL you submitted does not match the required format. Please submit a valid YouTube URL." config.INVALID_URL_MSG = "The URL you submitted does not match the required format. Please submit a valid YouTube URL." +-- Message shown to users when they attempt to execute the play command when music is already playing. +-- DEFAULT VALUE: "A music track is already playing!" +config.MUSIC_PLAYING_MSG = "A music track is already playing!" + +-- Message shown to users when they attempt to use the stop command when no music is playing. +-- DEFAULT VALUE: "There is no music playing at the moment." +config.NO_MUSIC_PLAYING_MSG = "There is no music playing at the moment." + +-- Message shown to users when they attempt to use the play command when there are no songs in the queue. +-- DEFAULT VALUE: "There are no songs currently in the queue. Use " .. config.COMMAND_PREFIX .. "add to add a song to the queue." +config.NO_SONGS_AVAILABLE = "There are no songs currently in the queue. Use " .. config.COMMAND_PREFIX .. "add to add a song to the queue." + ---------------------- -- HTML CONFIGURATION @@ -149,4 +165,14 @@ config.SONG_ADDED_HTML = [[ %s has added "%s" to the queue. ]] +-- Message shown to channel when a song is resumed with the play command. +config.SONG_PLAY_HTML = [[ + %s resumed audio playback. +]] + +-- Message shown to channel when a song is paused by a user. +config.SONG_PAUSED_HTML = [[ + %s has paused the song. +]] + return config diff --git a/mumbledj/download_audio.py b/mumbledj/download_audio.py index 39f340b..ebdfd80 100644 --- a/mumbledj/download_audio.py +++ b/mumbledj/download_audio.py @@ -12,15 +12,22 @@ import pafy from sys import argv from os.path import isfile -from os import remove +from os import remove, system url = argv[1] video = pafy.new(url) +def encode_file(stream, downloaded, ratio, rate, eta): + if ratio == 1: + print('Encoding!') + system("ffmpeg -i song.ogg -ar 48000 -ac 1 song-converted.ogg -y") + try: - video.oggstreams[0].download(filepath = "song.ogg", quiet = True) + video.oggstreams[0].download(filepath = "song.ogg", quiet = True, callback = encode_file) if isfile(".video_fail"): remove(".video_fail") except: with open(".video_fail", "w+") as f: f.close() + + diff --git a/mumbledj/mumbledj.lua b/mumbledj/mumbledj.lua index 1fff2e5..e8cae4b 100644 --- a/mumbledj/mumbledj.lua +++ b/mumbledj/mumbledj.lua @@ -6,6 +6,8 @@ local config = require("config") local song_queue = require("song_queue") +local skippers = {} + function piepan.onConnect() print("MumbleDJ has connected to the server!") local user = piepan.users["MumbleDJ"] @@ -40,7 +42,16 @@ function parseCommand(message) if config.OUTPUT then print(message.user.name .. " has told the bot to start playing music.") end - piepan.me.channel:play("song.ogg") + if song_queue.getLength() == 0 then + message.user:send(config.NO_SONGS_AVAILABLE) + else + if piepan.Audio.isPlaying() then + message.user:send(config.MUSIC_PLAYING_MSG) + else + piepan.me.channel:play("song-converted.ogg", config.VOLUME, nextSong) + end + end + else message.user:send(config.NO_PERMISSION_MSG) end @@ -51,6 +62,13 @@ function parseCommand(message) if config.OUTPUT then print(message.user.name .. " has told the bot to pause music playback.") end + + if piepan.Audio.isPlaying() then + piepan.me.channel:send(string.format(config.SONG_PAUSED_HTML, message.user.name)) + piepan.Audio.stop() + else + message.user:send(config.NO_MUSIC_PLAYING_MSG) + end else message.user:send(config.NO_PERMISSION_MSG) end @@ -60,7 +78,8 @@ function parseCommand(message) if has_permission then if config.OUTPUT then print(message.user.name .. " has told the bot to add the following URL to the queue: " .. argument .. ".") - if not song_queue.addSong(argument) then + if not song_queue.addSong(argument, message.user.name) then + print(debug.traceback()) message.user:send(config.INVALID_URL_MSG) end end @@ -74,6 +93,8 @@ function parseCommand(message) if config.OUTPUT then print(message.user.name .. " has voted to skip the current song.") end + + skip(message.user.name) else message.user:send(config.NO_PERMISSION_MSG) end @@ -83,6 +104,9 @@ function parseCommand(message) if has_permission then if config.OUTPUT then print(message.user.name .. " has changed the volume to the following: " .. argument .. ".") + if 0.1 < argument < 2 then + config.VOLUME = argument + end end end elseif command == "move" then @@ -105,16 +129,47 @@ function parseCommand(message) if config.OUTPUT then print(message.user.name .. " has told the bot to kill itself.") end + kill() else message.user:send(config.NO_PERMISSION_MSG) end + elseif command == "test" then + piepan.me.channel:play("song-converted.ogg", config.VOLUME, nextSong) else message.user:send("The command you have entered is not valid.") end end -function skip() - return +function skip(username) + local user_count = 0 + local skipper_count = 0 + local already_skipped = false + for name,_ in pairs(piepan.users) do + user_count = user_count + 1 + end + + user_count = user_count - 1 -- So that we do not count the bot. + + for name,_ in pairs(skippers) do + if name == username then + already_skipped = true + end + skipper_count = skipper_count + 1 + end + + if not already_skipped then + table.insert(skippers, username) + skipper_count = skipper_count + 1 + local skip_ratio = skipper_count / user_count + if skip_ratio > config.SKIP_RATIO then + piepan.me.channel:send("The number of votes required for a skip has been met. Skipping song!") + nextSong() + else + piepan.me.channel:send("" .. username .. " has voted to skip this song.") + end + else + message.user:send("You have already voted to skip this song.") + end end function move(chan) @@ -129,7 +184,9 @@ function move(chan) end function kill() - return + os.remove("song.ogg") + os.remove("song-converted.ogg") + os.exit(0) end function checkPermissions(ADMIN_COMMAND, username) @@ -149,3 +206,12 @@ function isAdmin(username) return false end + +function nextSong() + skippers = {} +end + +function file_exists(file) + local f=io.open(file,"r") + if f~=nil then io.close(f) return true else return false end +end diff --git a/mumbledj/song_queue.lua b/mumbledj/song_queue.lua index 762690c..463d380 100644 --- a/mumbledj/song_queue.lua +++ b/mumbledj/song_queue.lua @@ -7,6 +7,7 @@ -- used for queueing up songs. -- ------------------------------------------------- local deque = require("deque") +local config = require("config") local song_queue = deque.new() @@ -25,12 +26,10 @@ function SongQueue.addSong(url, username) local video_id = string.match(url, pattern) if video_id ~= nil and string.len(video_id) < 20 then print("YouTube URL is valid!") - piepan.Thread.new(getYoutubeInfo, youtubeInfoCompleted, {video_id, username}) - return true + --piepan.Thread.new(getYoutubeInfo, youtubeInfoCompleted, {video_id, username}) + getYoutubeInfo(video_id, username) end end - - return false end function getYoutubeInfo(id, username) @@ -49,25 +48,30 @@ function getYoutubeInfo(id, username) return end - return { + print("Finished getting info.") + youtubeInfoCompleted({ id = id, title = name, duration = string.format("%d:%02d", duration / 60, duration % 60), thumbnail = thumbnail, username = username - } + }) end function youtubeInfoCompleted(info) if info == nil then - return + return false end - song_queue.push_left(info) + song_queue:push_right(info) if song_queue:length() == 1 then - os.execute("python download_audio.py") - piepan.me.channel:play("song.ogg") + os.execute("python download_audio.py " .. info.id) + while not file_exists("song-converted.ogg") do + os.execute("sleep " .. tonumber(2)) + end + print("we done here") + piepan.me.channel:play("song-converted.ogg", config.VOLUME, nextSong) end if piepan.Audio:isPlaying() then @@ -77,6 +81,8 @@ function youtubeInfoCompleted(info) local message = string.format(config.SONG_ADDED_HTML, info.username, info.title) piepan.me.channel:send(message) end + + return true end function SongQueue.getNextSong(url) @@ -87,4 +93,9 @@ function SongQueue.getLength() return song_queue:length() end +function file_exists(file) + local f=io.open(file,"r") + if f~=nil then io.close(f) return true else return false end +end + return SongQueue