3 -- mod_admin_message -- Console-over-XMPP implementation.
5 -- This module depends on Prosody's admin_telnet module
7 -- Copyright (C) 2008-2010 Matthew Wild
8 -- Copyright (C) 2008-2010 Waqas Hussain
9 -- Copyright (C) 2012-2013 Mikael Berthe
11 -- This project is MIT/X11 licensed. Please see the
12 -- COPYING file in the source package for more information.
15 local st
= require
"util.stanza";
16 local um_is_admin
= require
"core.usermanager".is_admin
;
18 local admin_telnet
= module
:depends("admin_telnet");
19 local telnet_def_env
= module
:shared("/*/admin_telnet/env");
20 local telnet_commands
= module
:shared("/*/admin_telnet/commands");
21 local default_env_mt
= { __index
= telnet_def_env
};
23 local host
= module
.host
;
25 -- Create our own session. print() will store the results in a text
26 -- string. send(), quit(), disconnect() are no-op.
27 local function new_session ()
29 send
= function () end;
30 quit
= function () end;
31 disconnect
= function () end;
34 session
.print = function (...)
36 for i
=1,select("#", ...) do
37 t
[i
] = tostring(select(i
, ...));
39 local text
= "| "..table.concat(t
, "\t");
40 if session
.fulltext
then
41 session
.fulltext
= session
.fulltext
.. "\n" .. text
;
43 session
.fulltext
= text
;
47 session
.env
= setmetatable({}, default_env_mt
);
49 -- Load up environment with helper objects
50 for name
, t
in pairs(telnet_def_env
) do
51 if type(t
) == "table" then
52 session
.env
[name
] = setmetatable({ session
= session
},
60 local function on_message(event
)
61 -- Check the type of the incoming stanza to avoid loops:
62 if event
.stanza
.attr
.type == "error" then
63 return; -- We do not want to reply to these, so leave.
66 local userjid
= event
.stanza
.attr
.from
;
67 local bodytag
= event
.stanza
:get_child("body");
68 local body
= bodytag
and bodytag
:get_text() or "";
69 if not body
or body
== "" then
70 -- We do not reply to empty messages (chatstates, etc.)
74 -- Check the requester is an admin user
75 if not um_is_admin(userjid
, module
.host
) then
76 module
:log("info", "Ignored request from non-admin: %s",
81 -- Create a session in order to use an admin_telnet-like environment
82 local session
= new_session();
84 -- Process the message using admin_telnet's onincoming function
85 admin_telnet
.console
:process_line(session
, body
.."\n");
87 -- Strip trailing blank line
88 session
.fulltext
= tostring(session
.fulltext
):gsub("\n|%s*$", "")
90 -- Send the reply stanza
91 local reply_stanza
= st
.message({ from
= host
, to
= userjid
,
92 type = "chat" }, session
.fulltext
);
93 module
:send(reply_stanza
);
98 local function on_presence(event
)
100 local send_presence
= false;
102 local userjid
= event
.stanza
.attr
.from
;
104 -- Check the requester is an admin user
105 if not um_is_admin(userjid
, module
.host
) then
106 module
:log("info", "Ignored presence from non-admin: %s",
111 if (event
.stanza
.attr
.type == "subscribe") then
112 module
:log("info", "Subscription request from %s", userjid
);
113 send_presence
= true;
114 -- Send a subscription ack
115 local presence_stanza
= st
.presence({ from
= host
,
116 to
= userjid
, type = "subscribed",
117 id
= event
.stanza
.attr
.id
});
118 module
:send(presence_stanza
);
119 elseif (event
.stanza
.attr
.type == "probe") then
120 send_presence
= true;
121 elseif (event
.stanza
.attr
.type == "unsubscribe") then
122 -- For information only...
123 module
:log("info", "Unsubscription request from %s", userjid
);
126 if (send_presence
== true) then
127 -- Send a presence stanza
128 module
:send(st
.presence({ from
= host
, to
= userjid
}));
133 module
:hook("message/bare", on_message
);
134 module
:hook("presence/bare", on_presence
);