6193cafd227ddf8ccbe7450a2337e95978c3c82d
[prosody.git] / plugins / adhoc / adhoc.lib.lua
1 local st, uuid = require "util.stanza", require "util.uuid";
2
3 local xmlns_cmd = "http://jabber.org/protocol/commands";
4
5 local states = {}
6
7 local _M = {};
8
9 function _cmdtag(desc, status, sessionid, action)
10         local cmd = st.stanza("command", { xmlns = xmlns_cmd, node = desc.node, status = status });
11         if sessionid then cmd.attr.sessionid = sessionid; end
12         if action then cmd.attr.action = action; end
13
14         return cmd;
15 end
16
17 function _M.new(name, node, handler, permission)
18         return { name = name, node = node, handler = handler, cmdtag = _cmdtag, permission = (permission or "user") };
19 end
20
21 function _M.handle_cmd(command, origin, stanza)
22         local sessionid = stanza.tags[1].attr.sessionid or uuid.generate();
23         local dataIn = {};
24         dataIn.to = stanza.attr.to;
25         dataIn.from = stanza.attr.from;
26         dataIn.action = stanza.tags[1].attr.action or "execute";
27         dataIn.form = stanza.tags[1]:child_with_ns("jabber:x:data");
28
29         local data, state = command:handler(dataIn, states[sessionid]);
30         states[sessionid] = state;
31         local stanza = st.reply(stanza);
32         if data.status == "completed" then
33                 states[sessionid] = nil;
34                 cmdtag = command:cmdtag("completed", sessionid);
35         elseif data.status == "canceled" then
36                 states[sessionid] = nil;
37                 cmdtag = command:cmdtag("canceled", sessionid);
38         elseif data.status == "error" then
39                 states[sessionid] = nil;
40                 stanza = st.error_reply(stanza, data.error.type, data.error.condition, data.error.message);
41                 cmdtag = command:cmdtag("canceled", sessionid);
42         else 
43                 cmdtag = command:cmdtag("executing", sessionid);
44         end
45
46         for name, content in pairs(data) do
47                 if name == "info" then
48                         cmdtag:tag("note", {type="info"}):text(content):up();
49                 elseif name == "warn" then
50                         cmdtag:tag("note", {type="warn"}):text(content):up();
51                 elseif name == "error" then
52                         cmdtag:tag("note", {type="error"}):text(content.message):up();
53                 elseif name =="actions" then
54                         local actions = st.stanza("actions");
55                         for _, action in ipairs(content) do
56                                 if (action == "prev") or (action == "next") or (action == "complete") then
57                                         actions:tag(action):up();
58                                 else
59                                         module:log("error", 'Command "'..command.name..
60                                                 '" at node "'..command.node..'" provided an invalid action "'..action..'"');
61                                 end
62                         end
63                         cmdtag:add_child(actions);
64                 elseif name == "form" then
65                         cmdtag:add_child(content:form());
66                 elseif name == "result" then
67                         cmdtag:add_child(content.layout:form(content.data, "result"));
68                 elseif name == "other" then
69                         cmdtag:add_child(content);
70                 end
71         end
72         stanza:add_child(cmdtag);
73         origin.send(stanza);
74
75         return true;
76 end
77
78 return _M;