Compare commits
7 Commits
c75f53c474
...
a492d03ecc
Author | SHA1 | Date |
---|---|---|
Yessiest | a492d03ecc | |
Yessiest | af00e0c9d9 | |
Yessiest | 9d0829d652 | |
Yessiest | 72abab6e95 | |
Yessiest | 860134bccd | |
Yessiest | 08450e8a4b | |
Yessiest | 5542ac5ce5 |
|
@ -2,5 +2,8 @@
|
|||
/servers
|
||||
/discordia.log
|
||||
/gateway.json
|
||||
/luvit
|
||||
/lit
|
||||
/luvi
|
||||
*.so
|
||||
*.o
|
||||
|
|
36
bot.lua
36
bot.lua
|
@ -8,27 +8,33 @@ client = discordia.Client()
|
|||
--activate the import system
|
||||
local import = require("import")(require)
|
||||
|
||||
local server_ids = {
|
||||
"640251445949759499"
|
||||
}
|
||||
local servers = {}
|
||||
|
||||
--create server
|
||||
local server = import("classes.server-handler")
|
||||
client:on("ready",function()
|
||||
print("starting test")
|
||||
if not servers["640251445949759499"] then
|
||||
servers["640251445949759499"] = server(client,client:getGuild("640251445949759499"),{
|
||||
path = os.getenv("HOME").."/bot-savedata/640251445949759499/",
|
||||
autosave_frequency = 20,
|
||||
default_plugins = {
|
||||
"meta",
|
||||
"help",
|
||||
"plugins",
|
||||
"esolang",
|
||||
"tools",
|
||||
"reactions",
|
||||
"roledefaults",
|
||||
"security"
|
||||
}
|
||||
})
|
||||
for _,id in pairs(server_ids) do
|
||||
if not servers[id] then
|
||||
servers[id] = server(client,client:getGuild(id),{
|
||||
path = os.getenv("HOME").."/bot-savedata/"..id.."/",
|
||||
autosave_frequency = 20,
|
||||
default_plugins = {
|
||||
"meta",
|
||||
"help",
|
||||
"plugins",
|
||||
"esolang",
|
||||
"tools",
|
||||
"reactions",
|
||||
"roledefaults",
|
||||
"security",
|
||||
"cron"
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
@ -0,0 +1,405 @@
|
|||
-- Lua cron parser
|
||||
--[[
|
||||
Copyright © 2022 Yessiest
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
-- Adjustments for lua5.1
|
||||
if _VERSION=="Lua 5.1" then
|
||||
table.unpack = unpack
|
||||
end
|
||||
local cron = {
|
||||
directive_handler = nil
|
||||
}
|
||||
|
||||
local units = {
|
||||
m = 60,
|
||||
h = 60*60,
|
||||
d = 60*60*24,
|
||||
y = 60*60*24*356,
|
||||
w = 60*60*24*7
|
||||
}
|
||||
cron.convert_delay = function(str)
|
||||
local time = os.time()
|
||||
str:gsub("(%d+)([hmdyw])",function(n,unit)
|
||||
time = time+(units[unit]*tonumber(n))
|
||||
end)
|
||||
return time
|
||||
end
|
||||
|
||||
-- Utility functions
|
||||
local mdays = {31,28,31,30,31,30,31,31,30,31,30,31}
|
||||
cron._date = function(d,m,y)
|
||||
local current_date = os.date("*t")
|
||||
local y = ("2000"):sub(1,4-tostring(y):len())..tostring(y)
|
||||
d = tonumber(d or current_date.day)
|
||||
m = tonumber(m or current_date.month)
|
||||
y = tonumber(y or current_date.year)
|
||||
if ((y%4 == 0) and (y%100 ~= 0)) or ((y%100 == 0) and (y%400 == 0)) then
|
||||
mdays[2] = 29
|
||||
else
|
||||
mdays[2] = 28
|
||||
end
|
||||
return {
|
||||
assert((d > 0) and (d <= (mdays[m] or 31)) and d, "Invalid day: "..tostring(d)),
|
||||
assert(mdays[m] and m, "Invalid month: "..tostring(m)),
|
||||
y
|
||||
}
|
||||
end
|
||||
|
||||
cron._time = function(h,m)
|
||||
local current_date = os.date("*t")
|
||||
h = tonumber(h or current_date,hour)
|
||||
m = tonumber(m or current_date.min)
|
||||
return {
|
||||
assert((h >= 0) and (h < 24) and h, "Invalid hour: "..tostring(h)),
|
||||
assert((m >= 0) and (m < 60) and m, "Invalid min: "..tostring(m))
|
||||
}
|
||||
end
|
||||
|
||||
cron._compare_tables = function(d1,d2)
|
||||
for k,v in pairs(d1) do
|
||||
if d2[k] ~= v then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
-- Token types, in (regex, type, preprocessor) format
|
||||
local token_types = {
|
||||
{"^@(%w+)$", "directive", function(text)
|
||||
return text
|
||||
end},
|
||||
{"^(%d%d)%.(%d%d)%.(%d%d%d?%d?)$","date",function(d,m,y)
|
||||
return cron._date(d,m,y)
|
||||
end},
|
||||
{"^(%d%d):(%d%d)$","time",function(h,m)
|
||||
return cron._time(h,m)
|
||||
end},
|
||||
{"^(%d+,[%d,]+)$", "any_list",function(text)
|
||||
return function(num)
|
||||
local status = false
|
||||
text:gsub("%d*",function(number)
|
||||
if num == tonumber(number) then
|
||||
status = true
|
||||
end
|
||||
end)
|
||||
return status
|
||||
end
|
||||
end},
|
||||
{"^%*/(%d+)$", "any_modulo", function(text)
|
||||
return function(num)
|
||||
return (num % tonumber(text) == 0)
|
||||
end
|
||||
end},
|
||||
{"^%*$", "any", function()
|
||||
return function()
|
||||
return true
|
||||
end
|
||||
end},
|
||||
{"^%d+$", "number", function(text)
|
||||
return function(num)
|
||||
return num == tonumber(text)
|
||||
end
|
||||
end},
|
||||
{"^%s*$","spacer", function(text) return text end},
|
||||
{"^%S+$","command", function(text) return text end}
|
||||
}
|
||||
-- Valid argument matching predicates for directives
|
||||
local predtypes = {
|
||||
{"^([<>])(=?)(%d+)$","comparison",function(lm,eq,number)
|
||||
local number = tonumber(number)
|
||||
return function(input)
|
||||
local input = tonumber(input)
|
||||
if not input then return false end
|
||||
return ((eq == "=") and number == input) or
|
||||
((lm == ">") and number < input) or
|
||||
((lm == "<") and number > input)
|
||||
end
|
||||
end},
|
||||
{"^/([^/]*)/$","regex",function(regex)
|
||||
return function(input)
|
||||
return (tostring(input):match(regex) ~= nil)
|
||||
end
|
||||
end},
|
||||
{"^\"([^\"]*)\"$","string",function(str)
|
||||
return function(input)
|
||||
return str==tostring(input)
|
||||
end
|
||||
end},
|
||||
{"^'([^']*)'$","string",function(str)
|
||||
return function(input)
|
||||
return str==tostring(input)
|
||||
end
|
||||
end},
|
||||
{"^%d+$","number",function(number)
|
||||
return function(input)
|
||||
return number == tostring(input)
|
||||
end
|
||||
end},
|
||||
{"^%*$","any",function()
|
||||
return function()
|
||||
return true
|
||||
end
|
||||
end},
|
||||
{"^:$","delimiter",function()
|
||||
return function()
|
||||
error("Delimiter is not a predicate!")
|
||||
end
|
||||
end},
|
||||
{"^%s+$","spacer",function()
|
||||
return function()
|
||||
error("Spacer is not a predicate!")
|
||||
end
|
||||
end},
|
||||
{"^%S+$","command", function(text)
|
||||
return function()
|
||||
return text
|
||||
end
|
||||
end}
|
||||
}
|
||||
|
||||
-- Valid syntactic constructions
|
||||
local syntax = {
|
||||
{{"number","number","number","number","number"},"cronjob",
|
||||
function(min,hour,day,mo,dw,comm)
|
||||
return function(date)
|
||||
local status = min(date.min)
|
||||
status = status and hour(date.hour)
|
||||
status = status and day(date.day)
|
||||
status = status and mo(date.month)
|
||||
status = status and dw(wday)
|
||||
return status,comm
|
||||
end
|
||||
end},
|
||||
{{"date","time"},"onetime",function(date,time,comm)
|
||||
local time = os.time({day = date[1], month = date[2], year = date[3],
|
||||
hour = time[1], min = time[2]
|
||||
})
|
||||
return function(cdate)
|
||||
return os.time(cdate) >= time,comm
|
||||
end
|
||||
end},
|
||||
{{"time","date"},"onetime",function(time,date,comm)
|
||||
local time = os.time({day = date[1], month = date[2], year = date[3],
|
||||
hour = time[1], min = time[2]
|
||||
})
|
||||
return function(cdate)
|
||||
return os.time(cdate) >= time,comm
|
||||
end
|
||||
end}
|
||||
}
|
||||
|
||||
local find_strings = function(text)
|
||||
-- Find 2 string delimiters.
|
||||
-- Partition text into before and after if the string is empty
|
||||
-- Partition text into before, string and after if the string isn't empty
|
||||
local strings = {text}
|
||||
while strings[#strings]:match("[\"'/]") do
|
||||
local string = strings[#strings]
|
||||
-- Opening character for a string
|
||||
local open_pos = string:find("[\"'/]")
|
||||
local open_char = string:sub(open_pos,open_pos)
|
||||
if strings[#strings]:sub(open_pos+1,open_pos+1) == open_char then
|
||||
-- Empty string
|
||||
local text_before = string:sub(1,open_pos-1)
|
||||
local text_after = string:sub(open_pos+2,-1)
|
||||
strings[#strings] = text_before
|
||||
table.insert(strings,open_char..open_char)
|
||||
table.insert(strings,text_after)
|
||||
else
|
||||
-- Non-empty string
|
||||
local text_before = string:sub(1,open_pos-1)
|
||||
local _,closing_position = string:sub(open_pos,-1):find("[^\\]"..open_char)
|
||||
if not closing_position then
|
||||
break
|
||||
else
|
||||
closing_position = closing_position+open_pos-1
|
||||
end
|
||||
local text_string = string:sub(open_pos,closing_position)
|
||||
local text_after = string:sub(closing_position+1,-1)
|
||||
strings[#strings] = text_before
|
||||
table.insert(strings,text_string)
|
||||
table.insert(strings,text_after)
|
||||
end
|
||||
end
|
||||
for k,v in pairs(strings) do
|
||||
if v:len() == 0 then
|
||||
table.remove(strings,k)
|
||||
end
|
||||
end
|
||||
return strings
|
||||
-- P.S: This one is the best one i've written. Sure it looks clunky, but it
|
||||
-- does exactly what I expect it to do - handle cases when there are string
|
||||
-- delimiters inside other strings. Lovely. Also kinda horrifying.
|
||||
end
|
||||
|
||||
local startfrom = function(pos,t)
|
||||
local newtable = {}
|
||||
for i = pos,#t do
|
||||
newtable[i+1-pos] = t[i]
|
||||
end
|
||||
return newtable
|
||||
end
|
||||
|
||||
cron._split = function(text)
|
||||
-- Parse strings
|
||||
local tokens = {}
|
||||
text:gsub("(%S*)(%s*)",function(text,padding)
|
||||
table.insert(tokens,text)
|
||||
if padding:len() > 0 then
|
||||
table.insert(tokens,padding)
|
||||
end
|
||||
end)
|
||||
return tokens
|
||||
end
|
||||
|
||||
|
||||
cron._split_with_strings = function(text)
|
||||
-- Parse strings
|
||||
local nt = find_strings(text)
|
||||
local tokens = {}
|
||||
for k,v in pairs(nt) do
|
||||
if not ((v:sub(1,1) == v:sub(-1,-1)) and (v:match("^[\"'/]"))) then
|
||||
-- Parse space-separated tokens
|
||||
v:gsub("(%S*)(%s*)",function(text,padding)
|
||||
table.insert(tokens,text)
|
||||
if padding:len() > 0 then
|
||||
table.insert(tokens,padding)
|
||||
end
|
||||
end)
|
||||
else
|
||||
-- Insert pre-parsed strings into tokens
|
||||
table.insert(tokens,v)
|
||||
end
|
||||
end
|
||||
return tokens
|
||||
end
|
||||
|
||||
cron.parse_token = function(text)
|
||||
local token = {text}
|
||||
for _,pair in pairs(token_types) do
|
||||
if text:match(pair[1]) then
|
||||
token.type = pair[2]
|
||||
token[1] = pair[3](token[1]:match(pair[1]))
|
||||
return token
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cron.parse_directive = function(tokens)
|
||||
table.remove(tokens,1)
|
||||
-- Prepare predicate chain
|
||||
local argmatches = {}
|
||||
local stop = nil
|
||||
for k,v in pairs(tokens) do
|
||||
for _,pair in pairs(predtypes) do
|
||||
if v:match(pair[1]) then
|
||||
-- Stop at delimiter
|
||||
if pair[2] == "delimiter" then
|
||||
stop = k
|
||||
break
|
||||
end
|
||||
-- Ignore spacers - they're not predicates
|
||||
if pair[2] ~= "spacer" then
|
||||
table.insert(argmatches,pair[3](v:match(pair[1])))
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- We use a delimiter so that command start wouldn't be ambiguous
|
||||
-- Rather than defining an amount of arguments to directives, we
|
||||
-- simply allow the directive to match any amount of arguments all times
|
||||
if not stop then
|
||||
return false, "Directive arguments should end with a : delimiter"
|
||||
end
|
||||
local command = table.concat(startfrom(stop+2,tokens))
|
||||
-- Return the function that matches against a predicate chain
|
||||
return function(arguments)
|
||||
for k,v in pairs(argmatches) do
|
||||
if not v(arguments[k]) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true, command
|
||||
end,"directive"
|
||||
end
|
||||
|
||||
cron.parse_generic = function(tokens)
|
||||
-- Parse tokens
|
||||
local parsed_tokens = {}
|
||||
for k,v in pairs(tokens) do
|
||||
local status,token = pcall(cron.parse_token,v)
|
||||
if not status then
|
||||
return false,token
|
||||
end
|
||||
table.insert(parsed_tokens,token)
|
||||
end
|
||||
-- Match against a syntactic construction
|
||||
for k,v in pairs(syntax) do
|
||||
local matches = true
|
||||
local args = {}
|
||||
for pos,type in pairs(v[1]) do
|
||||
-- Remove trailing spacer tokens
|
||||
while parsed_tokens[pos] and parsed_tokens[pos].type == "spacer" do
|
||||
table.remove(parsed_tokens,pos)
|
||||
end
|
||||
if not parsed_tokens[pos] then
|
||||
break
|
||||
end
|
||||
-- Numbers are a special case because they can be matched
|
||||
-- by multiple predicates
|
||||
if type == "number" then
|
||||
if (parsed_tokens[pos].type ~= "number") and
|
||||
(not parsed_tokens[pos].type:match("^any")) then
|
||||
matches = false
|
||||
break
|
||||
end
|
||||
else
|
||||
if (parsed_tokens[pos].type ~= type) then
|
||||
matches = false
|
||||
break
|
||||
end
|
||||
end
|
||||
table.insert(args,parsed_tokens[pos][1])
|
||||
end
|
||||
if matches then
|
||||
-- Calculate cut position
|
||||
local cut_pos = #v[1]*2+1
|
||||
local command = table.concat(startfrom(cut_pos,tokens))
|
||||
args[#args+1] = command
|
||||
return v[3](table.unpack(args)),v[2]
|
||||
end
|
||||
end
|
||||
return false, "Syntax doesn't match any valid construction"
|
||||
end
|
||||
|
||||
cron.parse_line = function(line)
|
||||
local tokens = cron._split(line)
|
||||
local status,first_token = pcall(cron.parse_token,tokens[1])
|
||||
if not status then
|
||||
return false,first_token
|
||||
end
|
||||
if first_token.type == "directive" then
|
||||
|
||||
return cron.parse_directive(cron._split_with_strings(line))
|
||||
-- ...
|
||||
else
|
||||
return cron.parse_generic(tokens)
|
||||
-- ...
|
||||
end
|
||||
end
|
||||
|
||||
cron.parse = function(text)
|
||||
text:gsub("\n.-\n?$",function(line)
|
||||
cron.parse_line(line)
|
||||
end)
|
||||
end
|
||||
|
||||
return cron
|
|
@ -0,0 +1,21 @@
|
|||
cron = require("cron"); b,err = cron.parse_line("@directive /test/ >6 : s"); print(b,err); s,comm = b({"test",7}); print(s,comm)
|
||||
-- Testing basic functionality
|
||||
b,err = cron.parse_line("@directive /test/ >6 : s"); print(b,err); print(b({"test",5}));
|
||||
b,err = cron.parse_line("@directive \"test\" >6 : s"); print(b,err); print(b({"nottest",7}));
|
||||
b,err = cron.parse_line("*/2 14 */2 * * test"); print(b,err); print(b(os.date("*t")));
|
||||
b,err = cron.parse_line("08.05.22 15:30 test"); print(b,err); print(b(os.date("*t")));
|
||||
b,err = cron.parse_line("12:00 08.05.22 test"); print(b,err); print(b(os.date("*t")));
|
||||
-- Testing command forming
|
||||
b,err = cron.parse_line("08.05.22 15:30 test 2 the mega test"); print(b,err); print(b(os.date("*t")));
|
||||
b,err = cron.parse_line("12:00 08.05.22 test supreme"); print(b,err); print(b(os.date("*t")));
|
||||
b,err = cron.parse_line("*/2 14 */2 * * test of course yet another"); print(b,err); print(b(os.date("*t")));
|
||||
-- Testing parsing limits
|
||||
b,err = cron.parse_line("* * * test"); print(b,err);
|
||||
b,err = cron.parse_line("* * * * * * test"); print(b,err); --actually valid - and should be!
|
||||
b,err = cron.parse_line("@directive /test/ >6 no delimiter error"); print(b,err);
|
||||
b,err = cron.parse_line("08.05.22 shit"); print(b,err);
|
||||
b,err = cron.parse_line("10:20 shit"); print(b,err);
|
||||
-- Testing parsing dates and time
|
||||
b,err = cron.parse_line("51.02.2022 shit"); print(b,err);
|
||||
b,err = cron.parse_line("25:69 shit"); print(b,err);
|
||||
|
|
@ -0,0 +1,427 @@
|
|||
local md5 = {
|
||||
_VERSION = "md5.lua 1.1.0",
|
||||
_DESCRIPTION = "MD5 computation in Lua (5.1-3, LuaJIT)",
|
||||
_URL = "https://github.com/kikito/md5.lua",
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
-- bit lib implementions
|
||||
|
||||
local char, byte, format, rep, sub =
|
||||
string.char, string.byte, string.format, string.rep, string.sub
|
||||
local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift
|
||||
|
||||
local ok, bit = pcall(require, 'bit')
|
||||
local ok_ffi, ffi = pcall(require, 'ffi')
|
||||
if ok then
|
||||
bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift = bit.bor, bit.band, bit.bnot, bit.bxor, bit.rshift, bit.lshift
|
||||
else
|
||||
ok, bit = pcall(require, 'bit32')
|
||||
|
||||
if ok then
|
||||
|
||||
bit_not = bit.bnot
|
||||
|
||||
local tobit = function(n)
|
||||
return n <= 0x7fffffff and n or -(bit_not(n) + 1)
|
||||
end
|
||||
|
||||
local normalize = function(f)
|
||||
return function(a,b) return tobit(f(tobit(a), tobit(b))) end
|
||||
end
|
||||
|
||||
bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor)
|
||||
bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift)
|
||||
|
||||
else
|
||||
|
||||
local function tbl2number(tbl)
|
||||
local result = 0
|
||||
local power = 1
|
||||
for i = 1, #tbl do
|
||||
result = result + tbl[i] * power
|
||||
power = power * 2
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function expand(t1, t2)
|
||||
local big, small = t1, t2
|
||||
if(#big < #small) then
|
||||
big, small = small, big
|
||||
end
|
||||
-- expand small
|
||||
for i = #small + 1, #big do
|
||||
small[i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
local to_bits -- needs to be declared before bit_not
|
||||
|
||||
bit_not = function(n)
|
||||
local tbl = to_bits(n)
|
||||
local size = math.max(#tbl, 32)
|
||||
for i = 1, size do
|
||||
if(tbl[i] == 1) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
-- defined as local above
|
||||
to_bits = function (n)
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
return to_bits(bit_not(math.abs(n)) + 1)
|
||||
end
|
||||
-- to bits table
|
||||
local tbl = {}
|
||||
local cnt = 1
|
||||
local last
|
||||
while n > 0 do
|
||||
last = n % 2
|
||||
tbl[cnt] = last
|
||||
n = (n-last)/2
|
||||
cnt = cnt + 1
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
bit_or = function(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
for i = 1, #tbl_m do
|
||||
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
bit_and = function(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
for i = 1, #tbl_m do
|
||||
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
bit_xor = function(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
for i = 1, #tbl_m do
|
||||
if(tbl_m[i] ~= tbl_n[i]) then
|
||||
tbl[i] = 1
|
||||
else
|
||||
tbl[i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
bit_rshift = function(n, bits)
|
||||
local high_bit = 0
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(math.abs(n)) + 1
|
||||
high_bit = 0x80000000
|
||||
end
|
||||
|
||||
local floor = math.floor
|
||||
|
||||
for i=1, bits do
|
||||
n = n/2
|
||||
n = bit_or(floor(n), high_bit)
|
||||
end
|
||||
return floor(n)
|
||||
end
|
||||
|
||||
bit_lshift = function(n, bits)
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(math.abs(n)) + 1
|
||||
end
|
||||
|
||||
for i=1, bits do
|
||||
n = n*2
|
||||
end
|
||||
return bit_and(n, 0xFFFFFFFF)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- convert little-endian 32-bit int to a 4-char string
|
||||
local lei2str
|
||||
-- function is defined this way to allow full jit compilation (removing UCLO instruction in LuaJIT)
|
||||
if ok_ffi then
|
||||
local ct_IntType = ffi.typeof("int[1]")
|
||||
lei2str = function(i) return ffi.string(ct_IntType(i), 4) end
|
||||
else
|
||||
lei2str = function (i)
|
||||
local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
|
||||
return f(0)..f(8)..f(16)..f(24)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- convert raw string to big-endian int
|
||||
local function str2bei(s)
|
||||
local v=0
|
||||
for i=1, #s do
|
||||
v = v * 256 + byte(s, i)
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- convert raw string to little-endian int
|
||||
local str2lei
|
||||
|
||||
if ok_ffi then
|
||||
local ct_constcharptr = ffi.typeof("const char*")
|
||||
local ct_constintptr = ffi.typeof("const int*")
|
||||
str2lei = function(s)
|
||||
local int = ct_constcharptr(s)
|
||||
return ffi.cast(ct_constintptr, int)[0]
|
||||
end
|
||||
else
|
||||
str2lei = function(s)
|
||||
local v=0
|
||||
for i = #s,1,-1 do
|
||||
v = v*256 + byte(s, i)
|
||||
end
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- cut up a string in little-endian ints of given size
|
||||
local function cut_le_str(s)
|
||||
return {
|
||||
str2lei(sub(s, 1, 4)),
|
||||
str2lei(sub(s, 5, 8)),
|
||||
str2lei(sub(s, 9, 12)),
|
||||
str2lei(sub(s, 13, 16)),
|
||||
str2lei(sub(s, 17, 20)),
|
||||
str2lei(sub(s, 21, 24)),
|
||||
str2lei(sub(s, 25, 28)),
|
||||
str2lei(sub(s, 29, 32)),
|
||||
str2lei(sub(s, 33, 36)),
|
||||
str2lei(sub(s, 37, 40)),
|
||||
str2lei(sub(s, 41, 44)),
|
||||
str2lei(sub(s, 45, 48)),
|
||||
str2lei(sub(s, 49, 52)),
|
||||
str2lei(sub(s, 53, 56)),
|
||||
str2lei(sub(s, 57, 60)),
|
||||
str2lei(sub(s, 61, 64)),
|
||||
}
|
||||
end
|
||||
|
||||
-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
|
||||
-- 10/02/2001 jcw@equi4.com
|
||||
|
||||
local CONSTS = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
|
||||
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
|
||||
}
|
||||
|
||||
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
|
||||
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
|
||||
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
|
||||
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
|
||||
local z=function (ff,a,b,c,d,x,s,ac)
|
||||
a=bit_and(a+ff(b,c,d)+x+ac,0xFFFFFFFF)
|
||||
-- be *very* careful that left shift does not cause rounding!
|
||||
return bit_or(bit_lshift(bit_and(a,bit_rshift(0xFFFFFFFF,s)),s),bit_rshift(a,32-s))+b
|
||||
end
|
||||
|
||||
local function transform(A,B,C,D,X)
|
||||
local a,b,c,d=A,B,C,D
|
||||
local t=CONSTS
|
||||
|
||||
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
|
||||
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
|
||||
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
|
||||
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
|
||||
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
|
||||
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
|
||||
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
|
||||
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
|
||||
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
|
||||
d=z(f,d,a,b,c,X[ 9],12,t[10])
|
||||
c=z(f,c,d,a,b,X[10],17,t[11])
|
||||
b=z(f,b,c,d,a,X[11],22,t[12])
|
||||
a=z(f,a,b,c,d,X[12], 7,t[13])
|
||||
d=z(f,d,a,b,c,X[13],12,t[14])
|
||||
c=z(f,c,d,a,b,X[14],17,t[15])
|
||||
b=z(f,b,c,d,a,X[15],22,t[16])
|
||||
|
||||
a=z(g,a,b,c,d,X[ 1], 5,t[17])
|
||||
d=z(g,d,a,b,c,X[ 6], 9,t[18])
|
||||
c=z(g,c,d,a,b,X[11],14,t[19])
|
||||
b=z(g,b,c,d,a,X[ 0],20,t[20])
|
||||
a=z(g,a,b,c,d,X[ 5], 5,t[21])
|
||||
d=z(g,d,a,b,c,X[10], 9,t[22])
|
||||
c=z(g,c,d,a,b,X[15],14,t[23])
|
||||
b=z(g,b,c,d,a,X[ 4],20,t[24])
|
||||
a=z(g,a,b,c,d,X[ 9], 5,t[25])
|
||||
d=z(g,d,a,b,c,X[14], 9,t[26])
|
||||
c=z(g,c,d,a,b,X[ 3],14,t[27])
|
||||
b=z(g,b,c,d,a,X[ 8],20,t[28])
|
||||
a=z(g,a,b,c,d,X[13], 5,t[29])
|
||||
d=z(g,d,a,b,c,X[ 2], 9,t[30])
|
||||
c=z(g,c,d,a,b,X[ 7],14,t[31])
|
||||
b=z(g,b,c,d,a,X[12],20,t[32])
|
||||
|
||||
a=z(h,a,b,c,d,X[ 5], 4,t[33])
|
||||
d=z(h,d,a,b,c,X[ 8],11,t[34])
|
||||
c=z(h,c,d,a,b,X[11],16,t[35])
|
||||
b=z(h,b,c,d,a,X[14],23,t[36])
|
||||
a=z(h,a,b,c,d,X[ 1], 4,t[37])
|
||||
d=z(h,d,a,b,c,X[ 4],11,t[38])
|
||||
c=z(h,c,d,a,b,X[ 7],16,t[39])
|
||||
b=z(h,b,c,d,a,X[10],23,t[40])
|
||||
a=z(h,a,b,c,d,X[13], 4,t[41])
|
||||
d=z(h,d,a,b,c,X[ 0],11,t[42])
|
||||
c=z(h,c,d,a,b,X[ 3],16,t[43])
|
||||
b=z(h,b,c,d,a,X[ 6],23,t[44])
|
||||
a=z(h,a,b,c,d,X[ 9], 4,t[45])
|
||||
d=z(h,d,a,b,c,X[12],11,t[46])
|
||||
c=z(h,c,d,a,b,X[15],16,t[47])
|
||||
b=z(h,b,c,d,a,X[ 2],23,t[48])
|
||||
|
||||
a=z(i,a,b,c,d,X[ 0], 6,t[49])
|
||||
d=z(i,d,a,b,c,X[ 7],10,t[50])
|
||||
c=z(i,c,d,a,b,X[14],15,t[51])
|
||||
b=z(i,b,c,d,a,X[ 5],21,t[52])
|
||||
a=z(i,a,b,c,d,X[12], 6,t[53])
|
||||
d=z(i,d,a,b,c,X[ 3],10,t[54])
|
||||
c=z(i,c,d,a,b,X[10],15,t[55])
|
||||
b=z(i,b,c,d,a,X[ 1],21,t[56])
|
||||
a=z(i,a,b,c,d,X[ 8], 6,t[57])
|
||||
d=z(i,d,a,b,c,X[15],10,t[58])
|
||||
c=z(i,c,d,a,b,X[ 6],15,t[59])
|
||||
b=z(i,b,c,d,a,X[13],21,t[60])
|
||||
a=z(i,a,b,c,d,X[ 4], 6,t[61])
|
||||
d=z(i,d,a,b,c,X[11],10,t[62])
|
||||
c=z(i,c,d,a,b,X[ 2],15,t[63])
|
||||
b=z(i,b,c,d,a,X[ 9],21,t[64])
|
||||
|
||||
return bit_and(A+a,0xFFFFFFFF),bit_and(B+b,0xFFFFFFFF),
|
||||
bit_and(C+c,0xFFFFFFFF),bit_and(D+d,0xFFFFFFFF)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
local function md5_update(self, s)
|
||||
self.pos = self.pos + #s
|
||||
s = self.buf .. s
|
||||
for ii = 1, #s - 63, 64 do
|
||||
local X = cut_le_str(sub(s,ii,ii+63))
|
||||
assert(#X == 16)
|
||||
X[0] = table.remove(X,1) -- zero based!
|
||||
self.a,self.b,self.c,self.d = transform(self.a,self.b,self.c,self.d,X)
|
||||
end
|
||||
self.buf = sub(s, math.floor(#s/64)*64 + 1, #s)
|
||||
return self
|
||||
end
|
||||
|
||||
local function md5_finish(self)
|
||||
local msgLen = self.pos
|
||||
local padLen = 56 - msgLen % 64
|
||||
|
||||
if msgLen % 64 > 56 then padLen = padLen + 64 end
|
||||
|
||||
if padLen == 0 then padLen = 64 end
|
||||
|
||||
local s = char(128) .. rep(char(0),padLen-1) .. lei2str(bit_and(8*msgLen, 0xFFFFFFFF)) .. lei2str(math.floor(msgLen/0x20000000))
|
||||
md5_update(self, s)
|
||||
|
||||
assert(self.pos % 64 == 0)
|
||||
return lei2str(self.a) .. lei2str(self.b) .. lei2str(self.c) .. lei2str(self.d)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
function md5.new()
|
||||
return { a = CONSTS[65], b = CONSTS[66], c = CONSTS[67], d = CONSTS[68],
|
||||
pos = 0,
|
||||
buf = '',
|
||||
update = md5_update,
|
||||
finish = md5_finish }
|
||||
end
|
||||
|
||||
function md5.tohex(s)
|
||||
return format("%08x%08x%08x%08x", str2bei(sub(s, 1, 4)), str2bei(sub(s, 5, 8)), str2bei(sub(s, 9, 12)), str2bei(sub(s, 13, 16)))
|
||||
end
|
||||
|
||||
function md5.sum(s)
|
||||
return md5.new():update(s):finish()
|
||||
end
|
||||
|
||||
function md5.sumhexa(s)
|
||||
return md5.tohex(md5.sum(s))
|
||||
end
|
||||
|
||||
return md5
|
|
@ -1,38 +0,0 @@
|
|||
local class = import("classes.baseclass")
|
||||
local taskhandler = class("TaskHandler")
|
||||
local sqlite = import("sqlite3")
|
||||
-- DB format:
|
||||
--
|
||||
-- ID (INT) | event(STR) | args (STR) | date (STR) | command (STR)
|
||||
-- ---------|------------|------------|------------|--------------
|
||||
-- 1 | time | NULL |12 30 1 10 | ?echo today is yes day
|
||||
-- 2 | msg | hi |NULL | ?echo yes hello
|
||||
--
|
||||
local exists = function(tab,sv)
|
||||
for k,v in pairs(tab) do
|
||||
if v == sv then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
function taskhandler:__init(dbpath)
|
||||
self.db = sqlite.open(dbpath)
|
||||
local query = self.db:exec("SELECT * FROM sqlite_master;")
|
||||
if not exists(query.tbl_name,"tasks") then
|
||||
self.db:exec([[
|
||||
CREATE TABLE tasks(
|
||||
ID INTEGER PRIMARY KEY,
|
||||
event STR,
|
||||
args STR,
|
||||
date STR,
|
||||
command STR
|
||||
);
|
||||
]])
|
||||
end
|
||||
self.cache = {}
|
||||
end
|
||||
|
||||
function taskhandler:daily_cache()
|
||||
self.db:
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
local pluginc = import("classes.plugin")
|
||||
local command = import("classes.command")
|
||||
local plugin = pluginc("cron")
|
||||
local cron = import("cron")
|
||||
local fake_message = import("fake_message")
|
||||
local md5 = import("md5")
|
||||
local events = {
|
||||
timer = {},
|
||||
event = {}
|
||||
}
|
||||
|
||||
local exec = function(v,command)
|
||||
local channel = client:getChannel(v.channel)
|
||||
if not channel then
|
||||
log("ERROR","Unable to retrieve timer channel: "..tostring(v.channel))
|
||||
return
|
||||
end
|
||||
local msg = channel:getMessage(v.id)
|
||||
if not msg then
|
||||
log("ERROR","Unable to retrieve timer message: "..tostring(v.id))
|
||||
return
|
||||
end
|
||||
command_handler:handle(fake_message(msg,{
|
||||
delete = function() end,
|
||||
content = command
|
||||
}))
|
||||
end
|
||||
|
||||
if not config.events then
|
||||
config.events = {
|
||||
timer = {},
|
||||
event = {message = {}}
|
||||
}
|
||||
end
|
||||
|
||||
local create_event = function(msg,cronjob,create_entry)
|
||||
local arg = cronjob
|
||||
local func,functype = cron.parse_line(arg)
|
||||
if not func then
|
||||
msg:reply(functype)
|
||||
return false
|
||||
end
|
||||
local hash = md5.sumhexa(arg):sub(1,16)
|
||||
if functype == "directive" then
|
||||
local event_name = arg:match("^@(%w+)")
|
||||
if not events.event[event_name] then events.event[event_name] = {} end
|
||||
events.event[event_name][hash] = {
|
||||
comm = func,
|
||||
channel = tostring(msg.channel.id),
|
||||
id = tostring(msg.id),
|
||||
user = tostring(msg.author.id),
|
||||
type = functype
|
||||
}
|
||||
if create_entry then return true end
|
||||
if not config.events.event[event_name] then config.events.event[event_name] = {} end
|
||||
config.events.event[event_name][hash] = {
|
||||
comm = arg,
|
||||
channel = tostring(msg.channel.id),
|
||||
id = tostring(msg.id),
|
||||
user = tostring(msg.author.id),
|
||||
type = functype
|
||||
}
|
||||
else
|
||||
events.timer[hash] = {
|
||||
comm = func,
|
||||
channel = tostring(msg.channel.id),
|
||||
id = tostring(msg.id),
|
||||
user = tostring(msg.author.id),
|
||||
type = functype
|
||||
}
|
||||
if create_entry then return true end
|
||||
config.events.timer[hash] = {
|
||||
comm = arg,
|
||||
channel = tostring(msg.channel.id),
|
||||
id = tostring(msg.id),
|
||||
user = tostring(msg.author.id),
|
||||
type = functype
|
||||
}
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- load timer events
|
||||
for k,v in pairs(config.events.timer) do
|
||||
local channel = client:getChannel(v.channel)
|
||||
if channel then
|
||||
local message = channel:getMessage(v.id)
|
||||
if message then
|
||||
create_event(message,v.comm,true)
|
||||
else
|
||||
log("ERROR","No message with id "..v.id)
|
||||
end
|
||||
else
|
||||
log("ERROR","No channel with id "..v.channel)
|
||||
end
|
||||
end
|
||||
|
||||
-- load named events
|
||||
for _,evtype in pairs(config.events.event) do
|
||||
events.event[_] = {}
|
||||
for k,v in pairs(evtype) do
|
||||
local channel = client:getChannel(v.channel)
|
||||
if channel then
|
||||
local message = channel:getMessage(v.id)
|
||||
if message then
|
||||
create_event(message,v.comm,true)
|
||||
else
|
||||
log("ERROR","No message with id "..v.id)
|
||||
end
|
||||
else
|
||||
log("ERROR","No channel with id "..v.channel)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local event = command("event",{
|
||||
help = {embed={
|
||||
title = "Add a cron event",
|
||||
description = "Description coming soon",
|
||||
fields = {
|
||||
{name = "Usage:",value = "event ..."},
|
||||
{name = "Perms:",value = "administrator"},
|
||||
}
|
||||
}},
|
||||
perms = {
|
||||
"administrator"
|
||||
},
|
||||
exec = function(msg,args,opts)
|
||||
return create_event(msg,table.concat(args," "))
|
||||
end
|
||||
})
|
||||
plugin:add_command(event)
|
||||
|
||||
local delay = command("delay",{
|
||||
help = {embed={
|
||||
title = "Delay a command",
|
||||
description = "Delay fromat is <number><unit>, where unit is one of the follwing:\n\"h\" - hour,\n\"m\" - minute,\n\"d\" - day,\n\"w\" - week,\n\"y\" - year",
|
||||
fields = {
|
||||
{name = "Usage:",value = "delay <delayformat> <command>"},
|
||||
{name = "Perms:",value = "any"},
|
||||
}
|
||||
}},
|
||||
exec = function(msg,args,opts)
|
||||
local format = args[1]
|
||||
table.remove(args,1)
|
||||
local arg = os.date("%d.%m.%y %H:%M ",cron.convert_delay(format))..table.concat(args," ")
|
||||
return create_event(msg,arg)
|
||||
end
|
||||
})
|
||||
plugin:add_command(delay)
|
||||
|
||||
local events_comm = command("events",{
|
||||
help = {embed={
|
||||
title = "View your running events",
|
||||
description = "nuff said.",
|
||||
fields = {
|
||||
{name = "Usage:",value = "events <page>"},
|
||||
{name = "Perms:",value = "any"},
|
||||
}
|
||||
}},
|
||||
args = {
|
||||
"number"
|
||||
},
|
||||
exec = function(msg,args,opts)
|
||||
local uevents = {}
|
||||
local uhashes = {}
|
||||
local upto = 5*args[1]
|
||||
for k,v in pairs(config.events.timer) do
|
||||
if v.user == tostring(msg.author.id) then
|
||||
table.insert(uevents,v)
|
||||
table.insert(uhashes,k)
|
||||
end
|
||||
if #events == upto then
|
||||
break
|
||||
end
|
||||
end
|
||||
local stop = false
|
||||
for _,evtype in pairs(config.events.event) do
|
||||
for k,v in pairs(evtype) do
|
||||
if v.user == tostring(msg.author.id) then
|
||||
table.insert(uevents,v)
|
||||
table.insert(uhashes,k)
|
||||
end
|
||||
if #events == upto then
|
||||
stop = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if stop then
|
||||
break
|
||||
end
|
||||
end
|
||||
local message = {embed = {
|
||||
title = "Your events: ",
|
||||
description = "",
|
||||
footer = {
|
||||
text = "Events "..tostring(upto-4).." - "..tostring(upto)
|
||||
}
|
||||
}}
|
||||
for I = upto-4,upto do
|
||||
if not uhashes[I] then
|
||||
break
|
||||
end
|
||||
message.embed.description = message.embed.description.."["..uhashes[I].."] `"..uevents[I].comm.."`\n"
|
||||
end
|
||||
msg:reply(message)
|
||||
end
|
||||
})
|
||||
plugin:add_command(events_comm)
|
||||
|
||||
local remove_event= command("remove-event",{
|
||||
help = {embed={
|
||||
title = "Remove an event",
|
||||
description = "nuff said.",
|
||||
fields = {
|
||||
{name = "Usage:",value = "remove-event <id>"},
|
||||
{name = "Perms:",value = "any"},
|
||||
}
|
||||
}},
|
||||
args = {
|
||||
"string"
|
||||
},
|
||||
exec = function(msg,args,opts)
|
||||
for k,v in pairs(config.events.timer) do
|
||||
if (k == args[1]) and (v.user == tostring(msg.author.id)) then
|
||||
config.events.timer[k] = nil
|
||||
events.timer[k] = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
for evname,evtype in pairs(config.events.event) do
|
||||
for k,v in pairs(evtype) do
|
||||
if (k == args[1]) and (v.user == tostring(msg.author.id)) then
|
||||
config.events.event[evname][k] = nil
|
||||
events.event[evname][k] = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
msg:reply("Not found")
|
||||
return false
|
||||
end
|
||||
})
|
||||
plugin:add_command(remove_event)
|
||||
|
||||
local timer = discordia.Clock()
|
||||
timer:on("min",function()
|
||||
for k,v in pairs(events.timer) do
|
||||
local status,command = v.comm(os.date("*t"))
|
||||
if status then
|
||||
exec(v,command)
|
||||
if v.type == "onetime" then
|
||||
events.timer[k] = nil
|
||||
config.events.timer[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
client:on("messageCreate",function(msg)
|
||||
if (not msg.guild) or (tostring(msg.guild.id) ~= tostring(id)) then
|
||||
return
|
||||
end
|
||||
local content = msg.content
|
||||
local user = msg.author.id
|
||||
local channelid = msg.channel.id
|
||||
for k,v in pairs(events.event.message or {}) do
|
||||
local status,command = v.comm({content,user,channelid})
|
||||
if status then
|
||||
exec(v,command)
|
||||
end
|
||||
end
|
||||
for k,v in pairs(events.event.messageOnce or {}) do
|
||||
local status,command = v.comm({content,user,channelid})
|
||||
events.event.messageOnce[k] = nil
|
||||
config.events.event.messageOnce[k] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
timer:start(true)
|
||||
return plugin
|
|
@ -333,6 +333,20 @@ local c_echo = command("echo",{
|
|||
})
|
||||
plugin:add_command(c_echo)
|
||||
|
||||
local c_pingself = command("pingself",{
|
||||
args = {
|
||||
"string"
|
||||
},
|
||||
exec = function(msg,args,opts)
|
||||
local text = purify_strings(msg, table.concat(args," "))
|
||||
if opts["unescape"] or opts["u"] then
|
||||
text = text:gsub("\\","")
|
||||
end
|
||||
msg:reply("<@"..tostring(msg.member.id).."> "..text)
|
||||
end,
|
||||
})
|
||||
plugin:add_command(c_pingself)
|
||||
|
||||
plugin.removal_callback = function()
|
||||
for k,v in pairs(config.aliases) do
|
||||
remove_alias(k)
|
||||
|
|
|
@ -98,7 +98,7 @@ local infractions = command("infractions", {
|
|||
title = "List user infractions",
|
||||
description = "Infractions include kicks, bans, mutes and warnings.",
|
||||
fields = {
|
||||
{name = "Usage: ", value = "infractions <user> [<page>]"},
|
||||
{name = "Usage: ", value = "infractions <user> [<startfrom>]"},
|
||||
{name = "Perms: ", value = "kick_members"},
|
||||
{name = "Options: ", value = "--type=(warn default,ban,kick)"}
|
||||
}
|
||||
|
@ -123,13 +123,13 @@ local infractions = command("infractions", {
|
|||
title = "Infractions list for "..args[1].name,
|
||||
fields = {},
|
||||
footer = {
|
||||
text = "Total: "..tostring(tonumber(v[1])).." | Page: "..tostring(page)
|
||||
text = "Total: "..tostring(tonumber(v[1])).." | Starting from: "..tostring(page)
|
||||
|
||||
}
|
||||
}}
|
||||
-- Prepare a statement to match infractions
|
||||
local pagedb = db:prepare("SELECT * FROM infractions WHERE action = ? AND user = ? AND id > ? ORDER BY id LIMIT 5")
|
||||
local pagecomm = pagedb:reset():bind(dtype,tostring(args[1].id),5*page)
|
||||
local pagecomm = pagedb:reset():bind(dtype,tostring(args[1].id),page)
|
||||
-- Keep matching infractions as long as something is returned
|
||||
local pagedata = pagecomm:step()
|
||||
while pagedata ~= nil do
|
||||
|
|
Loading…
Reference in New Issue