-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbot.lua
More file actions
306 lines (237 loc) · 9.07 KB
/
Copy pathbot.lua
File metadata and controls
306 lines (237 loc) · 9.07 KB
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
---------------------------------------------------
--------------- BOT.lua ---------------------------
--- This file sets up the IRC bot and -------
--- the command system. -------
---------------------------------------------------
---------------------------------------------------
bot = {}
bot.Servers = {}
bot.Debug = false
--Get config
bot.Config = util.LoadConfig("config.txt")
--Get admins
bot.Admins = util.LoadConfig("admins.txt")
if not bot.Config then
print("[ERROR] Could not find config.txt!")
return
end
if not bot.Admins then
print("[WARNING] No admins.txt found, no admin commands will be avaivable.")
end
if bot.Debug then print("[DEBUG] Config table:") printtable(bot.Config) end
function ConnectAll()
for k,v in pairs(bot.Servers) do
v:Disconnect(bot.Config.Quitmsg or "Bye!")
end
print("Connecting to all servers..")
for k,srv in pairs(bot.Config.Servers) do
print("Trying server " .. srv ..":"..bot.Config.Port.." ("..bot.Config.Timeout.."s)...")
local new = IRC_NewClient(srv, bot.Config.Port, bot.Config.Timeout, bot.Debug)
new:SetNick(bot.Config.Nick)
new:SetUsername(bot.Config.Username)
new:SetRealname(bot.Config.Realname)
for k,room in pairs(bot.Config.Channels) do
new:JoinRoom(room)
end
local succ,err = new:Connect()
if succ then
print("Connection to " ..srv.." succeeded!")
table.insert(bot.Servers,new)
else
print("Failed connection attempt to " .. srv .. "!")
end
end
end
function bot.OnConnect(srv)
if bot.Config.JoinMsg then
for k,line in pairs(bot.Config.JoinMsg) do
srv:SendRaw(line)
end
end
end
hook.Add("OnConnect","bot_AutoMsgHook",bot.OnConnect)
function StartMainLoop()
ConnectAll()
while IRC_Think() do
hook.Call("Think")
end
print("No more active connections!")
end
---------------------------------------------------
-- Admin system - simplified
---------------------------------------------------
Admin = {}
function Admin.AddAdmin(nick,mask)
bot.Admins[nick] = mask
end
function Admin.IsAdmin(match)
for nick,mask in pairs(bot.Admins) do
local pattern = mask:gsub("[%^%$%(%)%%%.%[%]%+%-]", "%%%1"):gsub("%*", ".*"):gsub("%?", ".")
local f = match:find(pattern) --Allow wildcards
if f and f > -1 then return true end
end
return false
end
---------------------------------------------------
-- Commands system
---------------------------------------------------
CurTime = os.time
Command = {}
Command.ReplyPoll = {}
Command.LastSend = CurTime()
Command.SendInterval = tonumber(bot.Config.PollRate) or 0.5
Command.SilentMode = false
Command.Plugins = {}
Command.Commands = {}
function Command.Register(cmd, func, NumArgs, desc, AdminOnly)
if AdminOnly == nil then AdminOnly = true end
cmd = string.upper(cmd)
desc = desc or "None"
NumArgs = NumArgs or 0
local c = {}
c.Cmd = cmd
c.Func = func
c.Desc = desc
c.Admin = AdminOnly
c.NumArgs = NumArgs
Command.Commands[cmd] = c
end
function Command.Alias(alias, cmd)
Command.Commands[alias] = Command.Commands[cmd]
end
function Command.UnloadAll()
for cmd,tbl in pairs(Command.Commands) do
Commands[cmd] = nil
tbl = nil
end
Commands = {}
for k,tbl in pairs(Command.Plugins) do
if tbl.Unload then
tbl:Unload()
end
Command.Plugins[k] = nil
tbl = nil
end
print("Unloaded all plugins!")
end
function Command.LoadAll()
Command.UnloadAll()
for k,name in pairs(file.OpenDir(bot.Config.PluginDir)) do
if table.HasValue(bot.Config.PluginExtensions, file.GetExtension(name)) then
if Command.LoadPlugin(bot.Config.PluginDir.."/"..name) then
print("Loaded plugin " .. name)
end
end
end
print("Loaded all plugins in folder '"..bot.Config.PluginDir.."'!")
end
function Command.LoadPlugin(path)
local OldVar = PLUGIN
PLUGIN = {Name="NoName",Description="None"}
local WorkingPlugin = true
local func, err = loadfile(path)
if func then
local succ,err,_ = pcall(func)
if not succ then
print("Errored loading plugin " ..path..": "..err)
WorkingPlugin = false
end
else
print("Errored loading plugin " ..path..": "..err)
WorkingPlugin = false
end
PLUGIN.FilePath = path
table.insert(Command.Plugins,PLUGIN)
if PLUGIN.Load then
PLUGIN:Load()
end
PLUGIN = OldVar
return WorkingPlugin
end
function Command.Reply(msg,urgent)
local cmd = "PRIVMSG"
local target = Command.ReplyRoom
if Command.SilentMode then cmd = "NOTICE" target = Command.ReplyNick end
if urgent or Command.SendInterval <= 0 then
Command.ReplyServer:SendRaw(cmd.." "..target.." :"..msg)
else
table.insert(Command.ReplyPoll, cmd.." "..target.." :"..msg)
end
end
function Command.PollChat(target,msg)
if Command.SendInterval <= 0 then
Command.ReplyServer:SendRaw("PRIVMSG " .. target .. " :"..msg)
else
table.insert(Command.ReplyPoll, "PRIVMSG " .. target .. " :"..msg)
end
end
function Command.PollNotice(target,msg)
if Command.SendInterval <= 0 then
Command.ReplyServer:SendRaw("NOTICE " .. target .. " :"..msg)
else
table.insert(Command.ReplyPoll, "NOTICE " .. target .. " :"..msg)
end
end
function Command.SpamProtection()
if #Command.ReplyPoll == 0 then return end
if CurTime() - Command.LastSend > Command.SendInterval then
local k = table.GetFirst(Command.ReplyPoll)
Command.ReplyServer:SendRaw(Command.ReplyPoll[k])
table.remove(Command.ReplyPoll,k)
Command.LastSend = CurTime()
end
end
hook.Add("Think","bot_SpamProtection",Command.SpamProtection)
function Command.SetupReply(srv,nick,room)
Command.ReplyServer = srv
Command.ReplyNick = nick
Command.ReplyRoom = room
end
function Command.CommandHandler(srv, user, mask, room, nick, msg, IsPm)
local prefix = string.sub(msg,1,string.len(bot.Config.CmdPrefix))
if prefix ~= bot.Config.CmdPrefix then return end
if IsPm then
Command.SetupReply(srv,nick,nick)
else
Command.SetupReply(srv,nick,room)
end
local Split = string.Explode(msg," ")
if not Split[1] then return end
local cmd = string.upper(string.sub(Split[1],string.len(bot.Config.CmdPrefix) + 1))
Split[1] = ""
if not Command.Commands[cmd] then print("["..room.."] "..nick.." tried unknown command '" .. cmd.."'") return end
local CmdTbl = Command.Commands[cmd]
if CmdTbl.Admin and not Admin.IsAdmin(mask) then
print("["..room.."] " .. nick .. " was refused command " .. cmd..": Needs admin rights.")
return
end
local args = {}
local AllArgs = ""
if table.Count(Split) > 1 then
for k,v in pairs(Split) do
if string.Trim(v) ~= "" then
table.insert(args,string.Trim(v))
end
end
AllArgs = string.Implode(args," ")
end
if table.Count(args) < CmdTbl.NumArgs then
print("Not enough arguments!")
Command.Reply("Not enough arguments!")
print("["..room.."] " .. nick .. " was refused command " .. cmd..": Not enough arguments.")
return
end
local succ,err,retval = pcall(CmdTbl.Func,user,nick,mask,room,args,AllArgs,IsPm)
if not succ then
print("["..room.."] " .. nick .. " errored executing command " .. cmd..": "..err)
Command.Reply("ERROR in command '"..cmd.." "..AllArgs.."': " .. err)
else
print("["..room.."] " .. nick .. " executed command: '" .. cmd.." "..AllArgs.."'")
end
end
hook.Add("RecieveChat","bot_CommandHandler",Command.CommandHandler)
---------------------------------------------------
-- Hand control to the main loop
---------------------------------------------------
Command.LoadAll()
StartMainLoop()