]> git.lizzy.rs Git - luairc.git/blob - test/luabot.lua
Port to Lua 5.3
[luairc.git] / test / luabot.lua
1 #!/usr/bin/env lua
2
3 local sig = require 'signal'
4 local irc = require 'irc'
5 irc.DEBUG = true
6
7 local nick = "luabot"
8 local channel = "#doytest"
9 local network = "irc.freenode.org"
10
11 local envs = {}
12
13 local function create_env()
14     return {
15         _VERSION =      _VERSION,
16         assert =         assert,
17         collectgarbage = collectgarbage,
18         error =          error,
19         getfenv =        getfenv,
20         getmetatable =   getmetatable,
21         ipairs =         ipairs,
22         loadstring =     loadstring,
23         next =           next,
24         pairs =          pairs,
25         pcall =          pcall,
26         rawequal =       rawequal,
27         rawget =         rawget,
28         rawset =         rawset,
29         select =         select,
30         setfenv =        setfenv,
31         setmetatable =   setmetatable,
32         tonumber =       tonumber,
33         tostring =       tostring,
34         type =           type,
35         unpack =         unpack,
36         xpcall =         xpcall,
37         coroutine =      coroutine,
38         math =           math,
39         string =         string,
40         table =          table,
41     }
42 end
43
44 local commands = {
45     eval = function(target, from, code)
46         code = code:gsub("^=", "return ")
47         local fn, err = loadstring(code)
48         if not fn then
49             irc.say(target, from .. ": Error loading code: " .. code .. err:match(".*(:.-)$"))
50             return
51         else
52             setfenv(fn, envs[from])
53             sig.signal("ALRM", error)
54             sig.alarm(5)
55             local result = {pcall(fn)}
56             sig.alarm(0)
57             sig.signal("ALRM", "default")
58             local success = table.remove(result, 1)
59             if not success then
60                 local err = result[1]:match(".*: (.-)$")
61                 if err == "ALRM" then err = "timed out" end
62                 irc.say(target, from .. ": Error running code: " .. code ..
63                                         ": " .. err)
64             else
65                 if result[1] == nil then
66                     irc.say(target, from .. ": nil")
67                 else
68                     for i, v in ipairs(result) do result[i] = tostring(v) end
69                     irc.say(target, from .. ": " .. table.concat(result, ", "))
70                 end
71             end
72         end
73     end,
74     clear = function(target, from)
75         irc.say(target, from .. ": Clearing your environment")
76         envs[from] = create_env()
77     end,
78     help = function(target, from, arg)
79         if arg == "" or not arg then
80             irc.say(target, from .. ": Commands: !clear, !eval, !help")
81         elseif arg == "eval" then
82             irc.say(target, from .. ": Evaluates a Lua statement in your own persistent environment")
83         elseif arg == "clear" then
84             irc.say(target, from .. ": Clears your personal environment")
85         end
86     end
87 }
88
89 irc.register_callback("connect", function()
90     irc.join(channel)
91 end)
92
93 irc.register_callback("channel_msg", function(channel, from, message)
94     message = message:gsub("^" .. nick .. "[:,>] ", "!eval ")
95     local is_cmd, cmd, arg = message:match("^(!)([%w_]+) ?(.-)$")
96     if is_cmd and commands[cmd] then
97         envs[from] = envs[from] or create_env()
98         commands[cmd](channel.name, from, arg)
99     end
100 end)
101
102 irc.register_callback("private_msg", function(from, message)
103     message = message:gsub("^" .. nick .. "[:,>] ", "!eval ")
104     local is_cmd, cmd, arg = message:match("^(!)([%w_]+) ?(.-)$")
105     envs[from] = envs[from] or create_env()
106     if is_cmd and commands[cmd] then
107         commands[cmd](from, from, arg)
108     else
109         commands["eval"](from, from, message)
110     end
111 end)
112
113 irc.register_callback("nick_change", function(from, old_nick)
114     if envs[old_nick] and not envs[from] then
115         envs[from] = envs[old_nick]
116         envs[old_nick] = nil
117     end
118 end)
119
120 irc.connect{network = network, nick = nick}