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