Bumper commit for the new modulemanager API \o/ Updates all the modules, though some...
[prosody.git] / plugins / mod_console.lua
1 \r
2 local connlisteners_register = require "net.connlisteners".register;\r
3 \r
4 local console_listener = { default_port = 5582; default_mode = "*l"; };\r
5 \r
6 local commands = {};\r
7 local def_env = {};\r
8 local default_env_mt = { __index = def_env };\r
9 \r
10 console = {};\r
11 \r
12 function console:new_session(conn)\r
13         local w = conn.write;\r
14         local session = { conn = conn;\r
15                         send = function (t) w(tostring(t)); end;\r
16                         print = function (t) w("| "..tostring(t).."\n"); end;\r
17                         disconnect = function () conn.close(); end;\r
18                         };\r
19         session.env = setmetatable({}, default_env_mt);\r
20         \r
21         -- Load up environment with helper objects\r
22         for name, t in pairs(def_env) do\r
23                 if type(t) == "table" then\r
24                         session.env[name] = setmetatable({ session = session }, { __index = t });\r
25                 end\r
26         end\r
27         \r
28         return session;\r
29 end\r
30 \r
31 local sessions = {};\r
32 \r
33 function console_listener.listener(conn, data)\r
34         local session = sessions[conn];\r
35         \r
36         if not session then\r
37                 -- Handle new connection\r
38                 session = console:new_session(conn);\r
39                 sessions[conn] = session;\r
40                 session.print("Welcome to the lxmppd admin console!");\r
41         end\r
42         if data then\r
43                 -- Handle data\r
44                 \r
45                 if data:match("[!.]$") then\r
46                         local command = data:lower();\r
47                         command = data:match("^%w+") or data:match("%p");\r
48                         if commands[command] then\r
49                                 commands[command](session, data);\r
50                                 return;\r
51                         end\r
52                 end\r
53                 \r
54                 session.env._ = data;\r
55                 \r
56                 local chunk, err = loadstring("return "..data);\r
57                 if not chunk then\r
58                         chunk, err = loadstring(data);\r
59                         if not chunk then\r
60                                 err = err:gsub("^%[string .-%]:%d+: ", "");\r
61                                 err = err:gsub("^:%d+: ", "");\r
62                                 err = err:gsub("'<eof>'", "the end of the line");\r
63                                 session.print("Sorry, I couldn't understand that... "..err);\r
64                                 return;\r
65                         end\r
66                 end\r
67                 \r
68                 setfenv(chunk, session.env);\r
69                 local ranok, taskok, message = pcall(chunk);\r
70                 \r
71                 if not ranok then\r
72                         session.print("Fatal error while running command, it did not complete");\r
73                         session.print("Error: "..taskok);\r
74                         return;\r
75                 end\r
76                 \r
77                 if not message then\r
78                         session.print("Result: "..tostring(taskok));\r
79                         return;\r
80                 elseif (not taskok) and message then\r
81                         session.print("Command completed with a problem");\r
82                         session.print("Message: "..tostring(message));\r
83                         return;\r
84                 end\r
85                 \r
86                 session.print("OK: "..tostring(message));\r
87         end\r
88 end\r
89 \r
90 function console_listener.disconnect(conn, err)\r
91         \r
92 end\r
93 \r
94 connlisteners_register('console', console_listener);\r
95 \r
96 -- Console commands --\r
97 -- These are simple commands, not valid standalone in Lua\r
98 \r
99 function commands.bye(session)\r
100         session.print("See you! :)");\r
101         session.disconnect();\r
102 end\r
103 \r
104 commands["!"] = function (session, data)\r
105         if data:match("^!!") then\r
106                 session.print("!> "..session.env._);\r
107                 return console_listener.listener(session.conn, session.env._);\r
108         end\r
109         local old, new = data:match("^!(.-[^\\])!(.-)!$");\r
110         if old and new then\r
111                 local ok, res = pcall(string.gsub, session.env._, old, new);\r
112                 if not ok then\r
113                         session.print(res)\r
114                         return;\r
115                 end\r
116                 session.print("!> "..res);\r
117                 return console_listener.listener(session.conn, res);\r
118         end\r
119         session.print("Sorry, not sure what you want");\r
120 end\r
121 \r
122 -- Session environment --\r
123 -- Anything in def_env will be accessible within the session as a global variable\r
124 \r
125 def_env.server = {};\r
126 function def_env.server:reload()\r
127         dofile "main.lua"\r
128         return true, "Server reloaded";\r
129 end\r
130 \r
131 def_env.module = {};\r
132 function def_env.module:load(name)\r
133         local mm = require "modulemanager";\r
134         local ok, err = mm.load(name);\r
135         if not ok then\r
136                 return false, err or "Unknown error loading module";\r
137         end\r
138         return true, "Module loaded";\r
139 end\r
140 \r
141 def_env.config = {};\r
142 function def_env.config:load(filename, format)\r
143         local config_load = require "core.configmanager".load;\r
144         local ok, err = config_load(filename, format);\r
145         if not ok then\r
146                 return false, err or "Unknown error loading config";\r
147         end\r
148         return true, "Config loaded";\r
149 end\r
150 \r
151 function def_env.config:get(host, section, key)\r
152         local config_get = require "core.configmanager".get\r
153         return true, tostring(config_get(host, section, key));\r
154 end\r
155 \r
156 def_env.hosts = {};\r
157 function def_env.hosts:list()\r
158         for host, host_session in pairs(hosts) do\r
159                 self.session.print(host);\r
160         end\r
161         return true, "Done";\r
162 end\r
163 \r
164 function def_env.hosts:add(name)\r
165 end\r