dopath 'mpd'
tune_enabled = false
mpd_pub_song = { }
function mpd_getstatus ()
local status = mpd.call_command { 'status' }
if not tune_enabled or ( status.state ~= 'play' and status.state ~= 'pause' ) then
if mpd_pub_song.artist or mpd_pub_song.length or mpd_pub_song.source or mpd_pub_song.title or mpd_pub_song.track then
mpd_pub_song.artist = nil
mpd_pub_song.length = nil
mpd_pub_song.source = nil
mpd_pub_song.title = nil
mpd_pub_song.track = nil
return mpd_pub_song
else
return nil
end
end
local modified = false
local song = mpd.call_command { 'currentsong' }
local dir, file = song.file:match ( '(.+)/(.-)' )
-- populate according to currentsong fields: artist - artist, length - time, source - album, title - title, track - id, rating - ?, uri - ?
local artist, length, source, title, track = song.artist, song.time, song.album, song.title, song.id
if not artist or artist == '' then
artist = 'Unknown'
end
if not mpd_pub_song.artist or artist ~= mpd_pub_song.artist[1] then
mpd_pub_song.artist = { artist }
modified = true
end
if length and length ~= 0 then
if not mpd_pub_song.length or length ~= mpd_pub_song.length[1] then
mpd_pub_song.length = { length }
modified = true
end
elseif mpd_pub_song.length then -- no length
mpd_pub_song.length = nil
modified = true
end
if not source or source == '' then
source = dir
end
if not mpd_pub_song.source or source ~= mpd_pub_song.source[1] then
mpd_pub_song.source = { source }
modified = true
end
if not title or title == '' then
title = file
end
if not mpd_pub_song.title or title ~= mpd_pub_song.title[1] then
mpd_pub_song.title = { title }
modified = true
end
if not mpd_pub_song.track or track ~= mpd_pub_song.track[1] then
mpd_pub_song.track = { track }
modified = true
end
if modified then
return mpd_pub_song
else
return nil
end
end
function pep_publish ( node, data )
local conn = lm.connection.bless ( main.connection () )
data.xmlns = 'http://jabber.org/protocol/' .. node -- this may modify original data? imo it does not matter.
if conn:status () == 'authenticated' then
-- local bjid = conn:jid():gsub ( '/.*', '' )
conn:send (
lm.message.create { mtype = 'iq-set', -- from = conn:jid (), to = bjid,
pubsub = { xmlns = 'http://jabber.org/protocol/pubsub',
publish = { node = 'http://jabber.org/protocol/' .. node,
item = { -- id = "current",
[node] = data,
},
},
},
--[[
configure = {
x = {
field = {{ type = "hidden", var = 'FORM_TYPE',
value = { 'http://jabber.org/protocol/pubsub#node_config' },
},{ var = "pubsub#access_model",
value = { 'presence' },
}},
},
},
--]]
},
function ( conn, mess )
local mtype, smtype = mess:type ()
if smtype == 'result' then
return true
elseif smtype == 'error' then
print ( 'Error publishing to ' .. node .. ': ' .. mess:xml () ) -- FIXME
return true
else
print ( 'Weird ansver to publishing request: ' .. mess:xml () )
return false
end
end )
end
end
pep_incoming_message_handler = lm.message_handler.new (
function ( conn, mess )
local e = mess:child ( 'event' )
if e and e:attribute ( 'xmlns' ) == 'http://jabber.org/protocol/pubsub#event' then
local enable = main.yesno ( main.option ( 'lua_pep_notification' ) )
if enable == false then
return true
end
local is = e:child ( 'items' )
if is then
local from = mess:attribute ( 'from' )
local node = is:attribute ( 'node' )
if node == 'http://jabber.org/protocol/tune' then
local tune = is:path ( 'item', 'tune' )
if tune then
local item = tune:children ()
local text = ''
while item do
text = ("%s\n- %s: %s"):format ( text, item:name (), item:value () or '' )
item = item:next ()
end
if text ~= '' then
text = 'Now listening to:' .. text
else
text = 'Now not listening to anything'
end
main.print_info ( from, text )
return true
else
main.print_info ( from, 'Strange: no tune item in pep notification' )
end
elseif node == 'http://jabber.org/protocol/mood' then
local mood = is:path ( 'item', 'mood' )
if mood then
local item = mood:children ()
local mood, desc
while item do
if item:name () == 'text' then
desc = item:value ()
else
mood = item:name ()
-- here we can add child elements handling (by namespace)
end
item = item:next ()
end
if mood then
main.print_info ( from, ("Buddy's mood now %s %s"):format ( mood, desc or '' ) )
else
main.print_info ( from, "Buddy hides his mood" )
end
return true
else
main.print_info ( from, 'Strange: no mood item in pep notification' )
end
elseif node == 'http://jabber.org/protocol/activity' then
local activity = is:path ( 'item', 'activity' )
if activity then
local item = activity:children ()
local activity, desc
while item do
if item:name () == 'text' then
desc = item:value ()
else
activity = item:name ()
local subitem = item:children ()
if subitem then
-- here we can check for non-standard subactivity elements,
-- add subactivity child elements handling
activity = ("%s: %s"):format ( activity, subitem:name () )
end
end
item = item:next ()
end
if activity then
main.print_info ( from, ("Now %s %s"):format ( activity, desc or '' ) )
else
main.print_info ( from, "Buddy hides his activity" )
end
return true
else
main.print_info ( from, 'Strange: no activity item in pep notification' )
end
elseif node == 'http://jabber.org/protocol/geoloc' then
local loc = is:path ( 'item', 'geoloc' )
if loc then
local item = loc:children ()
local text = ''
while item do
text = ("%s\n- %s: %s"):format ( text, item:name (), item:value () or '' )
item = item:next ()
end
if text ~= '' then
text = 'Now at:' .. text
else
text = 'Now in unknown location'
end
main.print_info ( from, text )
return true
else
main.print_info ( from, 'Strange: no geoloc item in pep notification' )
end
else
main.print_info ( from, 'Unknown node in pep notification: ' .. is:xml () )
end
end
end
return false
end )
function mpd_callback ()
local sdata = mpd_getstatus ()
if sdata then
pep_publish ( 'tune', sdata )
end
if tune_enabled then
return true
else
return false
end
end
-- do not call it too fast, or you end up with many daemons at once
function enable_tune ( yn )
if yn == nil then
yn = true
end
if yn then
if not tune_enabled then
main.timer ( 15, mpd_callback )
tune_enabled = true
-- update status
end
else
if tune_enabled then
tune_enabled = false
-- update status
end
end
end
main.command ( 'tune',
function ( args )
local enable = main.yesno ( args )
if enable == nil then
if tune_enabled then
print ( "Tune notifications enabled" )
else
print ( "Tune notifications disabled" )
end
else
enable_tune ( enable )
end
end, false, 'yesno' )
main.command ( 'mood',
function ( args )
local data = { }
local mood, text = args[1], args[2]
if text then
data.text = { text }
end
if mood then
data[mood] = { }
end
pep_publish ( 'mood', data )
end, true )
main.command ( 'activity',
function ( args )
local data = { }
local activity, text = args[1], args[2]
if text then
data.text = { text }
end
local act, subact = activity:match ( "(.-)%-(.+)" )
if not act then
act = activity
end
if act ~= '' then
data[act] = { }
if subact then
data[act][subact] = { }
end
end
pep_publish ( 'activity', data )
end, true )
main.command ( 'location',
function ( args )
local data = { }
for key, val in pairs ( args ) do
data[key] = { val }
end
pep_publish ( 'geoloc', data )
end, true )
commands_help['tune'] = "[enable|disable|on|off|yes|no|true|false]\n\nEnables or disables publishing of notifications about playing music in your player (currently only mpd is supported)."
commands_help['mood'] = "[mood [message]]\n\nPublishes your mood.\nNote, that for now it does not checks for mood validity, so, see xep0107 for valid moods."
commands_help['activity'] = "[activity[-specific_activity] [text]]\n\nPublishes your activity.\nNote, that for now it does not checks for activity validity, so, see xep0108 for valid activity values."
commands_help['location'] = "[-key value [-key value ...]]\n\nPublishes your current geolocation.\nValid keys are accuracy, alt, area, bearing, building, country, datum, description, error, floor, lat, locality, lon, postalcode, region, room, speed, street, text, timestamp and uri, according to xep0080."
pep_handler_registered = false
hooks_d['hook-post-connect'].xep0163 =
function ( args )
lm.connection.bless( main.connection () ):handler ( pep_incoming_message_handler, 'message', 'normal' )
pep_handler_registered = true
if tune_enabled then
mpd_callback ()
end
-- XXX: may it confuse pairs()?
hooks_d['hook-post-connect'].xep0163 =
function ( args )
if tune_enabled then
mpd_callback ()
end
end
hooks_d['hook-quit'].xep0163 =
function ( args )
if mpd_handler_registered then
lm.connection.bless( main.connection () ):handler ( pep_incoming_message_handler, 'message' )
pep_handler_registered = false
end
end
end
-- XXX: this really should be initialized after connection establishment?
-- but as this thing is implemented by now, it will be cached by server,
-- and, thus, we will be unable to get notifications.
main.add_feature ( 'http://jabber.org/protocol/tune+notify' )
main.add_feature ( 'http://jabber.org/protocol/tune' )
main.add_feature ( 'http://jabber.org/protocol/mood+notify' )
main.add_feature ( 'http://jabber.org/protocol/mood' )
main.add_feature ( 'http://jabber.org/protocol/activity+notify' )
main.add_feature ( 'http://jabber.org/protocol/activity' )
main.add_feature ( 'http://jabber.org/protocol/geoloc+notify' )
main.add_feature ( 'http://jabber.org/protocol/geoloc' )
-- vim: se ts=4: --