-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcommands.lua
144 lines (123 loc) · 4.22 KB
/
commands.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
local cb = require "callbacks"
--[[
This module parses the PS protocol and provides a self-filling table containing
callbacks for PS commands. For some reason, I decided it would be a good idea
to have in this same file a basically unrelated model that allows masters to
define new commands (as Lua code!) for the bot on the go via chat.
]]
COMMANDS = {}
setmetatable(COMMANDS, {__index = function(self, name)
local c, e = cb(name)
if not c then
print("ERROR!", e, name)
end
self[name] = c
return self[name]
end})
-- Set COMMANDS' metatable so that it automatically creates a callback handler
-- and assigns it in case something tries to access/use one that does not
-- exist yet. Does nothing to prevent invalid actions from being registered.
local lengthen = {
c = "chat",
b = "battle",
j = "join",
l = "leave",
n = "name"
}
-- Just a table with aliases PS uses for common events.
local parse = function(msg)
-- This is the function that does a preliminary parsing of PS' messages.
local lines = {}
for line in msg:gmatch("[^\n]+") do
lines[#lines+1] = line
end
-- Split the whole message into different lines, so that each can be handled
-- separately.
local room = lines[1]:match("^>(.-)\n") or lines[1]:match("^>(.-)$") or "lobby"
-- Tries to figure out what room this message is for, defaulting to lobby if
-- unspecified.
if #lines > 10 then
return --I refuse to parse all the text that's in the room before joining
end
--if room then table.remove(lines, 1)
if lines[1]:sub(1,1) == ">" then
table.remove(lines, 1)
-- Remove the first line, if it's the room the block refers to.
end
for i = 1, #lines do
local line = lines[i]
local action, rest = line:match("^|(.-)|(.-)$")
-- Extract the "action" (type of PS message) and the rest of the stuff.
if not action then
--just display this? I will create an appropriate callback for this when
-- I know more.
else
action = lengthen[action:lower()] or action
-- action should always be the long version, for clarity.
COMMANDS[action]:fire(rest, room)
-- Fires the callbacks for the received type of message, passing the
-- "arguments" of the message as first argument, as received from PS,
-- and the room it happens in as second.
end
end
end
receive:register(parse, "COMMANDS")
-- Register the parse function as callback when anything's received.
commands = {}
--[[
As stated above, this module allows master to add/set and remove custom bot
commands as Lua code. It's completely unrelated to the functionality above.
]]
setmetatable(commands, {__index = function(self, name)
local c, e = cb(name)
if not c then
print("error!", e, name)
end
self[name] = c
return self[name]
end})
-- Set commands' metatable so that it automatically creates a callback handler
-- and assigns it in case something tries to access/use one that does not
-- exist yet. This is related to bot commands, not PS actions.
commands.cmd:register(function(nick, ...)
local args = {...}
local action = args[1]
table.remove(args, 1)
local actions = {}
if not isMaster(nick) then
return
end
actions.remove = function(nick, command)
if commands[command] then
commands[command] = nil
else
send("|/pm " .. nick .. ", The command ``" .. command .. "`` already doesn't exist.")
end
end
actions.add = function(nick, cmdname, ...)
if rawget(commands, cmdname) then
send("|/pm " .. nick .. ", The command ``" .. cmdname .. "`` already exists. Use ``addow``.")
else
return actions.addow(nick, cmdname, ...)
end
end
actions.addow = function(nick, cmdname, ...)
commands[cmdname] = nil
local command = table.concat({...}, " ")
local f, e = loadstring(command)
if not f then
send("|/pm " .. nick .. ", Error: " .. e)
return
end
commands[cmdname]:register(function(...)
local results = {pcall(f, ...)}
if not results[1] then
print("commands:", cmdname, "failed:", results[2])
return
end
table.remove(results, 1)
return unpack(results)
end, "commands-"..cmdname)
end
if actions[action] then actions[action](nick, unpack(args)) end
end, "commands")