parent
a984f43458
commit
3c4071b245
@ -0,0 +1 @@
|
||||
*~
|
||||
@ -1,2 +1,28 @@
|
||||
# MPD_Jabber_bot
|
||||
# MPD Jabber bot
|
||||
|
||||
Jabber/XMPP bot that controls streaming MPD instance.
|
||||
|
||||
This software is written in Ruby and allows you to control mpd server with simple commands written in MUC chat.
|
||||
|
||||
It can skip to prev/next song, play/pause/stop playback, control outputs, return info about current song and song which will be played next.
|
||||
|
||||
This software is still in alpha stage. It works for me so I can't promise updates in near future. Feel free to send me a patch if you want. I'll consider merging them.
|
||||
|
||||
TODO:
|
||||
|
||||
* Create persistent config file
|
||||
* Code cleanup
|
||||
* Possibly add some more features
|
||||
* Make it work in all versions of private messages
|
||||
|
||||
Do:
|
||||
|
||||
<botnick>: help
|
||||
|
||||
to get basic usage help.
|
||||
|
||||
This bot depends on following ruby modules:
|
||||
|
||||
* rubygems
|
||||
* jabbot
|
||||
* ruby-mpd
|
||||
@ -0,0 +1,294 @@
|
||||
#!/usr/bin/ruby
|
||||
$VERBOSE = nil
|
||||
$BOTVERSION = "beta 0.0.1"
|
||||
scriptname = "botik.rb" # When its changed, bot will switch to dev mode
|
||||
|
||||
botnick = "StreamCtl"
|
||||
|
||||
require 'rubygems'
|
||||
require 'jabbot'
|
||||
require 'ruby-mpd'
|
||||
|
||||
mpd = MPD.new 'localhost', 6600
|
||||
mpd.connect
|
||||
|
||||
class MPD
|
||||
def outputs
|
||||
send_command 'outputs'
|
||||
end
|
||||
|
||||
def pause
|
||||
send_command 'pause'
|
||||
end
|
||||
|
||||
def outputstatus(list)
|
||||
outputs = outputrefresh()
|
||||
if list.kind_of?(Array) then
|
||||
conout = Hash.new
|
||||
list.each {
|
||||
|out|
|
||||
conout[out.to_i] = outputs[out]
|
||||
}
|
||||
return conout
|
||||
else
|
||||
return outputs
|
||||
end
|
||||
end
|
||||
|
||||
def outputtoggle(out)
|
||||
out = out.to_i
|
||||
outputs = outputrefresh()
|
||||
if outputs[out].status == 0 then
|
||||
send_command "enableoutput #{out}"
|
||||
else
|
||||
send_command "disableoutput #{out}"
|
||||
end
|
||||
end
|
||||
|
||||
def outputrefresh
|
||||
outarray = send_command 'outputs'
|
||||
i = 0
|
||||
outputs = Hash.new
|
||||
Struct.new("Output", :name, :status)
|
||||
until(outarray.length < 1)
|
||||
line = outarray[0]
|
||||
outid = line[:outputid].to_i
|
||||
outname = line[:outputname]
|
||||
outstatus = (line[:outputenabled] ? 1 : 0) # Conversion to int
|
||||
outputs[outid] = Struct::Output.new(outname, outstatus)
|
||||
outarray.shift
|
||||
end
|
||||
return outputs
|
||||
end
|
||||
|
||||
def outputstatus(list)
|
||||
outputs = outputrefresh()
|
||||
if list.kind_of?(Array) then
|
||||
conout = Hash.new
|
||||
list.each {
|
||||
|out|
|
||||
conout[out.to_i] = outputs[out]
|
||||
}
|
||||
return conout
|
||||
else
|
||||
return outputs
|
||||
end
|
||||
end
|
||||
|
||||
def outputtoggle(out)
|
||||
out = out.to_i
|
||||
outputs = outputrefresh()
|
||||
if outputs[out].status == 0 then
|
||||
send_command "enableoutput #{out}"
|
||||
else
|
||||
send_command "disableoutput #{out}"
|
||||
end
|
||||
end
|
||||
def nextsong
|
||||
stat = send_command "status"
|
||||
nsid = stat[:nextsongid]
|
||||
return send_command "playlistid #{nsid}"
|
||||
end
|
||||
end
|
||||
|
||||
def mpdcontrol(mpd,request, mess, type)
|
||||
arr = mess.text.split(/\W+/)
|
||||
if arr[2].nil? == false then
|
||||
if arr[2].chomp.strip != "" then
|
||||
param = arr[2].chomp.strip
|
||||
end
|
||||
end
|
||||
|
||||
def outputsctl (outputs,sitelink)
|
||||
reply = ""
|
||||
def site_state_translate (input)
|
||||
if input == 0 then
|
||||
return "off"
|
||||
else
|
||||
return "on"
|
||||
end
|
||||
end
|
||||
outputs.each {
|
||||
|key,var|
|
||||
outfile = var[:name].split.last
|
||||
weblink = ""
|
||||
case outfile
|
||||
when "HQ"
|
||||
file = "hi.ogg"
|
||||
when "LQ"
|
||||
file = "lo.ogg"
|
||||
when "MP3"
|
||||
file = "stream.mp3"
|
||||
end
|
||||
reply = reply+"#{key} - #{sitelink}/#{file} - #{site_state_translate(var.status)}\n"
|
||||
}
|
||||
return reply
|
||||
end
|
||||
|
||||
status = mpd.status[:state].to_s.downcase
|
||||
case request
|
||||
when "status"
|
||||
if status == "stop" then
|
||||
sticon = "◼"
|
||||
else
|
||||
status == "play" ? sticon = "▶" : sticon = "▮▮"
|
||||
end
|
||||
song = mpd.current_song
|
||||
if song.name != nil then
|
||||
answer = "Stream: #{song.name} .:. #{song.title} @ #{song.file}"
|
||||
else
|
||||
answer = "#{song.artist} - #{song.title} [album #{song.album}]"
|
||||
end
|
||||
|
||||
song = mpd.current_song
|
||||
if song.name != nil then
|
||||
# do nothing
|
||||
else
|
||||
ns = mpd.nextsong
|
||||
answer = "#{answer}\nNext song in queue: #{ns[:artist]} - #{ns[:title]} [album #{ns[:album]}]"
|
||||
end
|
||||
if type == "0" then
|
||||
post "#{sticon} #{answer}"
|
||||
else
|
||||
post "#{sticon} #{answer}" => mess.user
|
||||
end
|
||||
when "play"
|
||||
mpd.play
|
||||
when "pause"
|
||||
mpd.pause
|
||||
when "stop"
|
||||
mpd.stop
|
||||
when "prev"
|
||||
mpd.previous
|
||||
when "next"
|
||||
mpd.next
|
||||
when "nextsong"
|
||||
song = mpd.current_song
|
||||
if song.name != nil then
|
||||
answer = "MPD is playing external stream. I can't get next song info."
|
||||
else
|
||||
ns = mpd.nextsong
|
||||
answer = "Next song in queue: #{ns[:artist]} - #{ns[:title]} [album #{ns[:album]}]"
|
||||
end
|
||||
if type == "0" then
|
||||
post answer
|
||||
else
|
||||
post answer => mess.user
|
||||
end
|
||||
|
||||
when "toggle"
|
||||
if param.nil? == false then
|
||||
if param.to_i >= 0 and param.to_i <= 2 then
|
||||
mpd.outputtoggle param.to_i
|
||||
end
|
||||
end
|
||||
when "info"
|
||||
if status == "stop" then
|
||||
sticon = "◼"
|
||||
else
|
||||
status == "play" ? sticon = "▶" : sticon = "▮▮"
|
||||
end
|
||||
song = mpd.current_song
|
||||
if song.name != nil then
|
||||
answer = "Stream: #{song.name} .:. #{song.title} @ #{song.file}"
|
||||
else
|
||||
answer = "#{song.artist} - #{song.title} [album #{song.album}]"
|
||||
end
|
||||
if song.name != nil then
|
||||
nsanswer = "MPD is playing external stream. I can't get next song info."
|
||||
else
|
||||
ns = mpd.nextsong
|
||||
nsanswer = "Next song in queue: #{ns[:artist]} - #{ns[:title]} [album #{ns[:album]}]"
|
||||
end
|
||||
sitelink = "https://stream.example.com"
|
||||
outputs = mpd.outputstatus([0, 1, 2])
|
||||
outs = outputsctl(outputs,sitelink)
|
||||
|
||||
if type == "0" then
|
||||
post "#{sticon} #{answer}\n#{nsanswer}\nOutputs:\n#{outs}"
|
||||
else
|
||||
post "#{sticon} #{answer}\n#{nsanswer}\nOutputs:\n#{outs}" => mess.user
|
||||
end
|
||||
when "outputs"
|
||||
sitelink = "https://stream.example.com"
|
||||
outputs = mpd.outputstatus([0, 1, 2])
|
||||
if type == "0" then
|
||||
post outputsctl(outputs,sitelink)
|
||||
else
|
||||
post outputsctl(outputs,sitelink) => mess.user
|
||||
end
|
||||
when "version"
|
||||
if type == "0" then
|
||||
post "Pitriss MPD stream control bot, version #{$BOTVERSION}"
|
||||
else
|
||||
post "Pitriss MPD stream control bot, version #{$BOTVERSION}" => mess.user
|
||||
end
|
||||
when "help"
|
||||
answer = "Stream is located at https://stream.example.com/xyz.ext (see outputs)\n
|
||||
Commands:\n
|
||||
status - Info about played track
|
||||
nestsong - Info about next song in queue
|
||||
info - Verbose info about most relevant aspects
|
||||
outputs - list all outputs available and its status
|
||||
toggle <output number> - toggle state of output
|
||||
play - start MPD
|
||||
pause - pause MPD
|
||||
stop - stops MPD
|
||||
next - next song
|
||||
prev - previous song\n\n
|
||||
For more info ask in room. (eg howto access playlist control)"
|
||||
if type == "0" then
|
||||
post answer
|
||||
else
|
||||
post answer => mess.user
|
||||
end
|
||||
else
|
||||
if type == "0" then
|
||||
post "Are you kiddin' me? That's complete bullshit! I don't believe single word you told me! Maybe you can try again with \"help\"?"
|
||||
else
|
||||
post "Are you kiddin' me? That's complete bullshit! I don't believe single word you told me! Maybe you can try again with \"help\"?" => mess.user
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
configure do |conf|
|
||||
conf.login = "bot@example.com"
|
||||
conf.password = "ChangeMe"
|
||||
# conf.nick = "StreamCtl"
|
||||
conf.nick = botnick
|
||||
conf.resource = "StreamCtl"
|
||||
if scriptname == File.basename($0) then
|
||||
conf.channel = "some-room"
|
||||
else
|
||||
conf.channel = "botdev"
|
||||
end
|
||||
conf.server = "conf.example.com"
|
||||
end
|
||||
|
||||
|
||||
message(/^#{botnick}[,|:| ].*$/i) do |message, params|
|
||||
arr = message.text.split(/\W+/)
|
||||
if arr[1].nil? == false then
|
||||
if arr[1].chomp.strip != "" then
|
||||
mpdcontrol(mpd,arr[1].chomp.strip,message,"0")
|
||||
else
|
||||
mpdcontrol(mpd,"status",message,"0")
|
||||
end
|
||||
else
|
||||
mpdcontrol(mpd,"status",message,"0")
|
||||
end
|
||||
end
|
||||
|
||||
query do |message, params|
|
||||
arr = message.text.split(/\W+/)
|
||||
if arr[0].nil? == false then
|
||||
if arr[0].chomp.strip != "" then
|
||||
mpdcontrol(mpd,arr[0].chomp.strip,message, "1")
|
||||
else
|
||||
mpdcontrol(mpd,"status",message,"1")
|
||||
end
|
||||
else
|
||||
mpdcontrol(mpd,"status",message,"1")
|
||||
end
|
||||
end
|
||||
Loading…
Reference in new issue