Compare commits
No commits in common. "07501e7fa0c3a0ac9c9ca158e4375517aa27acd8" and "3dd57d3bdc222b2ad644b7af84613049e7453145" have entirely different histories.
07501e7fa0
...
3dd57d3bdc
|
@ -1,13 +1,11 @@
|
||||||
[![forthebadge](https://forthebadge.com/images/badges/powered-by-black-magic.svg)](https://forthebadge.com) [![made-with-luvit.svg](https://512mb.org/git/Yessiest/badges/raw/branch/master/badges/made-with-luvit.svg)](https://forthebadge.com/generator/)
|
[![forthebadge](https://forthebadge.com/images/badges/powered-by-black-magic.svg)](https://forthebadge.com) [![made-with-luvit.svg](https://512mb.org/git/Yessiest/badges/raw/branch/master/badges/made-with-luvit.svg)](https://forthebadge.com/generator/)
|
||||||
|
|
||||||
# 512mb.org-bot
|
# 512mb.org-bot
|
||||||
Yet another 512mb bot. It's running on a discord library for the luvit framework called [Discordia](https://github.com/SinisterRectus/discordia). For guides on using particular features of the bot check out the [wiki](https://github.com/512mb-org/512mb.org-bot/wiki).
|
yet another 512mb bot. it's running on a discord library for the luvit framework called [Discordia](https://github.com/SinisterRectus/discordia)
|
||||||
|
|
||||||
# Self-hosting
|
# Self-hosting
|
||||||
1. Get a bot token and place it in ./token
|
place the bot token in the "./token" file, change server id in bot.lua to the id of your server.
|
||||||
2. Install libqalculate and compile luaqalc
|
compile [luvit](https://luvit.io) and run bot.lua.
|
||||||
3. Place the ``libqalculator.so`` in ./libraries/
|
|
||||||
4. Get [luvit](https://luvit.io) and run ``bot.lua`` using the ``luvit`` binary
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
```
|
```
|
||||||
|
|
4
bot.lua
4
bot.lua
|
@ -16,7 +16,7 @@ local servers = {}
|
||||||
--create server
|
--create server
|
||||||
local server = import("classes.server-handler")
|
local server = import("classes.server-handler")
|
||||||
client:on("ready",function()
|
client:on("ready",function()
|
||||||
print("Starting bot")
|
print("starting test")
|
||||||
for _,id in pairs(server_ids) do
|
for _,id in pairs(server_ids) do
|
||||||
if not servers[id] then
|
if not servers[id] then
|
||||||
servers[id] = server(client,client:getGuild(id),{
|
servers[id] = server(client,client:getGuild(id),{
|
||||||
|
@ -46,4 +46,4 @@ if not tempfile then
|
||||||
end
|
end
|
||||||
local nstr = tempfile:read("*l")
|
local nstr = tempfile:read("*l")
|
||||||
tempfile:close()
|
tempfile:close()
|
||||||
client:run('Bot '..nstr:match("^%s*(.+)%s*$"))
|
client:run('Bot '..nstr)
|
||||||
|
|
Binary file not shown.
|
@ -1,153 +1,203 @@
|
||||||
--rewrite this lib (P.S: done)
|
--rewrite this lib (P.S: done)
|
||||||
--P.S: air stands for Advanced Input Recognition, although technically it's not all that advanced
|
--P.S: air stands for Advanced Input Recognition, although technically it's not all that advanced
|
||||||
local parse_string = require("string_parse")
|
|
||||||
local table_utils = require("table-utils")
|
|
||||||
air = {}
|
air = {}
|
||||||
object_types = {
|
air.match_strings = function(string)
|
||||||
["voiceChannel"] = function(id,client,guild_id)
|
local strings = {}
|
||||||
local guild = client:getGuild(guild_id)
|
string = string:gsub("\"(.-[^\\])\"",function(capt)
|
||||||
local channel = guild:getChannel(id:match("(%d+)[^%d]*$"))
|
string_id = string_id + 1
|
||||||
if tostring(channel):match("^GuildVoiceChannel: ") then
|
strings["%str"..string_id] = capt:gsub("\\\"","\"")
|
||||||
return true,channel
|
return " %str"..string_id
|
||||||
else
|
end)
|
||||||
return false
|
return string,strings
|
||||||
end
|
end
|
||||||
end,
|
|
||||||
["textChannel"] = function(id,client,guild_id)
|
local function parse_strings(thing,strings)
|
||||||
local guild = client:getGuild(guild_id)
|
--find all strings and replace them with string ids with no spaces
|
||||||
local channel = guild:getChannel(id:match("(%d+)[^%d]*$"))
|
local strings = strings or {}
|
||||||
if tostring(channel):match("^GuildTextChannel: ") then
|
local string_count = 0
|
||||||
return true,channel
|
local function get_string(text)
|
||||||
else
|
string_count = string_count + 1
|
||||||
return false
|
local id = "&;"..tostring(string_count)..";&"
|
||||||
end
|
strings[string_count] = text
|
||||||
end,
|
return id
|
||||||
["messageLink"] = function(id,client,guild_id)
|
end
|
||||||
local guild = client:getGuild(guild_id)
|
thing = thing:gsub("(\")\"",get_string)
|
||||||
local channelId,messageId = id:match("(%d+)/(%d+)[^%d]*$")
|
thing = thing:gsub("(\".-[^\\])\"",get_string)
|
||||||
channel = guild:getChannel(channelId)
|
thing = thing:gsub("(\')\'",get_string)
|
||||||
if tostring(channel):find("GuildTextChannel") then
|
thing = thing:gsub("(\'.-[^\\])\'",get_string)
|
||||||
message = channel:getMessage(messageId)
|
return thing,strings
|
||||||
if message then
|
end
|
||||||
return true,message
|
--this table will look up special types
|
||||||
end
|
special_case = {
|
||||||
end
|
["voiceChannel"] = function(id,client,guild_id)
|
||||||
return false
|
local guild = client:getGuild(guild_id)
|
||||||
end,
|
local channel = guild:getChannel(id:match("(%d+)[^%d]*$"))
|
||||||
["role"] = function(id,client,guild_id)
|
if tostring(channel):match("^GuildVoiceChannel: ") then
|
||||||
local guild = client:getGuild(guild_id)
|
return true,channel
|
||||||
local role = guild:getRole(id:match("(%d+)[^%d]*$"))
|
else
|
||||||
if role then
|
return false
|
||||||
return true,role
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
["member"] = function(id,client,guild_id)
|
|
||||||
local guild = client:getGuild(guild_id)
|
|
||||||
local member = guild:getMember(id:match("(%d+)[^%d]*$"))
|
|
||||||
if member then
|
|
||||||
return true,member
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
["emoji"] = function(id,client,guild_id)
|
|
||||||
local guild = client:getGuild(guild_id)
|
|
||||||
local emoji = guild:getEmoji(id:match("(%d+)[^%d]*$"))
|
|
||||||
if emoji then
|
|
||||||
return true,emoji
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
["ban"] = function(id,client,guild_id)
|
|
||||||
local guild = client:getGuild(guild_id)
|
|
||||||
local ban = guild:getBan(id:match("(%d+)[^%d]*$"))
|
|
||||||
if ban then
|
|
||||||
return true,ban
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
["channel"] = function(id,client,guild_id)
|
|
||||||
local guild = client:getGuild(guild_id)
|
|
||||||
local channel = guild:getChannel(id:match("(%d+)[^%d]*$"))
|
|
||||||
if channel then
|
|
||||||
return true,channel
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
["user"] = function(id,client,guild_id)
|
|
||||||
local user = client:getUser(id:match("(%d+)[^%d]*$"))
|
|
||||||
if user then
|
|
||||||
return true,user
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end,
|
|
||||||
["id"] = function(id)
|
|
||||||
if tonumber(id:match("(%d+)[^%d]*$")) and tostring(id:match("(%d+)[^%d]*$")):len() > 10 then
|
|
||||||
return true,id
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end,
|
|
||||||
["string"] = function(str)
|
|
||||||
if str:match("^[\"'].*[\"']$") then
|
|
||||||
return true, str:match("^[\"'](.*)[\"']$")
|
|
||||||
end
|
|
||||||
return true,str
|
|
||||||
end,
|
|
||||||
["number"] = function(n)
|
|
||||||
local number = tonumber(n)
|
|
||||||
return (number ~= nil), number
|
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
|
["textChannel"] = function(id,client,guild_id)
|
||||||
|
local guild = client:getGuild(guild_id)
|
||||||
|
local channel = guild:getChannel(id:match("(%d+)[^%d]*$"))
|
||||||
|
if tostring(channel):match("^GuildTextChannel: ") then
|
||||||
|
return true,channel
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["messageLink"] = function(id,client,guild_id)
|
||||||
|
local guild = client:getGuild(guild_id)
|
||||||
|
local channelId,messageId = id:match("(%d+)/(%d+)[^%d]*$")
|
||||||
|
channel = guild:getChannel(channelId)
|
||||||
|
if tostring(channel):find("GuildTextChannel") then
|
||||||
|
message = channel:getMessage(messageId)
|
||||||
|
if message then
|
||||||
|
return true,message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end,
|
||||||
|
["role"] = function(id,client,guild_id)
|
||||||
|
local guild = client:getGuild(guild_id)
|
||||||
|
local role = guild:getRole(id:match("(%d+)[^%d]*$"))
|
||||||
|
if role then
|
||||||
|
return true,role
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["member"] = function(id,client,guild_id)
|
||||||
|
local guild = client:getGuild(guild_id)
|
||||||
|
local member = guild:getMember(id:match("(%d+)[^%d]*$"))
|
||||||
|
if member then
|
||||||
|
return true,member
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["emoji"] = function(id,client,guild_id)
|
||||||
|
local guild = client:getGuild(guild_id)
|
||||||
|
local emoji = guild:getEmoji(id:match("(%d+)[^%d]*$"))
|
||||||
|
if emoji then
|
||||||
|
return true,emoji
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["ban"] = function(id,client,guild_id)
|
||||||
|
local guild = client:getGuild(guild_id)
|
||||||
|
local ban = guild:getBan(id:match("(%d+)[^%d]*$"))
|
||||||
|
if ban then
|
||||||
|
return true,ban
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["channel"] = function(id,client,guild_id)
|
||||||
|
local guild = client:getGuild(guild_id)
|
||||||
|
local channel = guild:getChannel(id:match("(%d+)[^%d]*$"))
|
||||||
|
if channel then
|
||||||
|
return true,channel
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
["user"] = function(id,client,guild_id)
|
||||||
|
local user = client:getUser(id:match("(%d+)[^%d]*$"))
|
||||||
|
if user then
|
||||||
|
return true,user
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end,
|
||||||
|
["id"] = function(id)
|
||||||
|
if tonumber(id:match("(%d+)[^%d]*$")) and tostring(id:match("(%d+)[^%d]*$")):len() > 10 then
|
||||||
|
return true,id
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
air.parse = function(string,argmatch,client,guild_id)
|
air.parse = function(string,argmatch,client,guild_id)
|
||||||
local strings = parse_string(string,"[\"']")
|
local args,opts = {},{}
|
||||||
local argmatch = table_utils.shallowcopy(argmatch or {})
|
local string_id = 0
|
||||||
local tokens,args,opts = {},{},{}
|
local strings = {}
|
||||||
-- Tokenize
|
string = string:gsub("[%s\n]+\"\"",function(capt)
|
||||||
for k,v in pairs(strings) do
|
string_id = string_id + 1
|
||||||
local padded_string = v:match("^%s*(.+)%s*$")
|
strings["%str"..string_id] = ""
|
||||||
if padded_string:match("^[\"'].*[\"']$") then
|
return " %str"..string_id
|
||||||
table.insert(tokens,padded_string)
|
end)
|
||||||
else
|
string = string:gsub("[%s\n]+\"(.-[^\\])\"",function(capt)
|
||||||
v:gsub("%S+",function(text)
|
string_id = string_id + 1
|
||||||
table.insert(tokens,text)
|
strings["%str"..string_id] = capt:gsub("\\\"","\"")
|
||||||
end)
|
return " %str"..string_id
|
||||||
end
|
end)
|
||||||
|
string = string:gsub("[%s\n]+%-%-(%w+)=\"\"",function(name)
|
||||||
|
opts[name] = ""
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
string = string:gsub("[%s\n]+%-%-(%w+)=\"(.-[^\\])\"",function(name,value)
|
||||||
|
opts[name] = value:gsub("\\\"","\"")
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
string = string:gsub("[%s\n]+%-%-(%w+)=(%S+)",function(name,value)
|
||||||
|
opts[name] = value
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
string = string:gsub("[%s\n]+%-%-(%w+)",function(name)
|
||||||
|
opts[name] = true
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
string = string:gsub("[%s\n]+%-(%w+)",function(args)
|
||||||
|
args:gsub(".",function(key)
|
||||||
|
opts[key] = true
|
||||||
|
end)
|
||||||
|
return ""
|
||||||
|
end)
|
||||||
|
string:gsub("([^%s\n]+)",function(match)
|
||||||
|
table.insert(args,match)
|
||||||
|
end)
|
||||||
|
for k,v in pairs(args) do
|
||||||
|
if v:match("%%str%d+") then
|
||||||
|
if strings[v] then
|
||||||
|
args[k] = strings[v]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
-- Remove opts and match arguments
|
end
|
||||||
for k,v in pairs(tokens) do
|
if argmatch and #argmatch > 0 then
|
||||||
if v:match("^%-%-%w+=$") then
|
local match,err = false
|
||||||
local optname = table.remove(tokens,k):match("^%-%-(%w+)=$")
|
local new_args = {}
|
||||||
local value = tokens[k]
|
for k,v in pairs(argmatch) do
|
||||||
opts[optname] = value
|
if not args[k] then
|
||||||
elseif v:match("^%-%-%w+$") then
|
match = false
|
||||||
local optname = v:match("^%-%-(%w+)$")
|
err = "Missing arguments: "..table.concat(argmatch,", ",k)
|
||||||
opts[optname] = true
|
break
|
||||||
elseif v:match("^%-%w+$") then
|
end
|
||||||
local opts = v:gsub("%w",function(c)
|
if v == "number" and tonumber(args[k]) then
|
||||||
opts[c] = true
|
match = true
|
||||||
end)
|
new_args[k] = tonumber(args[k])
|
||||||
else
|
elseif v == "string" then
|
||||||
local arg = table.remove(argmatch,1)
|
match = true
|
||||||
if arg then
|
new_args[k] = args[k]
|
||||||
local status,obj = object_types[arg](v,client,guild_id)
|
elseif special_case[v] then
|
||||||
if not status then
|
match,new_args[k] = special_case[v](args[k],client,guild_id)
|
||||||
return false, args, opts, "Mismatched argument "..tostring(#arg)..": "..arg.." expected."
|
else
|
||||||
end
|
match = false
|
||||||
table.insert(args,obj)
|
end
|
||||||
else
|
if match == false then
|
||||||
table.insert(args,select(2,object_types["string"](v)))
|
err = "Type mismatch for argument "..k..": "..argmatch[k].." expected."
|
||||||
end
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #argmatch > 0 then
|
for k,v in pairs(args) do
|
||||||
return false, args, opts, "Missing arguments: "..table.concat(argmatch,", ")
|
if not new_args[k] then
|
||||||
|
new_args[k] = v
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true, args, opts
|
return match,new_args,opts,err
|
||||||
|
else
|
||||||
|
return true,args,opts
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return air
|
return air
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
class = require("baseclass")
|
class = require("baseclass")
|
||||||
|
color = require("tty-colors")
|
||||||
tests = {}
|
tests = {}
|
||||||
tests[1] = function()
|
tests[1] = function()
|
||||||
print("Basic class initialization test")
|
print("Basic class initialization test")
|
||||||
|
@ -78,7 +79,8 @@ print("Deteceted "..#tests.." tests. Starting now.")
|
||||||
OK = 0
|
OK = 0
|
||||||
for k,v in pairs(tests) do
|
for k,v in pairs(tests) do
|
||||||
status,errcode = pcall(v)
|
status,errcode = pcall(v)
|
||||||
print("TEST #"..k.." "..((status and "OK") or "ERROR")..(((not status) and errcode) or ""))
|
stat_color = (status and "green") or "red"
|
||||||
|
print(color("TEST #"..k.." "..((status and "OK") or "ERROR")..(((not status) and errcode) or ""),stat_color))
|
||||||
if status then
|
if status then
|
||||||
OK = OK + 1
|
OK = OK + 1
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../../tty-colors.lua
|
|
@ -6,87 +6,87 @@ local class = import("classes.baseclass")
|
||||||
local table_utils = import("table-utils")
|
local table_utils = import("table-utils")
|
||||||
local acl = class("ACL")
|
local acl = class("ACL")
|
||||||
function acl:__init()
|
function acl:__init()
|
||||||
self.user_rules = {}
|
self.user_rules = {}
|
||||||
self.group_rules = {}
|
self.group_rules = {}
|
||||||
end
|
end
|
||||||
function acl:set_user_rule(user_id,status)
|
function acl:set_user_rule(user_id,status)
|
||||||
assert(
|
assert(
|
||||||
(status == nil) or (status == 0) or (status == -1) or (status == 1),
|
(status == nil) or (status == 0) or (status == -1) or (status == 1),
|
||||||
"invalid status setting"
|
"invalid status setting"
|
||||||
)
|
)
|
||||||
self.user_rules[user_id] = status
|
self.user_rules[user_id] = status
|
||||||
end
|
end
|
||||||
function acl:set_group_rule(group_id,status)
|
function acl:set_group_rule(group_id,status)
|
||||||
assert(
|
assert(
|
||||||
(status == nil) or (status == 0) or (status == -1) or (status == 1),
|
(status == nil) or (status == 0) or (status == -1) or (status == 1),
|
||||||
"invalid status setting"
|
"invalid status setting"
|
||||||
)
|
)
|
||||||
self.group_rules[group_id] = status
|
self.group_rules[group_id] = status
|
||||||
end
|
end
|
||||||
function acl:check_user(user_id)
|
function acl:check_user(user_id)
|
||||||
if self.user_rules[user_id] and self.user_rules[user_id] ~= 0 then
|
if self.user_rules[user_id] and self.user_rules[user_id] ~= 0 then
|
||||||
return true,(self.user_rules[user_id] == 1)
|
return true,(self.user_rules[user_id] == 1)
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function acl:check_group(groups)
|
function acl:check_group(groups)
|
||||||
local allow = false
|
local allow = false
|
||||||
local found = false
|
local found = false
|
||||||
for k,v in pairs(groups) do
|
for k,v in pairs(groups) do
|
||||||
if self.group_rules[v] then
|
if self.group_rules[v] then
|
||||||
found = true
|
found = true
|
||||||
allow = self.group_rules[v]
|
allow = self.group_rules[v]
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return found,(allow and allow == 1)
|
end
|
||||||
|
return found,(allow and allow == 1)
|
||||||
end
|
end
|
||||||
function acl:export_all_lists()
|
function acl:export_all_lists()
|
||||||
local lists = {
|
local lists = {
|
||||||
users = "",
|
users = "",
|
||||||
groups = ""
|
groups = ""
|
||||||
}
|
}
|
||||||
for k,v in pairs(self.user_rules) do
|
for k,v in pairs(self.user_rules) do
|
||||||
lists.users = lists.users..k..":"..tostring(v)..";\n"
|
lists.users = lists.users..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
for k,v in pairs(self.group_rules) do
|
for k,v in pairs(self.group_rules) do
|
||||||
lists.groups = lists.groups..k..":"..tostring(v)..";\n"
|
lists.groups = lists.groups..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
return lists
|
return lists
|
||||||
end
|
end
|
||||||
function acl:export_user_list()
|
function acl:export_user_list()
|
||||||
local list = ""
|
local list = ""
|
||||||
for k,v in pairs(self.user_rules) do
|
for k,v in pairs(self.user_rules) do
|
||||||
list = list..k..":"..tostring(v)..";\n"
|
list = list..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
return list
|
return list
|
||||||
end
|
end
|
||||||
function acl:export_group_list()
|
function acl:export_group_list()
|
||||||
local list = ""
|
local list = ""
|
||||||
for k,v in pairs(self.group_rules) do
|
for k,v in pairs(self.group_rules) do
|
||||||
list = list..k..":"..tostring(v)..";\n"
|
list = list..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
return list
|
return list
|
||||||
end
|
end
|
||||||
function acl:export_snapshot()
|
function acl:export_snapshot()
|
||||||
return {
|
return {
|
||||||
user_rules = bot_utils.deepcopy(self.user_rules),
|
user_rules = bot_utils.deepcopy(self.user_rules),
|
||||||
group_rules = bot_utils.deepcopy(self.group_rules)
|
group_rules = bot_utils.deepcopy(self.group_rules)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
function acl:import_snapshot(t)
|
function acl:import_snapshot(t)
|
||||||
self.user_rules = t.user_rules
|
self.user_rules = t.user_rules
|
||||||
self.group_rules = t.group_rules
|
self.group_rules = t.group_rules
|
||||||
end
|
end
|
||||||
function acl:import_user_list(list)
|
function acl:import_user_list(list)
|
||||||
list:gsub("(%w+):(%d+)",function(id,status)
|
list:gsub("(%w+):(%d+)",function(id,status)
|
||||||
self.user_rules[id] = status
|
self.user_rules[id] = status
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
function acl:import_group_list(list)
|
function acl:import_group_list(list)
|
||||||
list:gsub("(%w+):(%d+)",function(id,status)
|
list:gsub("(%w+):(%d+)",function(id,status)
|
||||||
self.group_rules[id] = status
|
self.group_rules[id] = status
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
return acl
|
return acl
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
--class generator (for the purpose of creating classes)
|
--class generator (for the purpose of creating classes)
|
||||||
return function(name)
|
return function(name)
|
||||||
|
local new_class = {}
|
||||||
|
new_class.__classname = name or "Object"
|
||||||
|
new_class.__index = new_class
|
||||||
|
new_class.__new = function(self,...)
|
||||||
|
local obj = {}
|
||||||
|
--set metamethod proetection measures
|
||||||
|
setmetatable(obj,{__index = function(obj,key)
|
||||||
|
if key:find("^__") then
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
return self[key]
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
__name = new_class.__classname})
|
||||||
|
if self.__init then
|
||||||
|
self.__init(obj,...)
|
||||||
|
end
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
new_class.extend = function(self,name)
|
||||||
local new_class = {}
|
local new_class = {}
|
||||||
new_class.__classname = name or "Object"
|
new_class.__classname = name or "Object"
|
||||||
new_class.__index = new_class
|
new_class.__index = new_class
|
||||||
new_class.__new = function(self,...)
|
setmetatable(new_class,{__index = self,__call = function(...) return new_class.__new(...) end, __name = new_class.__classname.." (class)"})
|
||||||
local obj = {}
|
|
||||||
--set metamethod proetection measures
|
|
||||||
setmetatable(obj,{__index = function(obj,key)
|
|
||||||
if key:find("^__") then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
return self[key]
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
__name = new_class.__classname})
|
|
||||||
if self.__init then
|
|
||||||
self.__init(obj,...)
|
|
||||||
end
|
|
||||||
return obj
|
|
||||||
end
|
|
||||||
new_class.extend = function(self,name)
|
|
||||||
local new_class = {}
|
|
||||||
new_class.__classname = name or "Object"
|
|
||||||
new_class.__index = new_class
|
|
||||||
setmetatable(new_class,{__index = self,__call = function(...) return new_class.__new(...) end, __name = new_class.__classname.." (class)"})
|
|
||||||
return new_class
|
|
||||||
end
|
|
||||||
--make our class callable; on call, it will initialize a new instance of itself
|
|
||||||
setmetatable(new_class,{__call = function(...) return new_class.__new(...) end, __name = new_class.__classname.." (class)"})
|
|
||||||
return new_class
|
return new_class
|
||||||
|
end
|
||||||
|
--make our class callable; on call, it will initialize a new instance of itself
|
||||||
|
setmetatable(new_class,{__call = function(...) return new_class.__new(...) end, __name = new_class.__classname.." (class)"})
|
||||||
|
return new_class
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,69 +6,85 @@ local discordia = import("discordia")
|
||||||
local enum_perms = discordia.enums.permission
|
local enum_perms = discordia.enums.permission
|
||||||
--The following method extends the ACL class to work with rule-specific features,
|
--The following method extends the ACL class to work with rule-specific features,
|
||||||
--such as the role position
|
--such as the role position
|
||||||
function command_acl:check_group(highest_role)
|
function command_acl:check_group(roles)
|
||||||
local allow = self.group_rules[tostring(highest_role.id)]
|
local found = false
|
||||||
return found,(allow and allow == 1)
|
local highest_role = nil
|
||||||
|
local highest_role_status = nil
|
||||||
|
for k,v in pairs(roles) do
|
||||||
|
if self.group_rules[v.id] then
|
||||||
|
found = true
|
||||||
|
if not highest_role then
|
||||||
|
highest_role = v
|
||||||
|
highest_role_status = self.group_rules[v.id]
|
||||||
|
end
|
||||||
|
if v.position > highest_role.position then
|
||||||
|
highest_role = v
|
||||||
|
highest_role_status = self.group_rules[v.id]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local allow = highest_role_status
|
||||||
|
return found,(allow and allow == 1)
|
||||||
end
|
end
|
||||||
--The following methods extend the ACL class to add the "perm" permissions
|
--The following methods extend the ACL class to add the "perm" permissions
|
||||||
--(the fallback when no rule/user permissions are found)
|
--(the fallback when no rule/user permissions are found)
|
||||||
function command_acl:__init()
|
function command_acl:__init()
|
||||||
self.user_rules = {}
|
self.user_rules = {}
|
||||||
self.group_rules = {}
|
self.group_rules = {}
|
||||||
self.perm_rules = {}
|
self.perm_rules = {}
|
||||||
end
|
end
|
||||||
function command_acl:check_perm(perms)
|
function command_acl:check_perm(perms)
|
||||||
local output = true
|
local output = true
|
||||||
for k,v in pairs(self.perm_rules) do
|
for k,v in pairs(self.perm_rules) do
|
||||||
if (bit.band(perms[1],enum_perms[v]) == 0) then
|
if (bit.band(perms[1],enum_perms[v]) == 0) then
|
||||||
output = false
|
output = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
function command_acl:set_perm_rules(list)
|
function command_acl:set_perm_rules(list)
|
||||||
assert(type(list)=="table","table expected, got "..type(list))
|
assert(type(list)=="table","table expected, got "..type(list))
|
||||||
self.perm_rules = list
|
self.perm_rules = list
|
||||||
end
|
end
|
||||||
function command_acl:export_all_lists()
|
function command_acl:export_all_lists()
|
||||||
local lists = {
|
local lists = {
|
||||||
users = "",
|
users = "",
|
||||||
groups = "",
|
groups = "",
|
||||||
perm = ""
|
perm = ""
|
||||||
}
|
}
|
||||||
for k,v in pairs(self.user_rules) do
|
for k,v in pairs(self.user_rules) do
|
||||||
lists.users = lists.users..k..":"..tostring(v)..";\n"
|
lists.users = lists.users..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
for k,v in pairs(self.group_rules) do
|
for k,v in pairs(self.group_rules) do
|
||||||
lists.groups = lists.groups..k..":"..tostring(v)..";\n"
|
lists.groups = lists.groups..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
for k,v in pairs(self.perm_rules) do
|
for k,v in pairs(self.perm_rules) do
|
||||||
lists.perm = lists.perm..k..":"..tostring(v)..";\n"
|
lists.perm = lists.perm..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
return lists
|
return lists
|
||||||
end
|
end
|
||||||
function command_acl:export_perm_list()
|
function command_acl:export_perm_list()
|
||||||
local list = ""
|
local list = ""
|
||||||
for k,v in pairs(self.perm_rules) do
|
for k,v in pairs(self.perm_rules) do
|
||||||
list = list..k..":"..tostring(v)..";\n"
|
list = list..k..":"..tostring(v)..";\n"
|
||||||
end
|
end
|
||||||
return list
|
return list
|
||||||
end
|
end
|
||||||
function command_acl:export_snapshot()
|
function command_acl:export_snapshot()
|
||||||
return {
|
return {
|
||||||
user_rules = table_utils.deepcopy(self.user_rules),
|
user_rules = table_utils.deepcopy(self.user_rules),
|
||||||
group_rules = table_utils.deepcopy(self.group_rules),
|
group_rules = table_utils.deepcopy(self.group_rules),
|
||||||
perm_rules = table_utils.deepcopy(self.perm_rules)
|
perm_rules = table_utils.deepcopy(self.perm_rules)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
function command_acl:import_snapshot(t)
|
function command_acl:import_snapshot(t)
|
||||||
self.user_rules = t.user_rules
|
self.user_rules = t.user_rules
|
||||||
self.group_rules = t.group_rules
|
self.group_rules = t.group_rules
|
||||||
self.perm_rules = t.perm_rules
|
self.perm_rules = t.perm_rules
|
||||||
end
|
end
|
||||||
function command_acl:import_perm_list()
|
function command_acl:import_perm_list()
|
||||||
list:gsub("(%w+):(%d+)",function(id,status)
|
list:gsub("(%w+):(%d+)",function(id,status)
|
||||||
self.perm_rules[id] = status
|
self.perm_rules[id] = status
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
return command_acl
|
return command_acl
|
||||||
|
|
|
@ -9,95 +9,108 @@ local command_handler = class("Command-handler")
|
||||||
local table_utils = import("table-utils")
|
local table_utils = import("table-utils")
|
||||||
local purify = import("purify")
|
local purify = import("purify")
|
||||||
function command_handler:__init(parent_server)
|
function command_handler:__init(parent_server)
|
||||||
self.server_handler = assert(parent_server,"parent server handler not provided")
|
self.server_handler = assert(parent_server,"parent server handler not provided")
|
||||||
self.pool = {}
|
self.command_pool = {}
|
||||||
self.prefixes = {}
|
self.prefixes = {}
|
||||||
self.meta = {
|
self.command_meta = {
|
||||||
plugins = {},
|
plugins = {},
|
||||||
categories = {}
|
categories = {}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
function command_handler:add_prefix(prefix)
|
function command_handler:add_prefix(prefix)
|
||||||
self.prefixes[prefix] = purify.purify_escapes(prefix)
|
local purified_prefix = purify.purify_escapes(prefix)
|
||||||
return true
|
self.prefixes[purified_prefix] = purified_prefix
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
function command_handler:remove_prefix(prefix)
|
function command_handler:remove_prefix(prefix)
|
||||||
if self.prefixes[prefix] and table_utils.count(self.prefixes) > 1 then
|
local purified_prefix = purify.purify_escapes(prefix)
|
||||||
self.prefixes[prefix] = nil
|
if self.prefixes[purified_prefix] or table_utils.count(self.prefixes) <= 1 then
|
||||||
return true
|
self.prefix[purified_prefix] = nil
|
||||||
end
|
return true
|
||||||
if not self.prefixes[prefix] then
|
else
|
||||||
return false, "Prefix not found"
|
return false, (
|
||||||
end
|
(self.prefixes[purified_prefix] and "No such prefix") or
|
||||||
return false, "Cannot remove last remaining prefix!"
|
"Cannot remove the last remaining prefix"
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
function command_handler:get_prefixes()
|
function command_handler:get_prefixes()
|
||||||
return table_utils.deepcopy(self.prefixes)
|
return table_utils.deepcopy(self.prefixes)
|
||||||
end
|
end
|
||||||
function command_handler:add_command(command)
|
function command_handler:add_command(command)
|
||||||
assert(type(command) == "table","command object expected")
|
assert(type(command) == "table","command object expected")
|
||||||
if self.pool[command.name] then
|
local purified_name = purify.purify_escapes(command.name)
|
||||||
return false, "Already have a command with the same name"
|
self.command_pool[purified_name] = command
|
||||||
end
|
if not self.command_meta.plugins[command.parent.name] then
|
||||||
self.pool[command.name] = command
|
self.command_meta.plugins[command.parent.name] = {}
|
||||||
if not self.meta.plugins[command.parent.name] then
|
end
|
||||||
self.meta.plugins[command.parent.name] = {}
|
if not self.command_meta.categories[command.options.category] then
|
||||||
end
|
self.command_meta.categories[command.options.category] = {}
|
||||||
self.meta.plugins[command.parent.name][command.name] = command.name
|
end
|
||||||
if not self.meta.categories[command.category] then
|
table.insert(self.command_meta.categories[command.options.category],command.name)
|
||||||
self.meta.categories[command.category] = {}
|
table.insert(self.command_meta.plugins[command.parent.name],command.name)
|
||||||
end
|
return command
|
||||||
self.meta.categories[command.category][command.name] = command.name
|
|
||||||
return command
|
|
||||||
end
|
end
|
||||||
function command_handler:remove_command(command)
|
function command_handler:remove_command(command)
|
||||||
assert(type(command) == "table","command object expected")
|
assert(type(command) == "table","command object expected")
|
||||||
if not self.pool[command.name] then
|
local purified_name = purify.purify_escapes(command.name)
|
||||||
return false
|
if self.command_pool[purified_name] then
|
||||||
|
local command = self.command_pool[purified_name]
|
||||||
|
--not exactly optimal, but lists are lists. can't do much about them.
|
||||||
|
table_utils.remove_value(self.command_meta.plugins[command.parent.name],command.name)
|
||||||
|
if #self.command_meta.plugins[command.parent.name] == 0 then
|
||||||
|
self.command_meta.plugins[command.parent.name] = nil
|
||||||
end
|
end
|
||||||
self.pool[command.name] = nil
|
table_utils.remove_value(self.command_meta.categories[command.options.category],command.name)
|
||||||
self.meta.categories[command.category][command.name] = nil
|
if #self.command_meta.categories[command.options.category] == 0 then
|
||||||
self.meta.plugins[command.parent.name][command.name] = nil
|
self.command_meta.categories[command.options.category] = nil
|
||||||
|
end
|
||||||
|
self.command_pool[purified_name] = nil
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
function command_handler:get_command(name)
|
function command_handler:get_command(name)
|
||||||
return self.pool[name]
|
local purified_name = purify.purify_escapes(assert(type(name) == "string") and name)
|
||||||
|
if self.command_pool[purified_name] then
|
||||||
|
return self.command_pool[purified_name]
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
function command_handler:get_commands(name)
|
function command_handler:get_commands(name)
|
||||||
local list = {}
|
local list = {}
|
||||||
for k,v in pairs(self.pool) do
|
for k,v in pairs(self.command_pool) do
|
||||||
table.insert(list,k)
|
table.insert(list,k)
|
||||||
end
|
end
|
||||||
return list
|
return list
|
||||||
end
|
end
|
||||||
function command_handler:get_metadata()
|
function command_handler:get_commands_metadata()
|
||||||
local plugins,categories = {},{}
|
return table_utils.deepcopy(self.command_meta)
|
||||||
for k,v in pairs(self.meta.plugins) do
|
|
||||||
plugins[k] = table_utils.listcopy(v)
|
|
||||||
end
|
|
||||||
for k,v in pairs(self.meta.categories) do
|
|
||||||
categories[k] = table_utils.listcopy(v)
|
|
||||||
end
|
|
||||||
return {
|
|
||||||
plugins = plugins,
|
|
||||||
categories = categories
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
function command_handler:handle(message,ignore_flag)
|
function command_handler:handle(message)
|
||||||
local content = message.content
|
for name,command in pairs(self.command_pool) do
|
||||||
local prefix = ""
|
if command.options.regex then
|
||||||
local command
|
if message.content:match(command.options.regex) then
|
||||||
for k,v in pairs(self.prefixes) do
|
command:exec(message)
|
||||||
if content:match("^"..v) then
|
return
|
||||||
prefix = k
|
end
|
||||||
|
else
|
||||||
|
if command.options.prefix then
|
||||||
|
for _,prefix in pairs(self.prefixes) do
|
||||||
|
if message.content:match("^"..prefix..name.."$") or message.content:match("^"..prefix..name.."%s") then
|
||||||
|
command:exec(message)
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
command = content:sub(prefix:len()+1,-1):match("^[%-_%w]+")
|
if message.content:match("^"..name.."$") or message.content:match("^"..name.."%s") then
|
||||||
if self.pool[command] then
|
command:exec(message)
|
||||||
if (prefix == "") and self.pool[command].options.prefix == false then
|
return
|
||||||
self.pool[command]:exec(message,ignore_flag)
|
|
||||||
elseif (prefix ~= "") and self.pool[command].options.prefix == true then
|
|
||||||
self.pool[command]:exec(message,ignore_flag)
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return command_handler
|
return command_handler
|
||||||
|
|
|
@ -7,170 +7,178 @@ local command = class("Command")
|
||||||
local acl = import("classes.command-acl")
|
local acl = import("classes.command-acl")
|
||||||
local discordia = import("discordia")
|
local discordia = import("discordia")
|
||||||
function command:__init(name,callback)
|
function command:__init(name,callback)
|
||||||
assert(name:match("^[-_%w]+$"),"Name can only contain alphanumeric characters, underscores or dashes")
|
self.rules = acl()
|
||||||
self.rules = acl()
|
self.name = name
|
||||||
self.name = name
|
self.timer = discordia.Date():toMilliseconds()
|
||||||
self.timer = discordia.Date():toMilliseconds()
|
self.options = {
|
||||||
self.category = "None"
|
allow_bots = false, --allow bots to execute the command
|
||||||
self.options = {
|
typing_decorator = false, --set if the bot should be "typing" while the command executes
|
||||||
allow_bots = false, --allow bots to execute the command
|
category = "None", --set category for the command
|
||||||
typing_decorator = false, --set if the bot should be "typing" while the command executes
|
prefix = true, --if true and if regex isn't enabled, check for prefix at the start. if not, don't check for prefix
|
||||||
prefix = true, --if true check for prefix at the start. if not, don't check for prefix
|
regex = false, --check if the message matches this regular expression (should be a string)
|
||||||
timeout = 1000, --set the timeout for a command
|
no_parsing = false, --check if you want to disable the message argument parsing process
|
||||||
}
|
timeout = 1000, --set the timeout for a command
|
||||||
if type(callback) == "table" then
|
}
|
||||||
for k,v in pairs(callback.options or {}) do
|
if type(callback) == "table" then
|
||||||
self.options[k] = v
|
for k,v in pairs(callback.options or {}) do
|
||||||
end
|
self.options[k] = v
|
||||||
self.callback = callback.exec
|
|
||||||
if callback.category then
|
|
||||||
self.category = callback.category
|
|
||||||
end
|
|
||||||
self.args = callback.args or self.args
|
|
||||||
if callback.users then
|
|
||||||
for k,v in pairs(callback.users) do
|
|
||||||
self.rules:set_user_rule(k,v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if callback.roles then
|
|
||||||
for k,v in pairs(callback.roles) do
|
|
||||||
self.rules:set_group_rule(k,v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
callback.perms = callback.perms and self.rules:set_perm_rules(callback.perms)
|
|
||||||
callback.help = callback.help and self:set_help(callback.help,callback.usage)
|
|
||||||
elseif type(callback) == "function" then
|
|
||||||
self.callback = callback
|
|
||||||
end
|
end
|
||||||
|
self.callback = callback.exec
|
||||||
|
self.args = callback.args or self.args
|
||||||
|
if callback.users then
|
||||||
|
for k,v in pairs(callback.users) do
|
||||||
|
self.rules:set_user_rule(k,v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if callback.roles then
|
||||||
|
for k,v in pairs(callback.roles) do
|
||||||
|
self.rules:set_group_rule(k,v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if callback.perms then
|
||||||
|
self.rules:set_perm_rules(callback.perms)
|
||||||
|
end
|
||||||
|
if callback.help then
|
||||||
|
self:set_help(callback.help,callback.usage)
|
||||||
|
end
|
||||||
|
elseif type(callback) == "function" then
|
||||||
|
self.callback = callback
|
||||||
|
end
|
||||||
end
|
end
|
||||||
--set the callback to be called on comm:exec(msg)
|
--set the callback to be called on comm:exec(msg)
|
||||||
function command:set_callback(fn)
|
function command:set_callback(fn)
|
||||||
assert(type(fn) == "function","function expected, got "..type(fn))
|
assert(type(fn) == "function","function expected, got "..type(fn))
|
||||||
self.callback = fn
|
self.callback = fn
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
--generate help using only description and usage, or nothing at all
|
--generate help using only description and usage, or nothing at all
|
||||||
function command:generate_help(description,usage)
|
function command:generate_help(description,usage)
|
||||||
assert(not description or (type(description) == "string"),"Description should be either string or nil, got "..type(description))
|
assert(not description or (type(description) == "string"),"Description should be either string or nil, got "..type(description))
|
||||||
assert(not usage or (type(usage) == "string"),"Usage should be either string or nil, got "..type(usage))
|
assert(not usage or (type(usage) == "string"),"Usage should be either string or nil, got "..type(usage))
|
||||||
local backup_usage_str
|
local backup_usage_str
|
||||||
if self.args then
|
if self.args then
|
||||||
backup_usage_str = self.name.." <"..table.concat(self.args,"> <")..">"
|
backup_usage_str = self.name.." <"..table.concat(self.args,"> <")..">"
|
||||||
else
|
else
|
||||||
backup_usage_str = "not defined"
|
backup_usage_str = "not defined"
|
||||||
end
|
end
|
||||||
local permissions = table.concat(self.rules:export_snapshot()["perms"] or {"All"},"\n")
|
local permissions = table.concat(self.rules:export_snapshot()["perms"] or {},"\n")
|
||||||
self.help = {embed = {
|
if permissions == "" then
|
||||||
title = "Help for ``"..self.name.."``",
|
permissions = "All"
|
||||||
description = description,
|
end
|
||||||
fields = {
|
self.help = {embed = {
|
||||||
{name = "Usage: ",value = usage or backup_usage_str},
|
title = "Help for ``"..self.name.."``",
|
||||||
{name = "Perms: ",value = permissions}
|
description = description,
|
||||||
}
|
fields = {
|
||||||
}}
|
{name = "Usage: ",value = usage or backup_usage_str},
|
||||||
return self
|
{name = "Perms: ",value = permissions}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
--set the help message to be sent
|
--set the help message to be sent
|
||||||
function command:set_help(obj,usage)
|
function command:set_help(obj,usage)
|
||||||
if type(obj) == "table" then
|
if type(obj) == "string" then
|
||||||
self.help = obj
|
self:generate_help(obj,usage)
|
||||||
else
|
elseif type(obj) == "table" then
|
||||||
self:generate_help(obj,
|
self.help = obj
|
||||||
(type(usage) == "string" and usage)
|
else
|
||||||
or "No description provided.")
|
error("Type "..type(obj).." cannot be set as a help message")
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
--print the help message, or generate it if there is none
|
--print the help message, or generate it if there is none
|
||||||
function command:get_help()
|
function command:get_help()
|
||||||
if not self.help then
|
if not self.help then
|
||||||
self:generate_help("Description not defined")
|
self:generate_help("Description not defined")
|
||||||
end
|
end
|
||||||
return self.help
|
return self.help
|
||||||
end
|
end
|
||||||
|
|
||||||
function command:set_timeout_callback(fn)
|
function command:set_timeout_callback(fn)
|
||||||
assert(type(fn) == "function","function expected, got "..type(fn))
|
assert(type(fn) == "function","function expected, got "..type(fn))
|
||||||
self.timeout_callback = fn
|
self.timeout_callback = fn
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--check the permissions for command
|
--check the permissions for command
|
||||||
function command:check_permissions(message,special_flag)
|
function command:check_permissions(message)
|
||||||
local ctime = discordia.Date():toMilliseconds()
|
if message.author.bot and (not self.options.allow_bots) then
|
||||||
if (ctime-self.options.timeout < self.timer) and (not ignore_flag) then
|
return false
|
||||||
if self.timeout_callback then
|
end
|
||||||
self.timeout_callback(message)
|
if discordia.Date():toMilliseconds()-self.options.timeout < self.timer then
|
||||||
end
|
if self.timeout_callback then
|
||||||
return false
|
self.timeout_callback(fn)
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
self.timer = discordia.Date():toMilliseconds()
|
end
|
||||||
-- user rules first, group second, permission rules last
|
self.timer = discordia.Date():toMilliseconds()
|
||||||
if ignore_flag == 2 then
|
if self.rules:check_user(message.author.id) then
|
||||||
return true
|
local found,allow = self.rules:check_user(message.author.id)
|
||||||
end
|
return allow
|
||||||
local User, allowUser = self.rules:check_user(tostring(message.author.id))
|
end
|
||||||
local Group, allowGroup = self.rules:check_group(message.member.highestRole)
|
if self.rules:check_group(message.member.roles) then
|
||||||
if User then
|
local found,allow = self.rules:check_group(message.member.roles)
|
||||||
return allowUser
|
return allow
|
||||||
end
|
end
|
||||||
if Group then
|
return self.rules:check_perm(message.member:getPermissions(message.channel))
|
||||||
return allowGroup
|
|
||||||
end
|
|
||||||
return self.rules:check_perm(message.member:getPermissions(message.channel))
|
|
||||||
end
|
end
|
||||||
--the main entry point for the command - execute the callback within after
|
--the main entry point for the command - execute the callback within after
|
||||||
--multiple checks
|
--multiple checks
|
||||||
function command:exec(message,ignore_flag)
|
function command:exec(message,args,opts)
|
||||||
if message.author.bot and (not self.options.allow_bots) then
|
local exec = self.callback
|
||||||
return false
|
if not self.callback then
|
||||||
|
error("Callback not set for command "..self.name)
|
||||||
|
end
|
||||||
|
if self.decorator then
|
||||||
|
self.callback = self.decorator(self.callback)
|
||||||
|
end
|
||||||
|
local content
|
||||||
|
if self.options.regex then
|
||||||
|
content = message.content
|
||||||
|
else
|
||||||
|
local strstart,strend = message.content:find(self.name,1,true)
|
||||||
|
content = message.content:sub(strend+1,-1)
|
||||||
|
end
|
||||||
|
if self:check_permissions(message) then
|
||||||
|
if self.options.typing_decorator then
|
||||||
|
message.channel:broadcastTyping()
|
||||||
end
|
end
|
||||||
if self:check_permissions(message,ignore_flag) then
|
local status,args,opts,err = import("air").parse(content,self.args,message.client,message.guild.id)
|
||||||
local exec = self.callback
|
if status then
|
||||||
if not self.callback then
|
local callst,status,response = pcall(self.callback,message,args,opts)
|
||||||
error("Callback not set for command "..self.name)
|
if callst then
|
||||||
|
if type(status) == "boolean" then
|
||||||
|
if status then
|
||||||
|
message:addReaction("✅")
|
||||||
|
else
|
||||||
|
message:addReaction("❌")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if self.decorator then
|
else
|
||||||
self.callback = self.decorator(self.callback)
|
message:addReaction("⚠️")
|
||||||
end
|
message:reply("An internal error occured: "..status)
|
||||||
local strstart,strend = message.content:find(self.name,1,true)
|
end
|
||||||
content = message.content:sub(strend+1,-1)
|
else
|
||||||
if self.options.typing_decorator then
|
message:addReaction("❌")
|
||||||
message.channel:broadcastTyping()
|
message:reply(err)
|
||||||
end
|
|
||||||
local status,args,opts,err = import("air").parse(content,self.args,message.client,message.guild.id)
|
|
||||||
if status then
|
|
||||||
local callst,status,response = pcall(self.callback,message,args,opts)
|
|
||||||
if callst then
|
|
||||||
if type(status) == "boolean" then
|
|
||||||
message:addReaction((status and "✅") or "❌")
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
message:addReaction("⚠️")
|
|
||||||
message:reply("An internal error occured: "..status)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
message:addReaction("❌")
|
|
||||||
message:reply(err)
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
message:addReaction("❌")
|
message:addReaction("❌")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
--add decorators for the callback
|
--add decorators for the callback
|
||||||
function command:set_decorator(fn)
|
function command:set_decorator(fn)
|
||||||
assert(type(fn) == "function","a decorator function expected, got "..type(fn))
|
assert(type(fn) == "function","a decorator function expected, got "..type(fn))
|
||||||
self.decorator = fn
|
self.decorator = fn
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
--get a list of all properties of the command
|
--get a list of all properties of the command
|
||||||
function command:get_properties()
|
function command:get_properties()
|
||||||
return {
|
return {
|
||||||
name = self.name,
|
name = self.name,
|
||||||
category = self.options.category,
|
category = self.options.category,
|
||||||
args = table_utils.deepcopy(self.args),
|
args = table_utils.deepcopy(self.args),
|
||||||
help = table_utils.deepcopy(self.help),
|
help = table_utils.deepcopy(self.help),
|
||||||
prefix = self.prefix
|
prefix = self.prefix
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
return command
|
return command
|
||||||
|
|
|
@ -2,94 +2,94 @@ local class = import("classes.baseclass")
|
||||||
local emitter_proxy = class("EmitterProxy")
|
local emitter_proxy = class("EmitterProxy")
|
||||||
|
|
||||||
function emitter_proxy:__init(emitter)
|
function emitter_proxy:__init(emitter)
|
||||||
self.original = emitter
|
self.original = emitter
|
||||||
self.callback_pool = {}
|
self.callback_pool = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:on(event,callback)
|
function emitter_proxy:on(event,callback)
|
||||||
if not self.callback_pool[event] then
|
if not self.callback_pool[event] then
|
||||||
self.callback_pool[event] = {}
|
self.callback_pool[event] = {}
|
||||||
end
|
end
|
||||||
self.callback_pool[event][callback] = callback
|
self.callback_pool[event][callback] = callback
|
||||||
self.original:on(event,callback)
|
self.original:on(event,callback)
|
||||||
return callback
|
return callback
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:once(event,callback)
|
function emitter_proxy:once(event,callback)
|
||||||
if not self.callback_pool[event] then
|
if not self.callback_pool[event] then
|
||||||
self.callback_pool[event] = {}
|
self.callback_pool[event] = {}
|
||||||
end
|
end
|
||||||
local wrapper = function(...)
|
local wrapper = function(...)
|
||||||
callback(...)
|
callback(...)
|
||||||
self.callback_pool[event][callback] = nil
|
self.callback_pool[event][callback] = nil
|
||||||
end
|
end
|
||||||
self.callback_pool[event][callback] = wrapper
|
self.callback_pool[event][callback] = wrapper
|
||||||
self.callback_pool[event][wrapper] = wrapper
|
self.callback_pool[event][wrapper] = wrapper
|
||||||
self.original:once(event,wrapper)
|
self.original:once(event,wrapper)
|
||||||
return callback
|
return callback
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:removeListener(event,callback)
|
function emitter_proxy:removeListener(event,callback)
|
||||||
if self.callback_pool[event] and self.callback_pool[event][callback] then
|
if self.callback_pool[event] and self.callback_pool[event][callback] then
|
||||||
self.callback_pool[event][callback] = nil
|
self.callback_pool[event][callback] = nil
|
||||||
self.original:removeListener(event,callback)
|
self.original:removeListener(event,callback)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:removeAllListeners(event,callback)
|
function emitter_proxy:removeAllListeners(event,callback)
|
||||||
if self.callback_pool[event] then
|
if self.callback_pool[event] then
|
||||||
for k,v in pairs(self.callback_pool[event]) do
|
for k,v in pairs(self.callback_pool[event]) do
|
||||||
self.original:removeListener(event,v)
|
self.original:removeListener(event,v)
|
||||||
end
|
|
||||||
self.callback_pool[event] = nil
|
|
||||||
end
|
end
|
||||||
|
self.callback_pool[event] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:listeners(event)
|
function emitter_proxy:listeners(event)
|
||||||
local copy = {}
|
local copy = {}
|
||||||
if self.callback_pool[event] then
|
if self.callback_pool[event] then
|
||||||
for k,v in pairs(self.callback_pool[event]) do
|
for k,v in pairs(self.callback_pool[event]) do
|
||||||
table.insert(copy,v)
|
table.insert(copy,v)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return copy
|
end
|
||||||
|
return copy
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:listenerCount(event)
|
function emitter_proxy:listenerCount(event)
|
||||||
local count = 0
|
local count = 0
|
||||||
if event then
|
if event then
|
||||||
if self.callback_pool[event] then
|
if self.callback_pool[event] then
|
||||||
for k,v in pairs(self.callback_pool[event]) do
|
for k,v in pairs(self.callback_pool[event]) do
|
||||||
count = count + 1
|
count = count + 1
|
||||||
end
|
end
|
||||||
end
|
|
||||||
else
|
|
||||||
for k,v in pairs(self.callback_pool) do
|
|
||||||
for k2,v2 in pairs(v) do
|
|
||||||
count = count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return count
|
else
|
||||||
|
for k,v in pairs(self.callback_pool) do
|
||||||
|
for k2,v2 in pairs(v) do
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return count
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:propogate(event,emitter)
|
function emitter_proxy:propogate(event,emitter)
|
||||||
if not self.callback_pool[event] then
|
if not self.callback_pool[event] then
|
||||||
self.callback_pool[event] = {}
|
self.callback_pool[event] = {}
|
||||||
end
|
end
|
||||||
local emitter_propogate_handler = function(...)
|
local emitter_propogate_handler = function(...)
|
||||||
emitter:emit(event,...)
|
emitter:emit(event,...)
|
||||||
end
|
end
|
||||||
self.callback_pool[event][emitter_propogate_handler] = emitter_propogate_handler
|
self.callback_pool[event][emitter_propogate_handler] = emitter_propogate_handler
|
||||||
self.original:on(event,emitter_propogate_handler)
|
self.original:on(event,emitter_propogate_handler)
|
||||||
return emitter_propogate_handler
|
return emitter_propogate_handler
|
||||||
end
|
end
|
||||||
|
|
||||||
function emitter_proxy:destroy()
|
function emitter_proxy:destroy()
|
||||||
for k,v in pairs(self.callback_pool) do
|
for k,v in pairs(self.callback_pool) do
|
||||||
for k2,v2 in pairs(v) do
|
for k2,v2 in pairs(v) do
|
||||||
self.original:removeListener(k,v2)
|
self.original:removeListener(k,v2)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return emitter_proxy
|
return emitter_proxy
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
local interface = {}
|
||||||
|
interface.wrapper = function(client,guild_id)
|
||||||
|
local new_i = {}
|
||||||
|
new_i.message = {}
|
||||||
|
new_i.message.get = function(channel,id)
|
||||||
|
local new_m = {}
|
||||||
|
local message = client.getMessage(id)
|
||||||
|
local new_m.content = message.content
|
||||||
|
local new_m.created_at = message.createdAt
|
||||||
|
local new_m.attachments = {}
|
||||||
|
for k,v in pairs(message.attachments) do
|
||||||
|
table.insert(new_m
|
|
@ -0,0 +1,90 @@
|
||||||
|
local RPC_server = import("classes.RPC-server")
|
||||||
|
local class = import("classes.baseclass")
|
||||||
|
local monitor = class("Monitor")
|
||||||
|
|
||||||
|
--we only generate proxies as far as 1 object deep.
|
||||||
|
--to provide seamlessness, metamethods that request object proxies from their
|
||||||
|
--pointers may be used on the client side
|
||||||
|
|
||||||
|
--pointers here mean tables that contain the __id and __type properties.
|
||||||
|
--they do not hold any info on the object besides its class name and id
|
||||||
|
|
||||||
|
--a lookup table of all classes that we do not ignore. we exclude client and containers
|
||||||
|
--because they might break the sandboxing. we *do not* want that.
|
||||||
|
local allowed_types = {
|
||||||
|
["guild"] = true,
|
||||||
|
["member"] = true,
|
||||||
|
["emoji"] = true,
|
||||||
|
["message"] = true,
|
||||||
|
["channel"] = true,
|
||||||
|
["role"] = true,
|
||||||
|
["user"] = true,
|
||||||
|
["invite"] = true,
|
||||||
|
["guildtextchannel"] = true,
|
||||||
|
["textchannel"] = true,
|
||||||
|
["iterable"] = true,
|
||||||
|
["cache"] = true,
|
||||||
|
["arrayiterable"] = true,
|
||||||
|
["filteretediterable"] = true,
|
||||||
|
["secondarycache"] = true,
|
||||||
|
["weakcache"] = true,
|
||||||
|
["tableiterable"] = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
--a lookup table of classes that can be explicitly converted to arrays.
|
||||||
|
local iterable_types = {
|
||||||
|
["iterable"] = true,
|
||||||
|
["cache"] = true,
|
||||||
|
["arrayiterable"] = true,
|
||||||
|
["filteretediterable"] = true,
|
||||||
|
["secondarycache"] = true,
|
||||||
|
["weakcache"] = true,
|
||||||
|
["tableiterable"] = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
local comprehend_object = function(object)
|
||||||
|
local output
|
||||||
|
if (type(object) == "table") and (object.__class) then
|
||||||
|
--our object is an instance of a class
|
||||||
|
local class = object.__class.__name:lower()
|
||||||
|
if allowed_types[class] and (not iterable_types[class]) then
|
||||||
|
--our object can only be pointed to
|
||||||
|
output = {__id = object[k].id, __type = class}
|
||||||
|
else
|
||||||
|
--our object can be converted to an array
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--our object is either an atomic data type, a string or a table.
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local create_proxy = function(object)
|
||||||
|
local output = {}
|
||||||
|
for k,v in pairs(getmetatable(object).__getters) do
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local proto_api = {
|
||||||
|
msg = {
|
||||||
|
get = function(channel,id)
|
||||||
|
channel:getMessage(id)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
guild = {
|
||||||
|
|
||||||
|
},
|
||||||
|
member = {
|
||||||
|
|
||||||
|
},
|
||||||
|
channel = {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function monitor:__init(guild,options)
|
||||||
|
assert(guild,"No guild provided")
|
||||||
|
assert(options,"No options provided (arg 2)")
|
||||||
|
|
||||||
|
|
|
@ -11,133 +11,131 @@ local json = import("json")
|
||||||
local core = import("core")
|
local core = import("core")
|
||||||
local emitter_proxy = import("classes.emitter-proxy")
|
local emitter_proxy = import("classes.emitter-proxy")
|
||||||
local table_utils = import("table-utils")
|
local table_utils = import("table-utils")
|
||||||
local log = import("logging")
|
|
||||||
|
|
||||||
function plugin_handler:__init(parent_server)
|
function plugin_handler:__init(parent_server)
|
||||||
assert(parent_server,"server handler to assign the plugin handler to has not been provided")
|
assert(parent_server,"server handler to assign the plugin handler to has not been provided")
|
||||||
self.server_handler = parent_server
|
self.server_handler = parent_server
|
||||||
self.plugins = {}
|
self.plugins = {}
|
||||||
self.plugin_info = {}
|
self.plugin_info = {}
|
||||||
self.plugin_paths = {}
|
self.plugin_paths = {}
|
||||||
self.server_handler.event_emitter:on("serverSaveConfig",function()
|
self.server_handler.event_emitter:on("serverSaveConfig",function()
|
||||||
log("SERVER", "Saving plugins configs")
|
print("[SERVER] Saving plugins configs")
|
||||||
for name,plugin in pairs(self.plugins) do
|
for name,plugin in pairs(self.plugins) do
|
||||||
self:save_plugin_config(name)
|
self:save_plugin_config(name)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:load_plugin_config(name)
|
function plugin_handler:load_plugin_config(name)
|
||||||
return file.readJSON(self.server_handler.config_path..name..".json",{})
|
return file.readJSON(self.server_handler.config_path..name..".json",{})
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:save_plugin_config(name)
|
function plugin_handler:save_plugin_config(name)
|
||||||
if self.plugins[name] then
|
if self.plugins[name] then
|
||||||
file.writeJSON(self.server_handler.config_path..name..".json",self.plugins[name].__env.config)
|
file.writeJSON(self.server_handler.config_path..name..".json",self.plugins[name].__env.config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:add_plugin_folder(path)
|
function plugin_handler:add_plugin_folder(path)
|
||||||
assert(type(path) == "string","path should be a string, got "..type(path))
|
assert(type(path) == "string","path should be a string, got "..type(path))
|
||||||
table.insert(self.plugin_paths,path)
|
table.insert(self.plugin_paths,path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:scan_folder(path)
|
function plugin_handler:scan_folder(path)
|
||||||
local file = io.open(path.."/meta.json","r")
|
local file = io.open(path.."/meta.json","r")
|
||||||
if file then
|
if file then
|
||||||
local metadata,code,err = json.decode(file:read("*a"))
|
local metadata,code,err = json.decode(file:read("*a"))
|
||||||
if metadata and metadata.name then
|
if metadata and metadata.name then
|
||||||
self.plugin_info[metadata.name] = metadata
|
self.plugin_info[metadata.name] = metadata
|
||||||
self.plugin_info[metadata.name].path = path.."/"
|
self.plugin_info[metadata.name].path = path.."/"
|
||||||
self.plugin_info[metadata.name].loaded = false
|
self.plugin_info[metadata.name].loaded = false
|
||||||
end
|
|
||||||
file:close()
|
|
||||||
else
|
|
||||||
for k,v in pairs({"/init.lua","/main.lua"}) do
|
|
||||||
local file = io.open(path..v,"r")
|
|
||||||
if file then
|
|
||||||
local name = path:match("[^/]+$")
|
|
||||||
self.plugin_info[name] = {["main"]=v:gsub("/","")}
|
|
||||||
self.plugin_info[name].path = path.."/"
|
|
||||||
self.plugin_info[name].loaded = false
|
|
||||||
file:close()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
file:close()
|
||||||
|
else
|
||||||
|
for k,v in pairs({"/init.lua","/main.lua"}) do
|
||||||
|
local file = io.open(path..v,"r")
|
||||||
|
if file then
|
||||||
|
local name = path:match("[^/]+$")
|
||||||
|
self.plugin_info[name] = {["main"]=v:gsub("/","")}
|
||||||
|
self.plugin_info[name].path = path.."/"
|
||||||
|
self.plugin_info[name].loaded = false
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:update_plugin_info()
|
function plugin_handler:update_plugin_info()
|
||||||
for k,v in pairs(self.plugin_paths) do
|
for k,v in pairs(self.plugin_paths) do
|
||||||
if file.existsDir(v) then
|
if file.existsDir(v) then
|
||||||
file.ls(v):gsub("[^\n]+",function(c)
|
file.ls(v):gsub("[^\n]+",function(c)
|
||||||
self:scan_folder(v..c)
|
self:scan_folder(v..c)
|
||||||
end)
|
end)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:list_loadable()
|
function plugin_handler:list_loadable()
|
||||||
return table_utils.deepcopy(self.plugin_info)
|
return table_utils.deepcopy(self.plugin_info)
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:load(name)
|
function plugin_handler:load(name)
|
||||||
if not self.plugin_info[name] then
|
if not self.plugin_info[name] then
|
||||||
return false, "No such plugin"
|
return false, "No such plugin"
|
||||||
end
|
end
|
||||||
if not self.plugin_info[name].main then
|
if not self.plugin_info[name].main then
|
||||||
return false, "Plugin metadata entry doesn't specify the main file path or main file isn't found"
|
return false, "Plugin metadata entry doesn't specify the main file path or main file isn't found"
|
||||||
end
|
end
|
||||||
if self.plugin_info[name].loaded then
|
if self.plugin_info[name].loaded then
|
||||||
return false, "Plugin is already loaded"
|
return false, "Plugin is already loaded"
|
||||||
end
|
end
|
||||||
local environment = setmetatable({
|
local environment = setmetatable({
|
||||||
id = self.server_handler.id,
|
id = self.server_handler.id,
|
||||||
globals = self.server_handler.config,
|
globals = self.server_handler.config,
|
||||||
signals = emitter_proxy(self.server_handler.signal_emitter),
|
signals = emitter_proxy(self.server_handler.signal_emitter),
|
||||||
client = self.server_handler.client,
|
client = self.server_handler.client,
|
||||||
events = emitter_proxy(self.server_handler.event_emitter),
|
events = emitter_proxy(self.server_handler.event_emitter),
|
||||||
discordia = import("discordia"),
|
discordia = import("discordia"),
|
||||||
server = self.server_handler,
|
server = self.server_handler,
|
||||||
command_handler = self.server_handler.command_handler,
|
command_handler = self.server_handler.command_handler,
|
||||||
plugin_handler = self.server_handler.plugin_handler,
|
plugin_handler = self.server_handler.plugin_handler,
|
||||||
log = log,
|
log = function() end,
|
||||||
config = self:load_plugin_config(name),
|
config = self:load_plugin_config(name),
|
||||||
import = import,
|
import = import,
|
||||||
},{__index = _G})
|
},{__index = _G})
|
||||||
local plugin_meta = self.plugin_info[name]
|
local plugin_meta = self.plugin_info[name]
|
||||||
if file.exists(plugin_meta.path..plugin_meta.main) then
|
if file.exists(plugin_meta.path..plugin_meta.main) then
|
||||||
environment["plugin_path"] = plugin_meta.path
|
environment["plugin_path"] = plugin_meta.path
|
||||||
local plugin_content = file.read(plugin_meta.path..plugin_meta.main,"*a")
|
local plugin_content = file.read(plugin_meta.path..plugin_meta.main,"*a")
|
||||||
local plugin_loader,err = load(plugin_content,"plugin loader: "..plugin_meta.path..plugin_meta.main,nil,environment)
|
local plugin_loader,err = load(plugin_content,"plugin loader: "..plugin_meta.path..plugin_meta.main,nil,environment)
|
||||||
if plugin_loader then
|
if plugin_loader then
|
||||||
local plugin_object = plugin_loader()
|
local plugin_object = plugin_loader()
|
||||||
if plugin_object then
|
if plugin_object then
|
||||||
plugin_object.name = name
|
plugin_object.name = name
|
||||||
plugin_object:load(environment)
|
plugin_object:load(environment)
|
||||||
self.plugins[name] = plugin_object
|
self.plugins[name] = plugin_object
|
||||||
self.plugins[name].__env = environment
|
self.plugins[name].__env = environment
|
||||||
self.plugin_info[name].loaded = true
|
self.plugin_info[name].loaded = true
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false, "Plugin object missing"
|
return false, "Plugin object missing"
|
||||||
end
|
end
|
||||||
else
|
|
||||||
return false, err
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
return false, "File specified as the main file is inaccessible"
|
return false, err
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
return false, "File specified as the main file is inaccessible"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin_handler:unload(name)
|
function plugin_handler:unload(name)
|
||||||
if self.plugins[name] then
|
if self.plugins[name] then
|
||||||
self.plugins[name].__env.signals:destroy()
|
self.plugins[name].__env.signals:destroy()
|
||||||
self.plugins[name].__env.events:destroy()
|
self.plugins[name].__env.events:destroy()
|
||||||
self.plugins[name]:unload()
|
self.plugins[name]:unload()
|
||||||
self.plugin_info[name].loaded = false
|
self.plugin_info[name].loaded = false
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false,"Plugin is not loaded"
|
return false,"Plugin is not loaded"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return plugin_handler
|
return plugin_handler
|
||||||
|
|
|
@ -2,81 +2,58 @@ local class = import("classes.baseclass")
|
||||||
local plugin = class("Plugin")
|
local plugin = class("Plugin")
|
||||||
|
|
||||||
function plugin:__init()
|
function plugin:__init()
|
||||||
self.command_pool = {}
|
self.command_pool = {}
|
||||||
self.config = {}
|
self.config = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin:load(environment)
|
function plugin:load(environment)
|
||||||
self.command_handler = environment.server.command_handler
|
self.command_handler = environment.server.command_handler
|
||||||
for k,v in pairs(self.command_pool) do
|
for k,v in pairs(self.command_pool) do
|
||||||
self.command_handler:add_command(v)
|
self.command_handler:add_command(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin:unload()
|
function plugin:unload()
|
||||||
if self.removal_callback then
|
if self.removal_callback then
|
||||||
self.removal_callback()
|
self.removal_callback()
|
||||||
end
|
end
|
||||||
for k,v in pairs(self.command_pool) do
|
for k,v in pairs(self.command_pool) do
|
||||||
self.command_handler:remove_command(v)
|
self.command_handler:remove_command(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin:for_all_commands(fn)
|
function plugin:for_all_commands(fn)
|
||||||
assert(type(fn)=="function","function expected, got "..type(fn))
|
assert(type(fn)=="function","function expected, got "..type(fn))
|
||||||
for k,v in pairs(self.command_pool) do
|
for k,v in pairs(self.command_pool) do
|
||||||
fn(v)
|
fn(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin:for_every_new_command(fn)
|
function plugin:for_every_new_command(fn)
|
||||||
assert(type(fn)=="function","function expected, got "..type(fn))
|
assert(type(fn)=="function","function expected, got "..type(fn))
|
||||||
self.decorator = fn
|
self.decorator = fn
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin:add_command(command_object)
|
function plugin:add_command(command_object)
|
||||||
if self.decorator then
|
if self.decorator then
|
||||||
self.fn(command_object)
|
self.fn(command_object)
|
||||||
end
|
end
|
||||||
command_object.parent = self
|
command_object.parent = self
|
||||||
self.command_pool[command_object] = command_object
|
self.command_pool[command_object] = command_object
|
||||||
--in post init state: we request the command handler to add the commands
|
--in post init state: we request the command handler to add the commands
|
||||||
--that way, we can link our plugin back to the command handler
|
--that way, we can link our plugin back to the command handler
|
||||||
if self.command_handler then
|
if self.command_handler then
|
||||||
self.command_handler:add_command(command_object)
|
self.command_handler:add_command(command_object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin:remove_command(command_object)
|
function plugin:remove_command(command_object)
|
||||||
if self.command_pool[command_object] then
|
if self.command_pool[command_object] then
|
||||||
self.command_pool[command_object] = nil
|
self.command_pool[command_object] = nil
|
||||||
end
|
end
|
||||||
--remove command after post-init state
|
--remove command after post-init state
|
||||||
if self.command_handler then
|
if self.command_handler then
|
||||||
self.command_handler:remove_command(command_object)
|
self.command_handler:remove_command(command_object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function plugin:load_helpdb(path)
|
|
||||||
local helpdb_file = io.open(path,r)
|
|
||||||
local helpdb,err = load(helpdb_file:read("*a") or "","helpdb "..path,nil,
|
|
||||||
setmetatable({
|
|
||||||
require = require,
|
|
||||||
import = import
|
|
||||||
},{
|
|
||||||
__index = _G
|
|
||||||
})
|
|
||||||
)
|
|
||||||
helpdb_file:close()
|
|
||||||
if not helpdb then
|
|
||||||
error(err)
|
|
||||||
end
|
|
||||||
helpdb = helpdb()
|
|
||||||
self:for_all_commands(function(command)
|
|
||||||
if helpdb[command.name] then
|
|
||||||
command:set_help(helpdb[command.name])
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -6,99 +6,98 @@ local command_handler = import("classes.command-handler")
|
||||||
local file = import("file")
|
local file = import("file")
|
||||||
local eventlist = import("eventlist")
|
local eventlist = import("eventlist")
|
||||||
local discordia = import("discordia")
|
local discordia = import("discordia")
|
||||||
local log = import("logging")
|
|
||||||
|
|
||||||
local function check_partitioning(id,...)
|
local function check_partitioning(id,...)
|
||||||
args = {...}
|
args = {...}
|
||||||
v = args[1]
|
v = args[1]
|
||||||
if type(v) == "table" and v.guild and v.guild.id == id then
|
if type(v) == "table" and v.guild and v.guild.id == id then
|
||||||
return true
|
return true
|
||||||
elseif not (type(v) == "table") then
|
elseif not (type(v) == "table") then
|
||||||
return true
|
return true
|
||||||
elseif type(v) == "table" and (not v.guild) and (tostring(v):find("Guild: ")) and v.id == id then
|
elseif type(v) == "table" and (not v.guild) and (tostring(v):find("Guild: ")) and v.id == id then
|
||||||
return true
|
return true
|
||||||
elseif type(v) == "table" and (not v.guild) and (v.message) and (v.message.guild.id == id) then
|
elseif type(v) == "table" and (not v.guild) and (v.message) and (v.message.guild.id == id) then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function server_handler:__init(client,guild,options)
|
function server_handler:__init(client,guild,options)
|
||||||
assert(type(client) == "table","discordia client expected, got "..type(client))
|
assert(type(client) == "table","discordia client expected, got "..type(client))
|
||||||
self.client = client
|
self.client = client
|
||||||
self.uptime = discordia.Date()
|
self.uptime = discordia.Date()
|
||||||
self.event_emitter = core.Emitter:new()
|
self.event_emitter = core.Emitter:new()
|
||||||
self.signal_emitter = core.Emitter:new()
|
self.signal_emitter = core.Emitter:new()
|
||||||
self.plugin_handler = plugin_handler(self)
|
self.plugin_handler = plugin_handler(self)
|
||||||
self.command_handler = command_handler(self)
|
self.command_handler = command_handler(self)
|
||||||
self.id = guild.id
|
self.id = guild.id
|
||||||
--conifgurable properties
|
--conifgurable properties
|
||||||
self.config_path = options.path or "./servers/%id/"
|
self.config_path = options.path or "./servers/%id/"
|
||||||
self.autosave = options.path or true
|
self.autosave = options.path or true
|
||||||
self.autosave_frequency = options.autosave_frequency or 10
|
self.autosave_frequency = options.autosave_frequency or 10
|
||||||
self.plugin_search_paths = options.plugin_search_paths or {"./plugins/"}
|
self.plugin_search_paths = options.plugin_search_paths or {"./plugins/"}
|
||||||
self.default_plugins = options.default_plugins or {"plugins"}
|
self.default_plugins = options.default_plugins or {"test"}
|
||||||
self.default_prefixes = options.default_prefixes or {"&","<@"..self.client.user.id.."> ","."}
|
self.default_prefixes = options.default_prefixes or {"&","<@!"..self.client.user.id..">"}
|
||||||
self.config = {}
|
self.config = {}
|
||||||
self.config_path = self.config_path:gsub("%%id",self.id)
|
self.config_path = self.config_path:gsub("%%id",self.id)
|
||||||
self:load_config()
|
self:load_config()
|
||||||
self.config["prefix"] = self.config["prefix"] or self.default_prefixes[1] or "(missing prefix)"
|
self.config["prefix"] = self.config["prefix"] or self.default_prefixes[1] or "(missing prefix)"
|
||||||
self.message_counter = 0
|
self.message_counter = 0
|
||||||
if self.autosave then
|
if self.autosave then
|
||||||
self.client:on("messageCreate",function(msg)
|
|
||||||
self.message_counter = self.message_counter + 1
|
|
||||||
if math.fmod(self.message_counter,self.autosave_frequency) == 0 then
|
|
||||||
self:save_config()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
if not file.existsDir(self.config_path) then
|
|
||||||
os.execute("mkdir -p "..self.config_path)
|
|
||||||
end
|
|
||||||
for k,v in pairs(eventlist) do
|
|
||||||
self.client:on(v,function(...)
|
|
||||||
--check if the event is for this server, and then emit.
|
|
||||||
if check_partitioning(self.id,...) then
|
|
||||||
self.event_emitter:emit(v,...)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
self.client:on("messageCreate",function(msg)
|
self.client:on("messageCreate",function(msg)
|
||||||
if msg.guild and msg.guild.id == self.id then
|
self.message_counter = self.message_counter + 1
|
||||||
self.command_handler:handle(msg)
|
if math.fmod(self.message_counter,self.autosave_frequency) == 0 then
|
||||||
end
|
self:save_config()
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
for _,path in pairs(self.plugin_search_paths) do
|
end
|
||||||
self.plugin_handler:add_plugin_folder(path)
|
if not file.existsDir(self.config_path) then
|
||||||
end
|
os.execute("mkdir -p "..self.config_path)
|
||||||
self.plugin_handler:update_plugin_info()
|
end
|
||||||
for _,plugin_name in pairs(self.default_plugins) do
|
for k,v in pairs(eventlist) do
|
||||||
log("SERVER", "Loading plugin: "..tostring(plugin_name).." - ", self.plugin_handler:load(plugin_name))
|
self.client:on(v,function(...)
|
||||||
end
|
--check if the event is for this server, and then emit.
|
||||||
for _,prefix in pairs(self.default_prefixes) do
|
if check_partitioning(self.id,...) then
|
||||||
self.command_handler:add_prefix(prefix)
|
self.event_emitter:emit(v,...)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
self.client:on("messageCreate",function(msg)
|
||||||
|
if msg.guild and msg.guild.id == self.id then
|
||||||
|
self.command_handler:handle(msg)
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
|
for _,path in pairs(self.plugin_search_paths) do
|
||||||
|
self.plugin_handler:add_plugin_folder(path)
|
||||||
|
end
|
||||||
|
self.plugin_handler:update_plugin_info()
|
||||||
|
for _,plugin_name in pairs(self.default_plugins) do
|
||||||
|
print("[SERVER] Loading plugin: "..tostring(plugin_name).." - ", self.plugin_handler:load(plugin_name))
|
||||||
|
end
|
||||||
|
for _,prefix in pairs(self.default_prefixes) do
|
||||||
|
self.command_handler:add_prefix(prefix)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function server_handler:load_config(path)
|
function server_handler:load_config(path)
|
||||||
log("SERVER", "Loading config")
|
print("[SERVER] Loading config")
|
||||||
if path then
|
if path then
|
||||||
self.config = file.readJSON(path,{})
|
self.config = file.readJSON(path,{})
|
||||||
else
|
else
|
||||||
self.config = file.readJSON(self.config_path.."config.json")
|
self.config = file.readJSON(self.config_path.."config.json")
|
||||||
end
|
end
|
||||||
self.event_emitter:emit("serverLoadConfig",self.config)
|
self.event_emitter:emit("serverLoadConfig",self.config)
|
||||||
end
|
end
|
||||||
|
|
||||||
function server_handler:save_config(path)
|
function server_handler:save_config(path)
|
||||||
log("SERVER", "Saving config")
|
print("[SERVER] Saving config")
|
||||||
if path then
|
if path then
|
||||||
file.writeJSON(path,self.config)
|
file.writeJSON(path,self.config)
|
||||||
else
|
else
|
||||||
file.writeJSON(self.config_path.."config.json",self.config)
|
file.writeJSON(self.config_path.."config.json",self.config)
|
||||||
end
|
end
|
||||||
self.event_emitter:emit("serverSaveConfig",self.config)
|
self.event_emitter:emit("serverSaveConfig",self.config)
|
||||||
end
|
end
|
||||||
return server_handler
|
return server_handler
|
||||||
|
|
|
@ -8,7 +8,6 @@ The above copyright notice and this permission notice shall be included in all c
|
||||||
|
|
||||||
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.
|
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.
|
||||||
]]
|
]]
|
||||||
local find_strings = require("string_parse")
|
|
||||||
|
|
||||||
local safe_regex = function(str,pattern)
|
local safe_regex = function(str,pattern)
|
||||||
local status,ret = pcall(string.match,str,pattern)
|
local status,ret = pcall(string.match,str,pattern)
|
||||||
|
@ -19,7 +18,6 @@ end
|
||||||
if _VERSION=="Lua 5.1" then
|
if _VERSION=="Lua 5.1" then
|
||||||
table.unpack = unpack
|
table.unpack = unpack
|
||||||
end
|
end
|
||||||
|
|
||||||
local cron = {
|
local cron = {
|
||||||
directive_handler = nil
|
directive_handler = nil
|
||||||
}
|
}
|
||||||
|
@ -202,6 +200,50 @@ local syntax = {
|
||||||
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 startfrom = function(pos,t)
|
||||||
local newtable = {}
|
local newtable = {}
|
||||||
for i = pos,#t do
|
for i = pos,#t do
|
||||||
|
@ -222,6 +264,7 @@ cron._split = function(text)
|
||||||
return tokens
|
return tokens
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
cron._split_with_strings = function(text)
|
cron._split_with_strings = function(text)
|
||||||
-- Parse strings
|
-- Parse strings
|
||||||
local nt = find_strings(text)
|
local nt = find_strings(text)
|
||||||
|
@ -274,9 +317,6 @@ cron.parse_directive = function(tokens)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if stop then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-- We use a delimiter so that command start wouldn't be ambiguous
|
-- We use a delimiter so that command start wouldn't be ambiguous
|
||||||
-- Rather than defining an amount of arguments to directives, we
|
-- Rather than defining an amount of arguments to directives, we
|
||||||
|
|
|
@ -1,48 +1,48 @@
|
||||||
return function(message,overrides)
|
return function(message,overrides)
|
||||||
assert(type(message) == "table","table expected, got "..type(message))
|
assert(type(message) == "table","table expected, got "..type(message))
|
||||||
assert(type(overrides) == "table","table expected for arg#2, got "..type(overrides))
|
assert(type(overrides) == "table","table expected for arg#2, got "..type(overrides))
|
||||||
local fake = {content = message.content,
|
local fake = {content = message.content,
|
||||||
author = message.author,
|
author = message.author,
|
||||||
member = message.guild:getMember(message.author.id),
|
member = message.guild:getMember(message.author.id),
|
||||||
channel = message.channel,
|
channel = message.channel,
|
||||||
client = message.client,
|
client = message.client,
|
||||||
guild = message.guild,
|
guild = message.guild,
|
||||||
delete = function() message:delete() end,
|
delete = function() message:delete() end,
|
||||||
reply = function(thing,...)
|
reply = function(thing,...)
|
||||||
message.channel:send(...)
|
message.channel:send(...)
|
||||||
end,
|
end,
|
||||||
createdAt = message.createdAt,
|
createdAt = message.createdAt,
|
||||||
_parent = message.parent,
|
_parent = message.parent,
|
||||||
parent = message.parent,
|
parent = message.parent,
|
||||||
id = message.id,
|
id = message.id,
|
||||||
attachment = message.attachment,
|
attachment = message.attachment,
|
||||||
attachments = message.attachments,
|
attachments = message.attachments,
|
||||||
cleanContent = message.cleanContent,
|
cleanContent = message.cleanContent,
|
||||||
editedTimestamp = message.editedTimestamp,
|
editedTimestamp = message.editedTimestamp,
|
||||||
embed = message.embed,
|
embed = message.embed,
|
||||||
embeds = message.embeds,
|
embeds = message.embeds,
|
||||||
link = message.link,
|
link = message.link,
|
||||||
mentionedChannels = message.mentionedChannels,
|
mentionedChannels = message.mentionedChannels,
|
||||||
mentionedEmojis = message.mentionedEmojis,
|
mentionedEmojis = message.mentionedEmojis,
|
||||||
mentionedRoles = message.mentionedRoles,
|
mentionedRoles = message.mentionedRoles,
|
||||||
mentionedUsers = message.mentionedUsers,
|
mentionedUsers = message.mentionedUsers,
|
||||||
nonce = message.nonce,
|
nonce = message.nonce,
|
||||||
oldContent = message.oldContent,
|
oldContent = message.oldContent,
|
||||||
pinned = message.pinned,
|
pinned = message.pinned,
|
||||||
reactions = message.reactions,
|
reactions = message.reactions,
|
||||||
tts = message.tts,
|
tts = message.tts,
|
||||||
type = message.type,
|
type = message.type,
|
||||||
webhookId = message.webhookId,
|
webhookId = message.webhookId,
|
||||||
addReaction = function(self,...)
|
addReaction = function(self,...)
|
||||||
message:addReaction(...)
|
message:addReaction(...)
|
||||||
end,
|
end,
|
||||||
removeReaction = function(self,...)
|
removeReaction = function(self,...)
|
||||||
message:removeReaction(...)
|
message:removeReaction(...)
|
||||||
end,
|
end,
|
||||||
emulated = true
|
emulated = true
|
||||||
}
|
}
|
||||||
for k,v in pairs(overrides) do
|
for k,v in pairs(overrides) do
|
||||||
fake[k] = v
|
fake[k] = v
|
||||||
end
|
end
|
||||||
return fake
|
return fake
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,112 +2,112 @@
|
||||||
local file = {}
|
local file = {}
|
||||||
local json
|
local json
|
||||||
if pcall(import,"json") then
|
if pcall(import,"json") then
|
||||||
json = import("json")
|
json = import("json")
|
||||||
elseif pcall(require,"json") then
|
elseif pcall(require,"json") then
|
||||||
json = require("json")
|
json = require("json")
|
||||||
end
|
end
|
||||||
file.safe = true
|
file.safe = true
|
||||||
file.read = function(filename,mode)
|
file.read = function(filename,mode)
|
||||||
assert(type(filename) == "string","string expected, got "..type(filename))
|
assert(type(filename) == "string","string expected, got "..type(filename))
|
||||||
local mode = mode or "*a"
|
local mode = mode or "*a"
|
||||||
local temp_file,err = io.open(filename,r)
|
local temp_file,err = io.open(filename,r)
|
||||||
if err then
|
if err then
|
||||||
if not file.safe then error(err) else
|
if not file.safe then error(err) else
|
||||||
ret_string = ""
|
ret_string = ""
|
||||||
end
|
|
||||||
else
|
|
||||||
ret_string = temp_file:read(mode)
|
|
||||||
temp_file:close()
|
|
||||||
end
|
end
|
||||||
return ret_string,err
|
else
|
||||||
|
ret_string = temp_file:read(mode)
|
||||||
|
temp_file:close()
|
||||||
|
end
|
||||||
|
return ret_string,err
|
||||||
end
|
end
|
||||||
|
|
||||||
file.write = function(filename,write)
|
file.write = function(filename,write)
|
||||||
assert(type(filename) == "string", "string expected, got "..type(filename))
|
assert(type(filename) == "string", "string expected, got "..type(filename))
|
||||||
assert(type(write) == "string", "string expected for argument #2, got "..type(write))
|
assert(type(write) == "string", "string expected for argument #2, got "..type(write))
|
||||||
local temp_file,err = io.open(filename,"w+")
|
local temp_file,err = io.open(filename,"w+")
|
||||||
local status = false
|
local status = false
|
||||||
if err then
|
if err then
|
||||||
if not file.safe then error(err) else
|
if not file.safe then error(err) else
|
||||||
status = false
|
status = false
|
||||||
end
|
|
||||||
else
|
|
||||||
temp_file:write(write)
|
|
||||||
temp_file:close()
|
|
||||||
status = true
|
|
||||||
end
|
end
|
||||||
return status,err
|
else
|
||||||
|
temp_file:write(write)
|
||||||
|
temp_file:close()
|
||||||
|
status = true
|
||||||
|
end
|
||||||
|
return status,err
|
||||||
end
|
end
|
||||||
|
|
||||||
file.exists = function(filename)
|
file.exists = function(filename)
|
||||||
local file = io.open(filename,"r")
|
local file = io.open(filename,"r")
|
||||||
if file then
|
if file then
|
||||||
file:close()
|
file:close()
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
file.existsDir = function(filename)
|
file.existsDir = function(filename)
|
||||||
local file = io.open(filename.."/stuff","w")
|
local file = io.open(filename.."/stuff","w")
|
||||||
if file then
|
if file then
|
||||||
file:close()
|
file:close()
|
||||||
os.remove(filename.."/stuff")
|
os.remove(filename.."/stuff")
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
file.ls = function(path)
|
file.ls = function(path)
|
||||||
if file.existsDir(path) then
|
if file.existsDir(path) then
|
||||||
local ls_handle = io.popen("ls -1 "..path,"r")
|
local ls_handle = io.popen("ls -1 "..path,"r")
|
||||||
local ls_data = ls_handle:read("*a")
|
local ls_data = ls_handle:read("*a")
|
||||||
ls_handle:close()
|
ls_handle:close()
|
||||||
return ls_data
|
return ls_data
|
||||||
else
|
else
|
||||||
return false, "No such file or directory"
|
return false, "No such file or directory"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if json then
|
if json then
|
||||||
file.readJSON = function(filename,default)
|
file.readJSON = function(filename,default)
|
||||||
assert(type(filename) == "string","string expected, got "..type(filename))
|
assert(type(filename) == "string","string expected, got "..type(filename))
|
||||||
local json_data,err = file.read(filename,"*a")
|
local json_data,err = file.read(filename,"*a")
|
||||||
local table_data, status
|
local table_data, status
|
||||||
if err then
|
if err then
|
||||||
if not file.safe then error(err) else
|
if not file.safe then error(err) else
|
||||||
status = err
|
status = err
|
||||||
table_data = default or {}
|
table_data = default or {}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
table_data,_,err = json.decode(json_data)
|
table_data,_,err = json.decode(json_data)
|
||||||
if not table_data then
|
if not table_data then
|
||||||
if not file.safe then error(err) else
|
if not file.safe then error(err) else
|
||||||
status = err
|
status = err
|
||||||
table_data = default or {}
|
table_data = default or {}
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return table_data, status
|
end
|
||||||
end
|
end
|
||||||
file.writeJSON = function(filename,table_data)
|
return table_data, status
|
||||||
assert(type(filename) == "string","string expected, got "..type(filename))
|
end
|
||||||
assert(type(table_data) == "table","table expected, got "..type(table_data))
|
file.writeJSON = function(filename,table_data)
|
||||||
local status = false
|
assert(type(filename) == "string","string expected, got "..type(filename))
|
||||||
local status,json_object,_,err = pcall(function() return json.encode(table_data) end)
|
assert(type(table_data) == "table","table expected, got "..type(table_data))
|
||||||
if not status then
|
local status = false
|
||||||
if not file.safe then error(err) else
|
local status,json_object,_,err = pcall(function() return json.encode(table_data) end)
|
||||||
status = false
|
if not status then
|
||||||
err = json_object
|
if not file.safe then error(err) else
|
||||||
end
|
status = false
|
||||||
else
|
err = json_object
|
||||||
if json_object then
|
end
|
||||||
status,err = file.write(filename,json_object)
|
else
|
||||||
end
|
if json_object then
|
||||||
end
|
status,err = file.write(filename,json_object)
|
||||||
return status, err
|
end
|
||||||
end
|
end
|
||||||
|
return status, err
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return file
|
return file
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
--Luvit's deadly sin - a library that fixes the dumbest problem in luvit
|
--Luvit's deadly sin - a library that fixes the dumbest problem in luvit
|
||||||
--That is, unability to load core modules from the files that were required
|
--That is, unability to load core modules from the files that were required
|
||||||
return function(reqfunc)
|
return function(reqfunc)
|
||||||
local function import(path)
|
local function import(path)
|
||||||
local paths = {}
|
local paths = { }
|
||||||
package.path:gsub("[^;]+",function(path)
|
package.path:gsub("[^;]+",function(path)
|
||||||
table.insert(paths,path)
|
table.insert(paths,path)
|
||||||
end)
|
end)
|
||||||
local filename = path:gsub("%.","/")
|
local filename = path:gsub("%.","/")
|
||||||
local file = io.open(filename..".lua","r")
|
local file = io.open(filename..".lua","r")
|
||||||
local iterator = 0
|
local iterator = 0
|
||||||
local last_filename = ""
|
local last_filename = ""
|
||||||
while not file do
|
while not file do
|
||||||
iterator = iterator + 1
|
iterator = iterator + 1
|
||||||
if paths[iterator] then
|
if paths[iterator] then
|
||||||
file = io.open(paths[iterator]:gsub("%?",filename),"r")
|
file = io.open(paths[iterator]:gsub("%?",filename),"r")
|
||||||
last_filename = paths[iterator]
|
last_filename = paths[iterator]
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
|
||||||
if not file then
|
|
||||||
return reqfunc(path)
|
|
||||||
else
|
|
||||||
content = file:read("*a")
|
|
||||||
local f,err = load(content,"import: "..filename,nil,setmetatable({
|
|
||||||
require = reqfunc,
|
|
||||||
import = import,
|
|
||||||
},{__index = _G}))
|
|
||||||
if err then
|
|
||||||
error("[import: "..filename.."] "..tostring(err))
|
|
||||||
end
|
|
||||||
return f()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return import
|
if not file then
|
||||||
|
return reqfunc(path)
|
||||||
|
else
|
||||||
|
content = file:read("*a")
|
||||||
|
local func,err = load(content,"import: "..filename,nil,setmetatable({
|
||||||
|
require = reqfunc,
|
||||||
|
import = import,
|
||||||
|
},{__index = _G}))
|
||||||
|
if err then
|
||||||
|
error(err)
|
||||||
|
end
|
||||||
|
return func()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return import
|
||||||
end
|
end
|
||||||
--[[
|
--[[
|
||||||
Usage:
|
Usage:
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
local logging_facilities = {
|
|
||||||
["ALIAS"] = "0;32",
|
|
||||||
["REACTIONS"] = "0;32",
|
|
||||||
["SERVER"] = "1;34",
|
|
||||||
["ERROR"] = "1;31",
|
|
||||||
["WARNING"] = "1;33"
|
|
||||||
}
|
|
||||||
local clear = "\27[0m"
|
|
||||||
local concat = function(tab,separator)
|
|
||||||
local text = ""
|
|
||||||
local separator = separator or "\9"
|
|
||||||
for k,v in pairs(tab) do
|
|
||||||
text = text..tostring(v)..separator
|
|
||||||
end
|
|
||||||
return text:sub(1,-1-separator:len())
|
|
||||||
end
|
|
||||||
return function(facility, ...)
|
|
||||||
local effect = "\27["
|
|
||||||
if logging_facilities[facility] then
|
|
||||||
effect = effect..logging_facilities[facility].."m"
|
|
||||||
else
|
|
||||||
effect = effect.."1m"
|
|
||||||
end
|
|
||||||
print(os.date("%Y-%m-%d %H:%M:%S | ")..effect.."["..facility.."]"..clear.."\9| "..concat({...}))
|
|
||||||
end
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 23fcea17c2eb380b6a6b1ba848d5bc7ebdc38b05
|
Subproject commit 9e6f09050f9ebecc4ffcea1234b920468254a79b
|
|
@ -1,123 +1,123 @@
|
||||||
local markov = {}
|
local markov = {}
|
||||||
|
|
||||||
local function node(relations)
|
local function node(relations)
|
||||||
local node = {}
|
local node = {}
|
||||||
local total = 0
|
local total = 0
|
||||||
for k,v in pairs(relations) do
|
for k,v in pairs(relations) do
|
||||||
total = total + v.occurences
|
total = total + v.occurences
|
||||||
end
|
end
|
||||||
for k,v in pairs(relations) do
|
for k,v in pairs(relations) do
|
||||||
node[k] = {probability = v.occurences/total,occurences = v.occurences}
|
node[k] = {probability = v.occurences/total,occurences = v.occurences}
|
||||||
end
|
end
|
||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
local function escape(str)
|
local function escape(str)
|
||||||
return str:gsub("([%%%*%(%)%^%.%[%]%+%-%$%?])","%%%1")
|
return str:gsub("([%%%*%(%)%^%.%[%]%+%-%$%?])","%%%1")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function register_words(str,word_list)
|
local function register_words(str,word_list)
|
||||||
local word_list = word_list or {}
|
local word_list = word_list or {}
|
||||||
str:gsub("%S+",function(word)
|
str:gsub("%S+",function(word)
|
||||||
if not word_list[word] then
|
if not word_list[word] then
|
||||||
word_list[word] = {}
|
word_list[word] = {}
|
||||||
|
end
|
||||||
|
local current_word = word_list[word]
|
||||||
|
local escaped_word = escape(word)
|
||||||
|
str:gsub("%s+" .. escaped_word .. "%s+(%S+)",function(word2)
|
||||||
|
if not current_word[word2] then
|
||||||
|
current_word[word2] = {}
|
||||||
end
|
end
|
||||||
local current_word = word_list[word]
|
if not current_word[word2].occurences then
|
||||||
local escaped_word = escape(word)
|
current_word[word2].occurences = 1
|
||||||
str:gsub("%s+" .. escaped_word .. "%s+(%S+)",function(word2)
|
else
|
||||||
if not current_word[word2] then
|
current_word[word2].occurences = current_word[word2].occurences + 1
|
||||||
current_word[word2] = {}
|
end
|
||||||
end
|
end)
|
||||||
if not current_word[word2].occurences then
|
end)
|
||||||
current_word[word2].occurences = 1
|
for k,v in pairs(word_list) do
|
||||||
else
|
word_list[k] = node(v)
|
||||||
current_word[word2].occurences = current_word[word2].occurences + 1
|
end
|
||||||
end
|
return word_list
|
||||||
end)
|
|
||||||
end)
|
|
||||||
for k,v in pairs(word_list) do
|
|
||||||
word_list[k] = node(v)
|
|
||||||
end
|
|
||||||
return word_list
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local table_length = function(tab)
|
local table_length = function(tab)
|
||||||
local len = 0
|
local len = 0
|
||||||
for k,v in pairs(tab) do
|
for k,v in pairs(tab) do
|
||||||
len = len + 1
|
len = len + 1
|
||||||
end
|
end
|
||||||
return len
|
return len
|
||||||
end
|
end
|
||||||
|
|
||||||
function markov.walk(self,start)
|
function markov.walk(self,start)
|
||||||
if not self.init then
|
if not self.init then
|
||||||
error("Attempted to use method on uninitialized instances")
|
error("Attempted to use an instance method on an uninitialized instance")
|
||||||
end
|
end
|
||||||
local random = math.random(0,1e7)/1e7
|
local random = math.random(0,1e7)/1e7
|
||||||
local words = {}
|
local words = {}
|
||||||
words.count = 0
|
words.count = 0
|
||||||
local word = nil
|
local word = nil
|
||||||
if self.net[start] then
|
if self.net[start] then
|
||||||
while (words.count < 1) and (table_length(self.net[start]) > 0) do
|
while (words.count < 1) and (table_length(self.net[start]) > 0) do
|
||||||
for k,v in pairs(self.net[start]) do
|
for k,v in pairs(self.net[start]) do
|
||||||
if (random <= v.probability) then
|
if (random <= v.probability) then
|
||||||
words.count = words.count + 1
|
words.count = words.count + 1
|
||||||
table.insert(words,k)
|
table.insert(words,k)
|
||||||
end
|
|
||||||
end
|
|
||||||
random = math.random(0,1e7)/1e7
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
random = math.random(0,1e7)/1e7
|
||||||
end
|
end
|
||||||
if words.count > 0 then
|
end
|
||||||
word = words[math.random(1,#words)]
|
if words.count > 0 then
|
||||||
end
|
word = words[math.random(1,#words)]
|
||||||
return word
|
end
|
||||||
|
return word
|
||||||
end
|
end
|
||||||
|
|
||||||
function markov.expand_vocabulary(self,source)
|
function markov.expand_vocabulary(self,source)
|
||||||
if not self.init then
|
if not self.init then
|
||||||
error("Attempted to use method on uninitialized instances")
|
error("Attempted to use an instance method on an uninitialized instance")
|
||||||
end
|
end
|
||||||
self.net = register_words(source,self.net)
|
self.net = register_words(source,self.net)
|
||||||
end
|
end
|
||||||
|
|
||||||
function markov.save_state(self)
|
function markov.save_state(self)
|
||||||
return self.net
|
return self.net
|
||||||
end
|
end
|
||||||
|
|
||||||
function markov.load_state(self,new_state)
|
function markov.load_state(self,new_state)
|
||||||
self.net = new_state
|
self.net = new_state
|
||||||
end
|
end
|
||||||
|
|
||||||
function markov.run(self,start,count)
|
function markov.run(self,start,count)
|
||||||
if not self.init then
|
if not self.init then
|
||||||
error("Attempted to use an instance method on an uninitialized instance")
|
error("Attempted to use an instance method on an uninitialized instance")
|
||||||
|
end
|
||||||
|
if not start then
|
||||||
|
for k,v in pairs(self.net) do
|
||||||
|
start = k
|
||||||
|
break
|
||||||
end
|
end
|
||||||
if not start then
|
end
|
||||||
for k,v in pairs(self.net) do
|
local sequence = ""
|
||||||
start = k
|
local current_word = start
|
||||||
break
|
while current_word do
|
||||||
end
|
sequence = sequence..current_word.." "
|
||||||
|
local _,counter = sequence:gsub("(%S+)","%1")
|
||||||
|
current_word = self:walk(current_word)
|
||||||
|
if counter > (count or 200) then
|
||||||
|
sequence = sequence:sub(1,-2).."..."
|
||||||
|
break
|
||||||
end
|
end
|
||||||
local sequence = ""
|
end
|
||||||
local current_word = start
|
return sequence
|
||||||
while current_word do
|
|
||||||
sequence = sequence..current_word.." "
|
|
||||||
local _,counter = sequence:gsub("(%S+)","%1")
|
|
||||||
current_word = self:walk(current_word)
|
|
||||||
if counter > (count or 200) then
|
|
||||||
sequence = sequence:sub(1,-2).."..."
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return sequence
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function markov.new(str)
|
function markov.new(str)
|
||||||
local self = setmetatable({},{__index = markov})
|
local self = setmetatable({},{__index = markov})
|
||||||
self.net = register_words(str or "")
|
self.net = register_words(str or "")
|
||||||
self.init = true
|
self.init = true
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
return markov
|
return markov
|
||||||
|
|
|
@ -1,34 +1,32 @@
|
||||||
--string purifier library
|
--string purifier library
|
||||||
local purify = {}
|
local purify = {}
|
||||||
purify.purify_pings = function(msg,input)
|
purify.purify_pings = function(msg,input)
|
||||||
local text = input
|
local text = input
|
||||||
while text:match("<@(%D*)(%d*)>") do
|
while text:match("<@(%D*)(%d*)>") do
|
||||||
local obj,id = text:match("<@(%D*)(%d*)>")
|
local obj,id = text:match("<@(%D*)(%d*)>")
|
||||||
local substitution = ""
|
local substitution = ""
|
||||||
if obj:match("!") then
|
if obj:match("!") then
|
||||||
local member = msg.guild:getMember(id)
|
local member = msg.guild:getMember(id)
|
||||||
if member then
|
if member then
|
||||||
substitution = "@"..member.name
|
substitution = "@"..member.name
|
||||||
end
|
end
|
||||||
elseif obj:match("&") then
|
elseif obj:match("&") then
|
||||||
local role = msg.guild:getRole(id)
|
local role = msg.guild:getRole(id)
|
||||||
if role then
|
if role then
|
||||||
substitution = "@"..role.name
|
substitution = "@"..role.name
|
||||||
end
|
end
|
||||||
end
|
|
||||||
if substitution == "" then
|
|
||||||
substitution = "<\\@"..obj..id..">"
|
|
||||||
end
|
|
||||||
text = text:gsub("<@(%D*)"..id..">",substitution)
|
|
||||||
end
|
end
|
||||||
text = text:gsub("@everyone","")
|
if substitution == "" then
|
||||||
text = text:gsub("@here","")
|
substitution = "<\\@"..obj..id..">"
|
||||||
return text
|
end
|
||||||
|
text = text:gsub("<@(%D*)"..id..">",substitution)
|
||||||
|
end
|
||||||
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
purify.purify_escapes = function(text)
|
purify.purify_escapes = function(text)
|
||||||
local match = "([%(%)%.%%%+%-%*%?%[%]%^%$])"
|
local match = "([%(%)%.%%%+%-%*%?%[%]%^%$])"
|
||||||
return text:gsub(match,"%%%1")
|
return text:gsub(match,"%%%1")
|
||||||
end
|
end
|
||||||
|
|
||||||
return purify
|
return purify
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
return function(text,custom_strings)
|
|
||||||
local delimiters = custom_strings or "[\"'/]"
|
|
||||||
-- 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(delimiters) do
|
|
||||||
local string = strings[#strings]
|
|
||||||
-- Opening character for a string
|
|
||||||
local open_pos = string:find(delimiters)
|
|
||||||
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
|
|
|
@ -15,50 +15,42 @@ utilities.deepcopy = function(orig)
|
||||||
return copy
|
return copy
|
||||||
end
|
end
|
||||||
utilities.slice = function(list,start,list_end)
|
utilities.slice = function(list,start,list_end)
|
||||||
local output = {}
|
local output = {}
|
||||||
for I = (start or 1),(list_end or #table) do
|
for I = (start or 1),(list_end or #table) do
|
||||||
table.insert(output,list[I])
|
table.insert(output,list[I])
|
||||||
end
|
end
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
utilities.shallowcopy = function(orig)
|
utilities.shallowcopy = function(orig)
|
||||||
local copy = {}
|
local copy = {}
|
||||||
for k,v in pairs(orig) do
|
for k,v in pairs(orig) do
|
||||||
copy[k] = v
|
copy[k] = v
|
||||||
end
|
end
|
||||||
return copy
|
return copy
|
||||||
end
|
|
||||||
|
|
||||||
utilities.listcopy = function(orig)
|
|
||||||
local list = {}
|
|
||||||
for k,v in pairs(orig) do
|
|
||||||
table.insert(list,v)
|
|
||||||
end
|
|
||||||
return list
|
|
||||||
end
|
end
|
||||||
--overwrite the original table's properties with new properties
|
--overwrite the original table's properties with new properties
|
||||||
utilities.overwrite = function(original,overwrite)
|
utilities.overwrite = function(original,overwrite)
|
||||||
local new = utilities.shallowcopy(original)
|
local new = utilities.shallowcopy(original)
|
||||||
for k,v in pairs(overwrite) do
|
for k,v in pairs(overwrite) do
|
||||||
new[k] = v
|
new[k] = v
|
||||||
end
|
end
|
||||||
return new
|
return new
|
||||||
end
|
end
|
||||||
--merge all objects passed as arguments into a table.
|
--merge all objects passed as arguments into a table.
|
||||||
--if the object is a table, merge all of it's contents with the table
|
--if the object is a table, merge all of it's contents with the table
|
||||||
utilities.merge = function(...)
|
utilities.merge = function(...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
local new = {}
|
local new = {}
|
||||||
for k,v in pairs(args) do
|
for k,v in pairs(args) do
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
for k2,v2 in pairs(v) do
|
for k2,v2 in pairs(v) do
|
||||||
table.insert(new,v2)
|
table.insert(new,v2)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
table.insert(new,v)
|
table.insert(new,v)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return new
|
end
|
||||||
|
return new
|
||||||
end
|
end
|
||||||
utilities.remove_value = function(tb,v)
|
utilities.remove_value = function(tb,v)
|
||||||
local id_to_remove = nil
|
local id_to_remove = nil
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
return function(sec)
|
return function(sec)
|
||||||
local hours = math.floor(sec/3600)
|
local hours = math.floor(sec/3600)
|
||||||
local minutes = math.floor((sec - hours*3600)/60)
|
local minutes = math.floor((sec - hours*3600)/60)
|
||||||
local seconds = sec - (hours*3600) - (minutes*60)
|
local seconds = sec - (hours*3600) - (minutes*60)
|
||||||
hours = ((hours < 10) and ("0"..hours)) or hours
|
hours = ((hours < 10) and ("0"..hours)) or hours
|
||||||
minutes = ((minutes < 10) and ("0"..minutes)) or minutes
|
minutes = ((minutes < 10) and ("0"..minutes)) or minutes
|
||||||
seconds = ((seconds < 10) and ("0"..seconds)) or seconds
|
seconds = ((seconds < 10) and ("0"..seconds)) or seconds
|
||||||
return ((tonumber(hours) > 0 and hours..":") or "")..minutes..":"..seconds
|
return ((tonumber(hours) > 0 and hours..":") or "")..minutes..":"..seconds
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,7 +26,10 @@ local triggerOnce = function(evname,args,vars)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
event_emitter:on("messageCreate",function(msg)
|
client:on("messageCreate",function(msg)
|
||||||
|
if (not msg.guild) or (tostring(msg.guild.id) ~= tostring(id)) then
|
||||||
|
return
|
||||||
|
end
|
||||||
local content = msg.content
|
local content = msg.content
|
||||||
local user = msg.author.id
|
local user = msg.author.id
|
||||||
local channelid = msg.channel.id
|
local channelid = msg.channel.id
|
||||||
|
@ -42,7 +45,10 @@ event_emitter:on("messageCreate",function(msg)
|
||||||
triggerOnce("messageOnce",{content,user,channelid},args)
|
triggerOnce("messageOnce",{content,user,channelid},args)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
event_emitter:on("userBan",function(user,guild)
|
client:on("userBan",function(user,guild)
|
||||||
|
if tostring(guild.id) ~= tostring(id) then
|
||||||
|
return
|
||||||
|
end
|
||||||
args = {
|
args = {
|
||||||
["%$USER"] = user.id,
|
["%$USER"] = user.id,
|
||||||
["%$USERNAME"] = user.name
|
["%$USERNAME"] = user.name
|
||||||
|
@ -53,7 +59,10 @@ event_emitter:on("userBan",function(user,guild)
|
||||||
triggerOnce("banOnce",{user.id},args)
|
triggerOnce("banOnce",{user.id},args)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
event_emitter:on("userUnban",function(user,guild)
|
client:on("userUnban",function(user,guild)
|
||||||
|
if tostring(guild.id) ~= tostring(id) then
|
||||||
|
return
|
||||||
|
end
|
||||||
args = {
|
args = {
|
||||||
["%$USER"] = user.id,
|
["%$USER"] = user.id,
|
||||||
["%$USERNAME"] = user.name
|
["%$USERNAME"] = user.name
|
||||||
|
@ -64,11 +73,14 @@ event_emitter:on("userUnban",function(user,guild)
|
||||||
triggerOnce("unbanOnce",{user.id},args)
|
triggerOnce("unbanOnce",{user.id},args)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
event_emitter:on("memberJoin", function(member)
|
client:on("memberJoin", function(member)
|
||||||
|
if tostring(member.guild.id) ~= tostring(id) then
|
||||||
|
return
|
||||||
|
end
|
||||||
args = {
|
args = {
|
||||||
["%$USER"] = member.id,
|
["%$USER"] = member.id,
|
||||||
["%$USERNAME"] = member.name,
|
["%$USERNAME"] = member.name,
|
||||||
["%$AGE"] = discordia.Date():toSeconds()-member.user.createdAt,
|
["%$AGE"] = member.user.createdAt,
|
||||||
["%$DISCRIM"] = member.user.discriminator,
|
["%$DISCRIM"] = member.user.discriminator,
|
||||||
["%$TAG"] = member.user.tag
|
["%$TAG"] = member.user.tag
|
||||||
}
|
}
|
||||||
|
@ -76,21 +88,24 @@ event_emitter:on("memberJoin", function(member)
|
||||||
trigger("join",{
|
trigger("join",{
|
||||||
member.id,
|
member.id,
|
||||||
member.name,
|
member.name,
|
||||||
discordia.Date():toSeconds()-member.user.createdAt
|
member.user.createdAt
|
||||||
},args)
|
},args)
|
||||||
-- @joinOnce: userid, username, age, $USER, $USERNAME, $AGE, $DISCRIM, $TAG
|
-- @joinOnce: userid, username, age, $USER, $USERNAME, $AGE, $DISCRIM, $TAG
|
||||||
triggerOnce("joinOnce",{
|
triggerOnce("joinOnce",{
|
||||||
member.id,
|
member.id,
|
||||||
member.name,
|
member.name,
|
||||||
discordia.Date():toSeconds()-member.user.createdAt
|
member.user.createdAt
|
||||||
},args)
|
},args)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
event_emitter:on("memberLeave", function(member)
|
client:on("memberLeave", function(member)
|
||||||
|
if tostring(member.guild.id) ~= tostring(id) then
|
||||||
|
return
|
||||||
|
end
|
||||||
args = {
|
args = {
|
||||||
["%$USER"] = member.id,
|
["%$USER"] = member.id,
|
||||||
["%$USERNAME"] = member.name,
|
["%$USERNAME"] = member.name,
|
||||||
["%$AGE"] = discordia.Date():toSeconds()-member.user.createdAt,
|
["%$AGE"] = member.user.createdAt,
|
||||||
["%$DISCRIM"] = member.user.discriminator,
|
["%$DISCRIM"] = member.user.discriminator,
|
||||||
["%$TAG"] = member.user.tag,
|
["%$TAG"] = member.user.tag,
|
||||||
["%$GUILDTIME"] = member.joinedAt,
|
["%$GUILDTIME"] = member.joinedAt,
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
return {
|
|
||||||
["event"] = {embed={
|
|
||||||
title = "Add a cron event",
|
|
||||||
description = "https://github.com/512mb-org/512mb.org-bot/wiki/Events-and-cronjobs",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "event ..."},
|
|
||||||
{name = "Perms:",value = "administrator"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["delay"] = {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"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["events"] = {embed={
|
|
||||||
title = "View your running events",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "events <page>"},
|
|
||||||
{name = "Perms:",value = "any"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["user-events"] = {embed={
|
|
||||||
title = "View running events of a certain user",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "user-events <user> <page>"},
|
|
||||||
{name = "Perms:",value = "administrator"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["remove-event"] = {embed={
|
|
||||||
title = "Remove an event",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "remove-event <id>"},
|
|
||||||
{name = "Perms:",value = "any"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["remove-user-event"] = {embed={
|
|
||||||
title = "Remove an event from a user",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "remove-user-event <user> <id>"},
|
|
||||||
{name = "Perms:",value = "administrator"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["date"] = "Print current date and time"
|
|
||||||
}
|
|
|
@ -4,8 +4,6 @@ local plugin = pluginc("cron")
|
||||||
local cron = import("cron")
|
local cron = import("cron")
|
||||||
local fake_message = import("fake_message")
|
local fake_message = import("fake_message")
|
||||||
local md5 = import("md5")
|
local md5 = import("md5")
|
||||||
local discordia = import("discordia")
|
|
||||||
local event_emitter = events
|
|
||||||
local events = {
|
local events = {
|
||||||
timer = {},
|
timer = {},
|
||||||
event = {}
|
event = {}
|
||||||
|
@ -15,24 +13,21 @@ local exec = function(v,command)
|
||||||
local channel = client:getChannel(v.channel)
|
local channel = client:getChannel(v.channel)
|
||||||
if not channel then
|
if not channel then
|
||||||
log("ERROR","Unable to retrieve event channel: "..tostring(v.channel))
|
log("ERROR","Unable to retrieve event channel: "..tostring(v.channel))
|
||||||
log("ERROR","Failed event: "..command)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local msg = channel:getMessage(v.id)
|
local msg = channel:getMessage(v.id)
|
||||||
if not msg then
|
if not msg then
|
||||||
log("ERROR","Unable to retrieve event message: "..tostring(v.id))
|
log("ERROR","Unable to retrieve event message: "..tostring(v.id))
|
||||||
log("ERROR","Failed event: "..command)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not msg.member then
|
if not msg.member then
|
||||||
log("ERROR","Unable to retrieve event creator: "..tostring(v.user.id))
|
log("ERROR","Unable to retrieve event creator: "..tostring(v.user.id))
|
||||||
log("ERROR","Failed event: "..command)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
command_handler:handle(fake_message(msg,{
|
command_handler:handle(fake_message(msg,{
|
||||||
delete = function() end,
|
delete = function() end,
|
||||||
content = command
|
content = command
|
||||||
}),1)
|
}))
|
||||||
end
|
end
|
||||||
|
|
||||||
if not config.events then
|
if not config.events then
|
||||||
|
@ -60,7 +55,7 @@ local create_event = function(msg,cronjob,create_entry)
|
||||||
user = tostring(msg.author.id),
|
user = tostring(msg.author.id),
|
||||||
type = functype
|
type = functype
|
||||||
}
|
}
|
||||||
if create_entry then return true,hash end
|
if create_entry then return true end
|
||||||
if not config.events.event[event_name] then config.events.event[event_name] = {} end
|
if not config.events.event[event_name] then config.events.event[event_name] = {} end
|
||||||
config.events.event[event_name][hash] = {
|
config.events.event[event_name][hash] = {
|
||||||
comm = arg,
|
comm = arg,
|
||||||
|
@ -77,7 +72,7 @@ local create_event = function(msg,cronjob,create_entry)
|
||||||
user = tostring(msg.author.id),
|
user = tostring(msg.author.id),
|
||||||
type = functype
|
type = functype
|
||||||
}
|
}
|
||||||
if create_entry then return true,hash end
|
if create_entry then return true end
|
||||||
config.events.timer[hash] = {
|
config.events.timer[hash] = {
|
||||||
comm = arg,
|
comm = arg,
|
||||||
channel = tostring(msg.channel.id),
|
channel = tostring(msg.channel.id),
|
||||||
|
@ -161,20 +156,16 @@ for k,v in pairs(config.events.timer) do
|
||||||
local status,hash = create_event(message,v.comm,true)
|
local status,hash = create_event(message,v.comm,true)
|
||||||
--orphan events with mismatching hashes
|
--orphan events with mismatching hashes
|
||||||
if status and (hash ~= k) then
|
if status and (hash ~= k) then
|
||||||
log("WARNING", "Hash mismatch, orphaning event.")
|
log("WARNING", "Hash mismatch, orpahning event.")
|
||||||
events.timer[k] = nil
|
events.timer[k] = nil
|
||||||
config.events.timer[k] = nil
|
config.events.timer[k] = nil
|
||||||
create_event(message,v.comm)
|
create_event(message,v.comm)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log("ERROR","No message with id "..v.id)
|
log("ERROR","No message with id "..v.id)
|
||||||
log("ERROR","Event id: "..k..".\nEvent description: ")
|
|
||||||
print(v.comm)
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log("ERROR","No channel with id "..v.channel)
|
log("ERROR","No channel with id "..v.channel)
|
||||||
log("ERROR","Event id: "..k..".\nEvent description: ")
|
|
||||||
print(v.comm)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -189,28 +180,35 @@ for _,evtype in pairs(config.events.event) do
|
||||||
local status,hash = create_event(message,v.comm,true)
|
local status,hash = create_event(message,v.comm,true)
|
||||||
--orphan events with mismatching hashes
|
--orphan events with mismatching hashes
|
||||||
if status and (hash ~= k) then
|
if status and (hash ~= k) then
|
||||||
log("WARNING", "Hash mismatch, orphaning event.")
|
log("WARNING", "Hash mismatch, orpahning event.")
|
||||||
events.event[_][k] = nil
|
events.event[_][k] = nil
|
||||||
config.events.event[_][k] = nil
|
config.events.event[_][k] = nil
|
||||||
create_event(message,v.comm)
|
create_event(message,v.comm)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log("ERROR","No message with id "..v.id)
|
log("ERROR","No message with id "..v.id)
|
||||||
log("ERROR","Event "..k..".\nEvent description: ")
|
|
||||||
config.events.event[_][k] = nil
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log("ERROR","No channel with id "..v.channel)
|
log("ERROR","No channel with id "..v.channel)
|
||||||
log("ERROR","Event "..k..".\nEvent description: ")
|
|
||||||
config.events.event[_][k] = nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local event = command("event",{
|
local event = command("event",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
perms = {"administrator"},
|
title = "Add a cron event",
|
||||||
args = {"string"},
|
description = "https://github.com/512mb-org/512mb.org-bot/wiki/Events-and-cronjobs",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "event ..."},
|
||||||
|
{name = "Perms:",value = "administrator"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"string"
|
||||||
|
},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
return create_event(msg,table.concat(args," "))
|
return create_event(msg,table.concat(args," "))
|
||||||
end
|
end
|
||||||
|
@ -218,7 +216,14 @@ local event = command("event",{
|
||||||
plugin:add_command(event)
|
plugin:add_command(event)
|
||||||
|
|
||||||
local delay = command("delay",{
|
local delay = command("delay",{
|
||||||
category = "Automation",
|
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"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
args = {
|
args = {
|
||||||
"string",
|
"string",
|
||||||
"string"
|
"string"
|
||||||
|
@ -233,7 +238,14 @@ local delay = command("delay",{
|
||||||
plugin:add_command(delay)
|
plugin:add_command(delay)
|
||||||
|
|
||||||
local events_comm = command("events",{
|
local events_comm = command("events",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
|
title = "View your running events",
|
||||||
|
description = "nuff said.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "events <page>"},
|
||||||
|
{name = "Perms:",value = "any"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
args[1] = tonumber(args[1]) or 1
|
args[1] = tonumber(args[1]) or 1
|
||||||
local upto = args[1]*5
|
local upto = args[1]*5
|
||||||
|
@ -242,7 +254,7 @@ local events_comm = command("events",{
|
||||||
title = "Your events: ",
|
title = "Your events: ",
|
||||||
description = "",
|
description = "",
|
||||||
footer = {
|
footer = {
|
||||||
text = "Events "..tostring(upto-4).." - "..tostring(upto).." | Total: "..tostring(#uevents)
|
text = "Events "..tostring(upto-4).." - "..tostring(upto)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
for I = upto-4,upto do
|
for I = upto-4,upto do
|
||||||
|
@ -257,9 +269,20 @@ local events_comm = command("events",{
|
||||||
plugin:add_command(events_comm)
|
plugin:add_command(events_comm)
|
||||||
|
|
||||||
local user_events_comm = command("user-events",{
|
local user_events_comm = command("user-events",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
args = {"member"},
|
title = "View running events of a certain user",
|
||||||
perms = {"administrator"},
|
description = "nuff said.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "user-events <user> <page>"},
|
||||||
|
{name = "Perms:",value = "administrator"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
args = {
|
||||||
|
"member"
|
||||||
|
},
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
args[2] = tonumber(args[2]) or 1
|
args[2] = tonumber(args[2]) or 1
|
||||||
local upto = args[2]*5
|
local upto = args[2]*5
|
||||||
|
@ -283,8 +306,17 @@ local user_events_comm = command("user-events",{
|
||||||
plugin:add_command(user_events_comm)
|
plugin:add_command(user_events_comm)
|
||||||
|
|
||||||
local remove_event= command("remove-event",{
|
local remove_event= command("remove-event",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
args = {"string"},
|
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)
|
exec = function(msg,args,opts)
|
||||||
return remove_user_event(msg.author.id,args[1])
|
return remove_user_event(msg.author.id,args[1])
|
||||||
end
|
end
|
||||||
|
@ -292,6 +324,14 @@ local remove_event= command("remove-event",{
|
||||||
plugin:add_command(remove_event)
|
plugin:add_command(remove_event)
|
||||||
|
|
||||||
local remove_user_event_c = command("remove-user-event",{
|
local remove_user_event_c = command("remove-user-event",{
|
||||||
|
help = {embed={
|
||||||
|
title = "Remove an event from a user",
|
||||||
|
description = "nuff said.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "remove-user-event <user> <id>"},
|
||||||
|
{name = "Perms:",value = "administrator"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
args = {
|
args = {
|
||||||
"member",
|
"member",
|
||||||
"string"
|
"string"
|
||||||
|
@ -299,21 +339,12 @@ local remove_user_event_c = command("remove-user-event",{
|
||||||
perms = {
|
perms = {
|
||||||
"administrator"
|
"administrator"
|
||||||
},
|
},
|
||||||
category = "Automation",
|
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
return remove_user_event(args[1].id,args[2])
|
return remove_user_event(args[1].id,args[2])
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(remove_user_event_c)
|
plugin:add_command(remove_user_event_c)
|
||||||
|
|
||||||
local date_c = command("date",{
|
|
||||||
category = "Utilities",
|
|
||||||
exec = function(msg,args,opts)
|
|
||||||
msg:reply(os.date("%d.%m.%Y %H:%M"))
|
|
||||||
end
|
|
||||||
})
|
|
||||||
plugin:add_command(date_c)
|
|
||||||
|
|
||||||
local timer = discordia.Clock()
|
local timer = discordia.Clock()
|
||||||
timer:on("min",function()
|
timer:on("min",function()
|
||||||
for k,v in pairs(events.timer) do
|
for k,v in pairs(events.timer) do
|
||||||
|
@ -329,19 +360,17 @@ timer:on("min",function()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--load events file
|
--load events file
|
||||||
local fhandler = io.open(plugin_path.."/events.lua","r")
|
local fhandler = io.open("./plugins/cron/events.lua","r")
|
||||||
local data = fhandler:read("*a")
|
local data = fhandler:read("*a")
|
||||||
fhandler:close()
|
fhandler:close()
|
||||||
local eventfunc = load(data,"event loader: "..plugin_path.."/events.lua",nil,setmetatable({
|
local eventfunc = load(data,"event loader: ./plugins/cron/events.lua",nil,setmetatable({
|
||||||
id = id,
|
id = id,
|
||||||
event_emitter = event_emitter,
|
client = client,
|
||||||
exec = exec,
|
exec = exec,
|
||||||
events = events,
|
events = events,
|
||||||
config = config,
|
config = config
|
||||||
discordia = discordia
|
|
||||||
},{__index = _G}))
|
},{__index = _G}))
|
||||||
eventfunc()
|
eventfunc()
|
||||||
timer:start(true)
|
|
||||||
|
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
timer:start(true)
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
return {
|
|
||||||
["save"] = "Force-save config data",
|
|
||||||
["error"] = "Force error",
|
|
||||||
["permerror"] = "Force permission error",
|
|
||||||
["return_error"] = "Force a return value error",
|
|
||||||
}
|
|
|
@ -1,32 +1,10 @@
|
||||||
local plugin = import("classes.plugin")("debug")
|
local plugin = import("classes.plugin")("debug")
|
||||||
local command = import("classes.command")
|
local command = import("classes.command")
|
||||||
local save = command("save",{
|
local save = command("save",{
|
||||||
|
help = "Force-save config data",
|
||||||
exec = function()
|
exec = function()
|
||||||
server:save_config()
|
server:save_config()
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(save)
|
plugin:add_command(save)
|
||||||
local err = command("error",{
|
|
||||||
exec = function()
|
|
||||||
error("Errored successfully!")
|
|
||||||
end
|
|
||||||
})
|
|
||||||
plugin:add_command(err)
|
|
||||||
local perm_error = command("permerror",{
|
|
||||||
users = {
|
|
||||||
["245973168257368076"] = -1
|
|
||||||
},
|
|
||||||
exec = function(msg)
|
|
||||||
msg:reply([[o no he's hot]])
|
|
||||||
end
|
|
||||||
})
|
|
||||||
plugin:add_command(perm_error)
|
|
||||||
local return_error = command("return_error",{
|
|
||||||
exec = function(msg)
|
|
||||||
msg:reply("nono :)")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
})
|
|
||||||
plugin:add_command(return_error)
|
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -4,110 +4,112 @@ local plugin_class = import("classes.plugin")
|
||||||
local command = import("classes.command")
|
local command = import("classes.command")
|
||||||
local plugin = plugin_class()
|
local plugin = plugin_class()
|
||||||
local settings = {
|
local settings = {
|
||||||
tapesize = 30000,
|
tapesize = 30000,
|
||||||
cellsize = 1,
|
cellsize = 1,
|
||||||
debug = true,
|
debug = true,
|
||||||
limit = 500000
|
limit = 500000
|
||||||
}
|
}
|
||||||
c_brainfuck = command("brainfuck",{
|
c_brainfuck = command("brainfuck",{
|
||||||
category = "Miscellaneous",
|
args = {
|
||||||
args = {
|
"string"
|
||||||
"string"
|
},
|
||||||
},
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
settings.load_extensions = {}
|
||||||
settings.load_extensions = {}
|
settings.path = "./lib/brainfuck/"
|
||||||
settings.path = "./lib/brainfuck/"
|
local instance = brainfuck.new(args[1],settings)
|
||||||
local instance = brainfuck.new(args[1],settings)
|
local result,opcount,err = instance:run(args[2] or "")
|
||||||
local result,opcount,err = instance:run(args[2] or "")
|
if result == "" then
|
||||||
if result == "" then
|
result = ""
|
||||||
result = ""
|
end
|
||||||
end
|
if not err then
|
||||||
if not err then
|
if opts["o"] or opts["output-only"] then
|
||||||
if opts["o"] or opts["output-only"] then
|
msg:reply(tostring(result):gsub("@","\\@"))
|
||||||
msg:reply(tostring(result):gsub("@","\\@"))
|
else
|
||||||
else
|
msg:reply({ embed = {
|
||||||
msg:reply({ embed = {
|
title = "Result:",
|
||||||
title = "Result:",
|
color = discordia.Color.fromHex("#32cd32").value,
|
||||||
color = discordia.Color.fromHex("#32cd32").value,
|
description = "```"..tostring(result):gsub("`","\\`").." ```",
|
||||||
description = "```"..tostring(result):gsub("`","\\`").." ```",
|
footer = {
|
||||||
footer = {
|
text = "Finished in "..opcount.." operations"
|
||||||
text = "Finished in "..opcount.." operations"
|
}
|
||||||
}
|
}})
|
||||||
}})
|
|
||||||
end
|
|
||||||
else
|
|
||||||
msg:reply({
|
|
||||||
embed = {
|
|
||||||
title = "Error:",
|
|
||||||
description = "```"..tostring(err).." ```",
|
|
||||||
color = discordia.Color.fromHex("#32cd32").value,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
msg:reply({
|
||||||
|
embed = {
|
||||||
|
title = "Error:",
|
||||||
|
description = "```"..tostring(err).." ```",
|
||||||
|
color = discordia.Color.fromHex("#32cd32").value,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(c_brainfuck)
|
plugin:add_command(c_brainfuck)
|
||||||
c_befunge = command("befunge",{
|
c_befunge = command("befunge",{
|
||||||
category = "Miscellaneous",
|
args = {
|
||||||
args = {
|
"string"
|
||||||
"string"
|
},
|
||||||
},
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
local code = msg.content:match("```(.+)```")
|
||||||
local code = msg.content:match("```(.+)```")
|
if not code then
|
||||||
if not code then
|
msg:reply("Invalid syntax")
|
||||||
msg:reply("Invalid syntax")
|
return
|
||||||
return
|
end
|
||||||
end
|
local input = msg.content:match("```.+``` ?(.+)") or ""
|
||||||
local input = msg.content:match("```.+``` ?(.+)") or ""
|
local stdout = ""
|
||||||
local stdout = ""
|
local stderr = ""
|
||||||
local stderr = ""
|
befunge:init(code,{
|
||||||
befunge:init(code,{
|
opcount = 10000,
|
||||||
opcount = 10000,
|
handle_int_input = function()
|
||||||
handle_int_input = function()
|
local int = input:match("^%d+")
|
||||||
local int = input:match("^%d+")
|
if not int then
|
||||||
if not int then
|
return
|
||||||
return
|
end
|
||||||
end
|
input = input:gsub("^%d+","",1)
|
||||||
input = input:gsub("^%d+","",1)
|
return tonumber(int)
|
||||||
return tonumber(int)
|
end,
|
||||||
end,
|
handle_input = function()
|
||||||
handle_input = function()
|
local char = input:sub(1,1)
|
||||||
local char = input:sub(1,1)
|
if not char then
|
||||||
if not char then
|
return
|
||||||
return
|
end
|
||||||
end
|
input = input:sub(2,-1)
|
||||||
input = input:sub(2,-1)
|
return string.byte(char)
|
||||||
return string.byte(char)
|
end,
|
||||||
end,
|
handle_output = function(char)
|
||||||
handle_output = function(char)
|
stdout = stdout..char
|
||||||
stdout = stdout..char
|
end,
|
||||||
end,
|
handle_warning = function(warn)
|
||||||
handle_warning = function(warn)
|
stderr = stderr.."[warning] "..warn.."\n"
|
||||||
stderr = stderr.."[warning] "..warn.."\n"
|
end,
|
||||||
end,
|
handle_error = function(error)
|
||||||
handle_error = function(error)
|
stderr = stderr.."[error] "..error.."\n"
|
||||||
stderr = stderr.."[error] "..error.."\n"
|
befunge.interpreter_state = false
|
||||||
befunge.interpreter_state = false
|
|
||||||
end
|
|
||||||
})
|
|
||||||
local opcount = befunge:run()
|
|
||||||
if opts["o"] or opts["output-only"] then
|
|
||||||
msg:reply(tostring(stdout):gsub("@","\\@"))
|
|
||||||
else
|
|
||||||
msg:reply({embed = {
|
|
||||||
title = "Result: ",
|
|
||||||
color = discordia.Color.fromHex("#32cd32").value,
|
|
||||||
fields = {
|
|
||||||
{name = "out",value = "```"..stdout:gsub("`","\\`").." ```"},
|
|
||||||
{name = "err",value = "```"..stderr.." ```"}
|
|
||||||
},
|
|
||||||
footer = {
|
|
||||||
text = "Finished in "..opcount.." operations"
|
|
||||||
}
|
|
||||||
}})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
})
|
||||||
|
local opcount = befunge:run()
|
||||||
|
if opts["o"] or opts["output-only"] then
|
||||||
|
msg:reply(tostring(stdout):gsub("@","\\@"))
|
||||||
|
else
|
||||||
|
msg:reply({embed = {
|
||||||
|
title = "Result: ",
|
||||||
|
color = discordia.Color.fromHex("#32cd32").value,
|
||||||
|
fields = {
|
||||||
|
{name = "out",value = "```"..stdout:gsub("`","\\`").." ```"},
|
||||||
|
{name = "err",value = "```"..stderr.." ```"}
|
||||||
|
},
|
||||||
|
footer = {
|
||||||
|
text = "Finished in "..opcount.." operations"
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(c_befunge)
|
plugin:add_command(c_befunge)
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
local helpdb = import(plugin_path:sub(3,-1).."help")
|
||||||
|
plugin:for_all_commands(function(command)
|
||||||
|
command:set_help(helpdb[command.name])
|
||||||
|
end)
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
return {
|
|
||||||
["help"] = {embed={
|
|
||||||
title = "View help embeds for commands and plugins",
|
|
||||||
description = "To specify if it's a plugin or a command, simply add the option accordingly",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "help [<command> or --plugin <plugin>]"},
|
|
||||||
{name = "Perms:",value = "any"},
|
|
||||||
{name = "Options:",value = "--plugin"}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
|
@ -1,49 +1,97 @@
|
||||||
local pluginc = import("classes.plugin")
|
local pluginc = import("classes.plugin")
|
||||||
local command = import("classes.command")
|
local command = import("classes.command")
|
||||||
local plugin = pluginc("help")
|
local plugin = pluginc("help")
|
||||||
local color = discordia.Color.fromHex
|
math.randomseed(os.time()+os.clock())
|
||||||
|
local help_message
|
||||||
|
local function randomize_stuff()
|
||||||
|
local chance = math.random(1,100)
|
||||||
|
if chance < 10 then
|
||||||
|
help_message = [[
|
||||||
|
This button here, builds Teleporters. This button, builds Dispensers.
|
||||||
|
And this little button makes them enemy sum-bitches wish they'd never been born!
|
||||||
|
|
||||||
|
--the inspiration behind this bot's design ]]
|
||||||
|
elseif chance >= 10 and chance < 90 then
|
||||||
|
help_message = [[
|
||||||
|
This plugin provides the help command, which can view help messages for plugins and commands
|
||||||
|
]]
|
||||||
|
else
|
||||||
|
help_message = [[
|
||||||
|
see the invisible
|
||||||
|
do the impossible
|
||||||
|
row row
|
||||||
|
fight da powah
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function count(tab)
|
||||||
|
local count = 0
|
||||||
|
for k,v in pairs(tab) do
|
||||||
|
count = count+1
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
local function concatenate_keys(tab)
|
||||||
|
local key_list = {}
|
||||||
|
for k,v in pairs(tab) do
|
||||||
|
table.insert(key_list,k)
|
||||||
|
end
|
||||||
|
return "``"..table.concat(key_list,"``,\n``").."``"
|
||||||
|
end
|
||||||
|
|
||||||
local help_command = command("help",{
|
local help_command = command("help",{
|
||||||
category = "Utilities",
|
help = {embed={
|
||||||
|
title = "View help embeds for commands and plugins",
|
||||||
|
description = "To specify if it's a plugin or a command, simply add the option accordingly",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "help [<command> or --plugin <plugin>]"},
|
||||||
|
{name = "Perms:",value = "any"},
|
||||||
|
{name = "Options:",value = "--plugin"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local embed = {
|
randomize_stuff()
|
||||||
color = color("32b3bc").value
|
local embed = {
|
||||||
}
|
color = discordia.Color.fromHex("32b3bc").value
|
||||||
if args[1] then
|
}
|
||||||
if not opts["plugin"] then
|
if args[1] then
|
||||||
if command_handler:get_command(args[1]) then
|
if count(opts) < 1 then
|
||||||
local command = command_handler:get_command(args[1])
|
if command_handler:get_command(args[1]) then
|
||||||
embed = command:get_help().embed
|
local command = command_handler:get_command(args[1])
|
||||||
else
|
embed = command:get_help().embed
|
||||||
embed.description = "No such command: "..args[1]
|
else
|
||||||
embed.color = color("990000").value
|
embed.description = "No such command"
|
||||||
end
|
end
|
||||||
else
|
elseif (opts["plugin"]) then
|
||||||
local meta = command_handler:get_metadata()
|
--[[ if plugin_data["plugins"] [args[1] ] then
|
||||||
local comms = meta.plugins[args[1]]
|
embed.title = "Plugin ``"..args[1].."``:"
|
||||||
if not comms then
|
embed.description = plugin_data["plugins"] [args[1] ]["_help"]
|
||||||
embed.description = "Unable to find plugin: "..args[1]
|
embed.fields = {{
|
||||||
embed.color = color("990000").value
|
name = "Commands:",
|
||||||
else
|
value ="``"..table.concat(plugin_data["plugins"] [args[1] ],"``,\n``").."``"
|
||||||
embed.title = "Plugin ``"..args[1].."``"
|
}}
|
||||||
embed.description = "``"..table.concat(comms,"``, ``").."``"
|
else
|
||||||
end
|
embed.description = "No such plugin"
|
||||||
end
|
end
|
||||||
else
|
--]]
|
||||||
local meta = command_handler:get_metadata()
|
embed.title = "Not yet implemented"
|
||||||
embed.title = "512mb.org commands:"
|
embed.description = "Check again later"
|
||||||
embed.description = "use ``help <command>`` to view help messages. (type ``help help`` for more info)"
|
|
||||||
embed.fields = {}
|
|
||||||
for name,category in pairs(meta.categories) do
|
|
||||||
table.insert(embed.fields,{
|
|
||||||
name = name,
|
|
||||||
value = "``"..table.concat(category,"``, ``").."``"
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
msg:reply({embed = embed})
|
else
|
||||||
|
embed.title = "512mb.org commands:"
|
||||||
|
embed.description = "use ``help <command>`` to view help messages. (type ``help help`` for more info)"
|
||||||
|
embed.fields = {}
|
||||||
|
for k,v in pairs(command_handler:get_commands_metadata().plugins) do
|
||||||
|
table.insert(embed.fields,{
|
||||||
|
name = k,
|
||||||
|
value = "``"..table.concat(v,"``, ``").."``"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
msg:reply({embed = embed})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(help_command)
|
plugin:add_command(help_command)
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
return {
|
return {
|
||||||
["prefix"] = {embed={
|
["prefix"] = {embed={
|
||||||
title = "Add/delete/list prefixes",
|
title = "Set or view current prefix for this bot",
|
||||||
description = "Multiple prefixes are possible",
|
description = "If you're not sure what's the current prefix, just ping the bot",
|
||||||
fields = {
|
fields = {
|
||||||
{name = "Usage:",value = "prefix [(add | remove | list (default)) [<new prefix>]]"},
|
{name = "Usage:",value = "prefix [<new prefix> or \"<new prefix>\"]"},
|
||||||
{name = "Perms:",value = "Administrator"},
|
{name = "Perms:",value = "Administrator"},
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
@ -16,10 +16,9 @@ return {
|
||||||
``alias !hi "!speak Hello!"`` - reply to !hi with "Hello!" using speak command
|
``alias !hi "!speak Hello!"`` - reply to !hi with "Hello!" using speak command
|
||||||
``alias !say "!speak ..."`` - reply to !hi with everything typed after !hi
|
``alias !say "!speak ..."`` - reply to !hi with everything typed after !hi
|
||||||
``alias !say "!speak $1"`` - reply to !hi with the first argument sent along with !hi
|
``alias !say "!speak $1"`` - reply to !hi with the first argument sent along with !hi
|
||||||
More at https://github.com/512mb-xyz/512mb.org-bot/wiki/Aliases]]
|
More at https://github.com/yessiest/SuppaBot/wiki/Tasks]]
|
||||||
},
|
},
|
||||||
{name = "Perms: ",value = "Administrator (doesn't apply to created aliases)"},
|
{name = "Perms: ",value = "Administrator (doesn't apply to created aliases)"}
|
||||||
{name = "Opts: ",value = "`-p` - bind the command to not use a prefix\n`--description=\"your description here\"` - add a description to alias"}
|
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
["unalias"] = {embed = {
|
["unalias"] = {embed = {
|
||||||
|
|
|
@ -4,14 +4,13 @@ local last_message_arrived = discordia.Stopwatch()
|
||||||
local unixToString = import("unixToString")
|
local unixToString = import("unixToString")
|
||||||
local command = import("classes.command")
|
local command = import("classes.command")
|
||||||
local plugin = import("classes.plugin")("meta")
|
local plugin = import("classes.plugin")("meta")
|
||||||
local purify = import("purify")
|
|
||||||
if not config.aliases then
|
if not config.aliases then
|
||||||
config.aliases = {}
|
config.aliases = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
client:on("messageCreate",function(msg)
|
client:on("messageCreate",function(msg)
|
||||||
last_message_arrived:reset()
|
last_message_arrived:reset()
|
||||||
last_message_arrived:start()
|
last_message_arrived:start()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local prefix
|
local prefix
|
||||||
|
@ -22,257 +21,268 @@ for k,v in pairs(command_handler:get_prefixes()) do
|
||||||
end
|
end
|
||||||
|
|
||||||
local function add_alias(name,comm,prefix,description)
|
local function add_alias(name,comm,prefix,description)
|
||||||
if (not aliases[name]) then
|
if (not aliases[name]) then
|
||||||
log("ALIAS","Adding alias \""..name.."\" for \""..comm.."\"")
|
print("[ALIAS] Adding alias \""..name.."\" for \""..comm.."\"")
|
||||||
config.aliases[name] = {comm = comm,prefix = (prefix == nil)}
|
config.aliases[name] = {comm = comm,prefix = prefix}
|
||||||
aliases[name] = command(name,{
|
aliases[name] = command(name,{
|
||||||
help = "Alias for ``"..comm.."``",
|
help = "Alias for ``"..comm.."``",
|
||||||
usage = ((prefix and globals.prefix) or "")..name,
|
usage = ((prefix and globals.prefix) or "")..name,
|
||||||
category = "Aliases",
|
exec = function(msg,args2,opts)
|
||||||
exec = function(msg,args2,opts)
|
print("[ALIAS] Triggerting alias "..tostring(comm).." with args \""..tostring(msg.content).."\"")
|
||||||
local str = msg.content:gsub("^%S+ ?","")
|
local str = msg.content:gsub("^%S+ ?","")
|
||||||
aftersub = comm:gsub("%.%.%.",str or "")
|
aftersub = comm:gsub("%.%.%.",str or "")
|
||||||
local status,args = require("air").parse(str)
|
aftersub = aftersub:gsub("%$prefix",prefix or "&")
|
||||||
for k,v in pairs(args) do
|
local status,args = require("air").parse(str)
|
||||||
aftersub = aftersub:gsub("([^\\])%$"..k,"%1"..v)
|
for k,v in pairs(args) do
|
||||||
end
|
aftersub = aftersub:gsub("([^\\])%$"..k,"%1"..v)
|
||||||
log("ALIAS", "Triggering alias "..name.." with args \""..aftersub.."\"")
|
end
|
||||||
command_handler:handle(fake_message(msg,{
|
command_handler:handle(fake_message(msg,{
|
||||||
content = aftersub
|
content = aftersub
|
||||||
}))
|
}))
|
||||||
end,
|
end,
|
||||||
options = {
|
options = {
|
||||||
prefix = (prefix == nil),
|
prefix = prefix,
|
||||||
custom = true
|
custom = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
plugin:add_command(aliases[name])
|
plugin:add_command(aliases[name])
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function remove_alias(name)
|
local function remove_alias(name)
|
||||||
if config.aliases[name] then
|
if config.aliases[name] then
|
||||||
config.aliases[name] = nil
|
config.aliases[name] = nil
|
||||||
plugin:remove_command(aliases[name])
|
plugin:remove_command(aliases[name])
|
||||||
aliases[name] = nil
|
aliases[name] = nil
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function purify_strings(msg,input)
|
||||||
|
local text = input
|
||||||
|
while text:match("<@(%D*)(%d*)>") do
|
||||||
|
local obj,id = text:match("<@(%D*)(%d*)>")
|
||||||
|
local substitution = ""
|
||||||
|
if obj:match("!") then
|
||||||
|
local member = msg.guild:getMember(id)
|
||||||
|
if member then
|
||||||
|
substitution = "@"..member.name
|
||||||
|
end
|
||||||
|
elseif obj:match("&") then
|
||||||
|
local role = msg.guild:getRole(id)
|
||||||
|
if role then
|
||||||
|
substitution = "@"..role.name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
if substitution == "" then
|
||||||
|
substitution = "<\\@"..obj..id..">"
|
||||||
|
end
|
||||||
|
text = text:gsub("<@(%D*)"..id..">",substitution)
|
||||||
|
end
|
||||||
|
text = text:gsub("@everyone","")
|
||||||
|
text = text:gsub("@here","")
|
||||||
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
for k,v in pairs(config.aliases) do
|
for k,v in pairs(config.aliases) do
|
||||||
commdata = v
|
commdata = v
|
||||||
if type(v) == "string" then --legacy format conversion
|
if type(v) == "string" then --legacy format conversion
|
||||||
commdata = {comm = v, prefix = false}
|
commdata = {comm = v, prefix = false}
|
||||||
end
|
end
|
||||||
add_alias(k,commdata.comm,commdata.prefix)
|
add_alias(k,commdata.comm,commdata.prefix)
|
||||||
end
|
end
|
||||||
|
|
||||||
local prefix = command("prefix",{
|
local prefix = command("prefix",{
|
||||||
perms = {
|
help = "Set prefix",
|
||||||
"administrator"
|
usage = "prefix [(add | remove | list (default)) [<new prefix>]]",
|
||||||
},
|
users = {
|
||||||
category = "Utilities",
|
[client.owner.id] = 1
|
||||||
exec = function(msg,args,opts)
|
},
|
||||||
local function list_prefixes(msg)
|
roles = {
|
||||||
local prefixes = ""
|
["747042157185073182"] = 1
|
||||||
for k,v in pairs(command_handler:get_prefixes()) do
|
},
|
||||||
prefixes = prefixes.."``"..v:gsub("`","\\`").."``".."\n"
|
perms = {
|
||||||
end
|
"administrator"
|
||||||
msg:reply({embed = {
|
},
|
||||||
title = "Prefixes for this server",
|
exec = function(msg,args,opts)
|
||||||
description = prefixes
|
local function list_prefixes(msg)
|
||||||
}})
|
local prefixes = ""
|
||||||
end
|
for k,v in pairs(command_handler:get_prefixes()) do
|
||||||
if args[1] then
|
prefixes = prefixes..v.."\n"
|
||||||
if args[1] == "add" and args[2] then
|
end
|
||||||
command_handler:add_prefix(args[2])
|
msg:reply({embed = {
|
||||||
msg:reply("Added ``"..args[2]:gsub("`","\\`").."`` as a prefix")
|
title = "Prefixes for this server",
|
||||||
elseif args[1] == "remove" and args[2] then
|
description = prefixes
|
||||||
local status,err = command_handler:remove_prefix(args[2])
|
}})
|
||||||
if status then
|
|
||||||
msg:reply("Removed the ``"..args[2]:gsub("`","\\`").."`` prefix")
|
|
||||||
else
|
|
||||||
msg:reply(err)
|
|
||||||
end
|
|
||||||
elseif args[1] == "list" then
|
|
||||||
list_prefixes(msg)
|
|
||||||
else
|
|
||||||
msg:reply("Syntax error")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
list_prefixes(msg)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
if args[1] then
|
||||||
|
if args[1] == "add" and args[2] then
|
||||||
|
command_handler:add_prefix(args[2])
|
||||||
|
msg:reply("Added "..args[2].." as a prefix")
|
||||||
|
elseif args[1] == "remove" and args[2] then
|
||||||
|
local status,err = command_handler:remove_prefix(args[2])
|
||||||
|
if status then
|
||||||
|
msg:reply("Removed the "..args[2].." prefix")
|
||||||
|
else
|
||||||
|
msg:reply(err)
|
||||||
|
end
|
||||||
|
elseif args[1] == "list" then
|
||||||
|
list_prefixes(msg)
|
||||||
|
else
|
||||||
|
msg:reply("Syntax error")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
list_prefixes(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(prefix)
|
plugin:add_command(prefix)
|
||||||
|
|
||||||
local c_alias = command("alias", {
|
local c_alias = command("alias", {
|
||||||
args = {
|
args = {
|
||||||
"string","string"
|
"string","string"
|
||||||
},
|
},
|
||||||
perms = {
|
perms = {
|
||||||
"administrator"
|
"administrator"
|
||||||
},
|
},
|
||||||
category = "Automation",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
if add_alias(args[1],args[2],(opts["prefix"] or opts["p"]),opts["description"]) then
|
||||||
if add_alias(args[1],args[2],(opts["prefix"] or opts["p"]),opts["description"]) then
|
msg:reply("Bound ``"..args[1].."`` as an alias to ``"..args[2].."``")
|
||||||
msg:reply("Bound ``"..args[1].."`` as an alias to ``"..args[2].."``")
|
else
|
||||||
else
|
msg:reply("``"..args[1].."`` is already bound")
|
||||||
msg:reply("``"..args[1].."`` is already bound")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(c_alias)
|
plugin:add_command(c_alias)
|
||||||
|
|
||||||
local c_unalias = command("unalias", {
|
local c_unalias = command("unalias", {
|
||||||
args = {
|
args = {
|
||||||
"string"
|
"string"
|
||||||
},
|
},
|
||||||
perms = {
|
perms = {
|
||||||
"administrator"
|
"administrator"
|
||||||
},
|
},
|
||||||
category = "Automation",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
if remove_alias(args[1]) then
|
||||||
if remove_alias(args[1]) then
|
msg:reply("Removed the ``"..args[1].."`` alias")
|
||||||
msg:reply("Removed the ``"..args[1].."`` alias")
|
else
|
||||||
else
|
msg:reply("No such alias")
|
||||||
msg:reply("No such alias")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(c_unalias)
|
plugin:add_command(c_unalias)
|
||||||
|
|
||||||
local c_aliases = command("aliases", {
|
local c_aliases = command("aliases", {
|
||||||
category = "Automation",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
msg:reply({embed = {
|
||||||
local page = (tonumber(args[1]) or 1)*5
|
title = "Aliases for this server",
|
||||||
local events = (function()
|
fields = (function()
|
||||||
local fields = {}
|
local fields = {}
|
||||||
for k,v in pairs(config.aliases) do
|
for k,v in pairs(config.aliases) do
|
||||||
table.insert(fields,{k,v})
|
table.insert(fields,{name = ((v["prefix"] and prefix) or "")..k,value = v["comm"]})
|
||||||
end
|
end
|
||||||
return fields
|
return fields
|
||||||
end)()
|
end)()
|
||||||
msg:reply({embed = {
|
}})
|
||||||
title = "Aliases for this server",
|
end
|
||||||
fields = (function()
|
|
||||||
local fields = {}
|
|
||||||
for i = page-4,page do
|
|
||||||
if not events[i] then break end
|
|
||||||
table.insert(fields,{
|
|
||||||
name = events[i][1],
|
|
||||||
value = events[i][2].comm
|
|
||||||
})
|
|
||||||
end
|
|
||||||
return fields
|
|
||||||
end)(),
|
|
||||||
footer = {
|
|
||||||
text = "Aliases "..tostring(page-4).." - "..tostring(page).." | Total: "..tostring(#events)
|
|
||||||
}
|
|
||||||
}})
|
|
||||||
end
|
|
||||||
})
|
})
|
||||||
plugin:add_command(c_aliases)
|
plugin:add_command(c_aliases)
|
||||||
|
|
||||||
local c_ping = command("ping", {
|
local c_ping = command("ping", {
|
||||||
category = "Utilities",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
local before = msg:getDate()
|
||||||
local before = msg:getDate()
|
local reply = msg:reply("Pong!")
|
||||||
local reply = msg:reply("Pong!")
|
if not reply then
|
||||||
if not reply then
|
log("ERROR","Couldn't send the ping reply for some reason")
|
||||||
log("ERROR","Couldn't send the ping reply for some reason")
|
return
|
||||||
return
|
|
||||||
end
|
|
||||||
local after = reply:getDate()
|
|
||||||
local latency = (after:toMilliseconds() - before:toMilliseconds())
|
|
||||||
last_message_arrived:stop()
|
|
||||||
local uptime = discordia.Date():toSeconds() - server.uptime:toSeconds()
|
|
||||||
local processing = (last_message_arrived:getTime():toMilliseconds())
|
|
||||||
msg:reply({embed = {
|
|
||||||
title = "Stats:",
|
|
||||||
fields = {
|
|
||||||
{name = "Latency",value = tostring(math.floor(latency)).."ms"},
|
|
||||||
{name = "Processing time",value = tostring(math.floor(processing)).."ms"},
|
|
||||||
{name = "Uptime",value = tostring(unixToString(uptime))}
|
|
||||||
}
|
|
||||||
}})
|
|
||||||
end
|
end
|
||||||
|
local after = reply:getDate()
|
||||||
|
local latency = (after:toMilliseconds() - before:toMilliseconds())
|
||||||
|
last_message_arrived:stop()
|
||||||
|
local uptime = discordia.Date():toSeconds() - server.uptime:toSeconds()
|
||||||
|
local processing = (last_message_arrived:getTime():toMilliseconds())
|
||||||
|
msg:reply({embed = {
|
||||||
|
title = "Stats:",
|
||||||
|
fields = {
|
||||||
|
{name = "Latency",value = tostring(math.floor(latency)).."ms"},
|
||||||
|
{name = "Processing time",value = tostring(math.floor(processing)).."ms"},
|
||||||
|
{name = "Uptime",value = tostring(unixToString(uptime))}
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(c_ping)
|
plugin:add_command(c_ping)
|
||||||
|
|
||||||
local c_about = command("about", {
|
local c_about = command("about", {
|
||||||
category = "Miscellaneous",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
|
||||||
local rand = math.random
|
local rand = math.random
|
||||||
local author = client:getUser("245973168257368076")
|
local author = client:getUser("245973168257368076")
|
||||||
msg:reply({embed = {
|
msg:reply({embed = {
|
||||||
title = "About 512mb.org bot",
|
title = "About 512mb.org bot",
|
||||||
thumbnail = {
|
thumbnail = {
|
||||||
url = client.user:getAvatarURL()
|
url = client.user:getAvatarURL()
|
||||||
},
|
},
|
||||||
color = discordia.Color.fromRGB(rand(50,200),rand(50,200),rand(50,200)).value,
|
color = discordia.Color.fromRGB(rand(50,200),rand(50,200),rand(50,200)).value,
|
||||||
description = "512mb.org is an open-source bot written in Lua. It is based on a beta rewrite version of the Suppa-Bot.",
|
description = "512mb.org is an open-source bot written in Lua. It is based on a beta rewrite version of the Suppa-Bot.",
|
||||||
fields = {
|
fields = {
|
||||||
{name = "Source Code: ",value = "https://github.com/512mb-xyz/512mb.org-bot"},
|
{name = "Source Code: ",value = "https://github.com/512mb-xyz/512mb.org-bot"},
|
||||||
{name = "Author: ",value = author.tag},
|
{name = "Author: ",value = author.tag},
|
||||||
{name = "Invite: ",value = "Not available yet"}
|
{name = "Invite: ",value = "Not available yet"}
|
||||||
},
|
},
|
||||||
footer = {
|
footer = {
|
||||||
text = "For any information regarding the bot, contact yessiest on 512mb.org discord."
|
text = "For any information regarding the bot, contact yessiest on 512mb.org discord."
|
||||||
}
|
}
|
||||||
}})
|
}})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(c_about)
|
plugin:add_command(c_about)
|
||||||
|
|
||||||
local c_server = command("server", {
|
local c_server = command("server", {
|
||||||
category = "Utilities",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
|
||||||
msg:reply({embed = {
|
msg:reply({embed = {
|
||||||
thumbnail = {
|
thumbnail = {
|
||||||
url = msg.guild.iconURL
|
url = msg.guild.iconURL
|
||||||
},
|
},
|
||||||
title = msg.guild.name,
|
title = msg.guild.name,
|
||||||
description = msg.guild.description,
|
description = msg.guild.description,
|
||||||
fields = {
|
fields = {
|
||||||
{name = "Members",value = msg.guild.totalMemberCount},
|
{name = "Members",value = msg.guild.totalMemberCount},
|
||||||
{name = "Owner",value = (msg.guild.owner and msg.guild.owner.user.tag..":"..msg.guild.owner.user.id) or msg.guild.ownerId},
|
{name = "Owner",value = (msg.guild.owner and msg.guild.owner.user.tag..":"..msg.guild.owner.user.id) or msg.guild.ownerId},
|
||||||
{name = "Created At",value = os.date("!%c",msg.guild.createdAt).." (UTC+0)"},
|
{name = "Created At",value = os.date("!%c",msg.guild.createdAt).." (UTC+0)"},
|
||||||
{name = "Text Channels",value = msg.guild.textChannels:count()},
|
{name = "Text Channels",value = msg.guild.textChannels:count()},
|
||||||
{name = "Voice Channels",value = msg.guild.voiceChannels:count()}
|
{name = "Voice Channels",value = msg.guild.voiceChannels:count()}
|
||||||
}
|
}
|
||||||
}})
|
}})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(c_server)
|
plugin:add_command(c_server)
|
||||||
|
|
||||||
local c_user = command("user", {
|
local c_user = command("user", {
|
||||||
category = "Utilities",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
|
||||||
local member = msg.guild:getMember((args[1] or ""):match("%d+")) or msg.guild:getMember(msg.author.id)
|
local member = msg.guild:getMember((args[1] or ""):match("%d+")) or msg.guild:getMember(msg.author.id)
|
||||||
local roles = ""
|
local roles = ""
|
||||||
for k,v in pairs(member.roles) do
|
for k,v in pairs(member.roles) do
|
||||||
roles = roles..v.mentionString.."\n"
|
roles = roles..v.mentionString.."\n"
|
||||||
end
|
end
|
||||||
msg:reply({embed = {
|
msg:reply({embed = {
|
||||||
title = member.user.tag..":"..member.user.id,
|
title = member.user.tag..":"..member.user.id,
|
||||||
thumbnail = {
|
thumbnail = {
|
||||||
url = member.user:getAvatarURL()
|
url = member.user:getAvatarURL()
|
||||||
},
|
},
|
||||||
fields = {
|
fields = {
|
||||||
{name = "Profile Created At",value = os.date("!%c",member.user.createdAt).." (UTC+0)"},
|
{name = "Profile Created At",value = os.date("!%c",member.user.createdAt).." (UTC+0)"},
|
||||||
{name = "Joined At",value = os.date("!%c",discordia.Date.fromISO(member.joinedAt):toSeconds()).." (UTC+0)",inline = true},
|
{name = "Joined At",value = os.date("!%c",discordia.Date.fromISO(member.joinedAt):toSeconds()).." (UTC+0)",inline = true},
|
||||||
{name = "Boosting",value = ((member.premiumSince and "Since "..member.premiumSince) or "No"),inline = true},
|
{name = "Boosting",value = ((member.premiumSince and "Since "..member.premiumSince) or "No"),inline = true},
|
||||||
{name = "Highest Role",value = member.highestRole.mentionString,inline = true},
|
{name = "Highest Role",value = member.highestRole.mentionString,inline = true},
|
||||||
{name = "Roles",value = roles,inline = true}
|
{name = "Roles",value = roles,inline = true}
|
||||||
}
|
}
|
||||||
}})
|
}})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(c_user)
|
plugin:add_command(c_user)
|
||||||
|
|
||||||
|
@ -280,9 +290,11 @@ local c_speak = command("speak", {
|
||||||
args = {
|
args = {
|
||||||
"string"
|
"string"
|
||||||
},
|
},
|
||||||
category = "Utilities",
|
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local text = purify.purify_pings(msg, table.concat(args," "))
|
local text = purify_strings(msg, table.concat(args," "))
|
||||||
|
if opts["unescape"] or opts["u"] then
|
||||||
|
text = text:gsub("\\","")
|
||||||
|
end
|
||||||
msg:reply(text)
|
msg:reply(text)
|
||||||
msg:delete()
|
msg:delete()
|
||||||
end,
|
end,
|
||||||
|
@ -290,83 +302,62 @@ local c_speak = command("speak", {
|
||||||
plugin:add_command(c_speak)
|
plugin:add_command(c_speak)
|
||||||
|
|
||||||
local c_adminSpeak = command("adminSpeak", {
|
local c_adminSpeak = command("adminSpeak", {
|
||||||
category = "Utilities",
|
args = {
|
||||||
args = {
|
"string"
|
||||||
"string"
|
},
|
||||||
},
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
local text = table.concat(args," ")
|
||||||
local text = table.concat(args," ")
|
if opts["unescape"] or opts["u"] then
|
||||||
msg:reply(text)
|
text = text:gsub("\\","")
|
||||||
msg:delete()
|
end
|
||||||
end,
|
msg:reply(text)
|
||||||
perms = {
|
msg:delete()
|
||||||
"mentionEveryone"
|
end,
|
||||||
}
|
perms = {
|
||||||
|
"mentionEveryone"
|
||||||
|
}
|
||||||
})
|
})
|
||||||
plugin:add_command(c_adminSpeak)
|
plugin:add_command(c_adminSpeak)
|
||||||
|
|
||||||
local c_adminSendToChannel = command("adminSendToChannel", {
|
|
||||||
category = "Utilities",
|
|
||||||
args = {
|
|
||||||
"textChannel",
|
|
||||||
"string"
|
|
||||||
},
|
|
||||||
exec = function(msg,args,opts)
|
|
||||||
local channel = args[1]
|
|
||||||
table.remove(args,1)
|
|
||||||
local text = table.concat(args," ")
|
|
||||||
channel:send(text)
|
|
||||||
end,
|
|
||||||
perms = {
|
|
||||||
"mentionEveryone"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
plugin:add_command(c_adminSendToChannel)
|
|
||||||
|
|
||||||
local c_echo = command("echo",{
|
local c_echo = command("echo",{
|
||||||
category = "Utilities",
|
|
||||||
args = {
|
args = {
|
||||||
"string"
|
"string"
|
||||||
},
|
},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local text = purify.purify_pings(msg, table.concat(args," "))
|
local text = purify_strings(msg, table.concat(args," "))
|
||||||
|
if opts["unescape"] or opts["u"] then
|
||||||
|
text = text:gsub("\\","")
|
||||||
|
end
|
||||||
msg:reply(text)
|
msg:reply(text)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(c_echo)
|
plugin:add_command(c_echo)
|
||||||
|
|
||||||
local c_sendToChannel = command("sendToChannel",{
|
|
||||||
category = "Utilities",
|
|
||||||
args = {
|
|
||||||
"textChannel",
|
|
||||||
"string"
|
|
||||||
},
|
|
||||||
exec = function(msg,args,opts)
|
|
||||||
local channel = args[1]
|
|
||||||
table.remove(args,1)
|
|
||||||
local text = purify.purify_pings(msg, table.concat(args," "))
|
|
||||||
channel:send(text)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
plugin:add_command(c_sendToChannel)
|
|
||||||
|
|
||||||
local c_pingself = command("pingself",{
|
local c_pingself = command("pingself",{
|
||||||
category = "Utilities",
|
|
||||||
args = {
|
args = {
|
||||||
"string"
|
"string"
|
||||||
},
|
},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local text = purify.purify_pings(msg, table.concat(args," "))
|
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)
|
msg:reply("<@"..tostring(msg.member.id).."> "..text)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(c_pingself)
|
plugin:add_command(c_pingself)
|
||||||
|
|
||||||
plugin.removal_callback = function()
|
plugin.removal_callback = function()
|
||||||
for k,v in pairs(config.aliases) do
|
for k,v in pairs(config.aliases) do
|
||||||
remove_alias(k)
|
remove_alias(k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
local helpdb = import(plugin_path:sub(3,-1).."help")
|
||||||
|
plugin:for_all_commands(function(command)
|
||||||
|
if helpdb[command.name] then
|
||||||
|
command:set_help(helpdb[command.name])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
local discordia = require('discordia')
|
|
||||||
return {
|
|
||||||
["enable"] = {embed = {
|
|
||||||
title = "Enable plugin",
|
|
||||||
description = [[This command loads a plugin,
|
|
||||||
addng its commands to the command pool]],
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "load <plugin-name>"},
|
|
||||||
{name = "Perms:",value = "Administrator, other (via ``rules --allow``)"}
|
|
||||||
},
|
|
||||||
color = discordia.Color.fromHex("ff5100").value
|
|
||||||
}},
|
|
||||||
["disable"] = {embed = {
|
|
||||||
title = "Disable a loaded plugin",
|
|
||||||
description = [[This commands unloads a previously loaded plugin,
|
|
||||||
removing its commands from the command pool]],
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "unload <plugin-name>"},
|
|
||||||
{name = "Perms:",value = "Administrator, other (via ``rules --allow``)"}
|
|
||||||
},
|
|
||||||
color = discordia.Color.fromHex("ff5100").value
|
|
||||||
}},
|
|
||||||
["plugins"] = {embed = {
|
|
||||||
title = "View all known plugins",
|
|
||||||
description = [[This commmand prints info on loaded and unloaded plugins]],
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "plugins"},
|
|
||||||
{name = "Perms:",value = "Administrator, other (via ``rules --allow``)"}
|
|
||||||
},
|
|
||||||
color = discordia.Color.fromHex("ff5100").value
|
|
||||||
}},
|
|
||||||
}
|
|
|
@ -4,83 +4,107 @@ local plugin = plugin_c("pluginmanager")
|
||||||
local utilities = require("table-utils")
|
local utilities = require("table-utils")
|
||||||
|
|
||||||
local generic_admin_template = {
|
local generic_admin_template = {
|
||||||
args = {"string"},
|
args = {"string"},
|
||||||
perms = {
|
perms = {
|
||||||
"administrator"
|
"administrator"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local enable = command("enable",utilities.overwrite(generic_admin_template,{
|
local enable = command("enable",utilities.overwrite(generic_admin_template,{
|
||||||
category = "Utilities",
|
help = {embed = {
|
||||||
|
title = "Enable plugin",
|
||||||
|
description = [[This command loads a plugin,
|
||||||
|
adding its commands to the command pool]],
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "load <plugin-name>"},
|
||||||
|
{name = "Perms:",value = "Administrator, other (via ``rules --allow``)"}
|
||||||
|
},
|
||||||
|
color = discordia.Color.fromHex("ff5100").value
|
||||||
|
}},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local status,message = plugin_handler:load(args[1])
|
local status,message = plugin_handler:load(args[1])
|
||||||
local plugin_data = command_handler:get_metadata().plugins
|
local plugin_data = command_handler:get_commands_metadata().plugins
|
||||||
local embed = {
|
local embed = {
|
||||||
description = message,
|
description = message,
|
||||||
color = discordia.Color.fromHex("ff5100").value,
|
color = discordia.Color.fromHex("ff5100").value,
|
||||||
|
}
|
||||||
|
if status then
|
||||||
|
embed.fields = {
|
||||||
|
{name = "New commands:",value =
|
||||||
|
table.concat(plugin_data[args[1]] or {},", ").." "
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if status then
|
end
|
||||||
embed.fields = {
|
msg:reply({embed = embed})
|
||||||
{name = "New commands:",value =
|
|
||||||
table.concat(plugin_data[args[1]] or {},", ").." "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
msg:reply({embed = embed})
|
|
||||||
end
|
end
|
||||||
}))
|
}))
|
||||||
plugin:add_command(enable)
|
plugin:add_command(enable)
|
||||||
local disable = command("disable",utilities.overwrite(generic_admin_template,{
|
local disable = command("disable",utilities.overwrite(generic_admin_template,{
|
||||||
category = "Utilities",
|
help = {embed = {
|
||||||
|
title = "Disable a loaded plugin",
|
||||||
|
description = [[This commands unloads a previously loaded plugin,
|
||||||
|
removing its commands from the command pool]],
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "unload <plugin-name>"},
|
||||||
|
{name = "Perms:",value = "Administrator, other (via ``rules --allow``)"}
|
||||||
|
},
|
||||||
|
color = discordia.Color.fromHex("ff5100").value
|
||||||
|
}},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local plugin_data = command_handler:get_metadata().plugins
|
local plugin_data = command_handler:get_commands_metadata().plugins
|
||||||
if not (args[1] == "plugins") then
|
if not (args[1] == "plugins") then
|
||||||
local status,message = plugin_handler:unload(args[1])
|
local status,message = plugin_handler:unload(args[1])
|
||||||
local embed = {
|
local embed = {
|
||||||
description = message,
|
description = message,
|
||||||
color = discordia.Color.fromHex("ff5100").value,
|
color = discordia.Color.fromHex("ff5100").value,
|
||||||
|
}
|
||||||
|
if status then
|
||||||
|
embed.fields = {
|
||||||
|
{name = "Removed commands:",value =
|
||||||
|
table.concat(plugin_data[args[1]] or {},", ").." "
|
||||||
}
|
}
|
||||||
if status then
|
}
|
||||||
embed.fields = {
|
|
||||||
{name = "Removed commands:",value =
|
|
||||||
table.concat(plugin_data[args[1]] or {},", ").." "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
msg:reply({embed = embed})
|
|
||||||
else
|
|
||||||
msg:reply("TIME PARADOX")
|
|
||||||
end
|
end
|
||||||
|
msg:reply({embed = embed})
|
||||||
|
else
|
||||||
|
msg:reply("TIME PARADOX")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
}))
|
}))
|
||||||
plugin:add_command(disable)
|
plugin:add_command(disable)
|
||||||
local plugins = command("plugins",utilities.overwrite(generic_admin_template,{
|
local plugins = command("plugins",utilities.overwrite(generic_admin_template,{
|
||||||
category = "Utilities",
|
help = {embed = {
|
||||||
args = {},
|
title = "View all known plugins",
|
||||||
exec = function(msg,args,opts)
|
description = [[This commmand prints info on loaded and unloaded plugins]],
|
||||||
local all_plugins = plugin_handler:list_loadable()
|
fields = {
|
||||||
local unloaded_plugins = {}
|
{name = "Usage:",value = "plugins"},
|
||||||
local loaded_plugins = {}
|
{name = "Perms:",value = "Administrator, other (via ``rules --allow``)"}
|
||||||
for k,v in pairs(all_plugins) do
|
}
|
||||||
if not v.loaded then
|
}},
|
||||||
table.insert(unloaded_plugins,k)
|
args = {},
|
||||||
else
|
exec = function(msg,args,opts)
|
||||||
table.insert(loaded_plugins,k)
|
local all_plugins = plugin_handler:list_loadable()
|
||||||
end
|
local unloaded_plugins = {}
|
||||||
end
|
local loaded_plugins = {}
|
||||||
if #unloaded_plugins == 0 then
|
for k,v in pairs(all_plugins) do
|
||||||
table.insert(unloaded_plugins," ")
|
if not v.loaded then
|
||||||
end
|
table.insert(unloaded_plugins,k)
|
||||||
msg:reply({embed={
|
else
|
||||||
color = discordia.Color.fromHex("ff5100").value,
|
table.insert(loaded_plugins,k)
|
||||||
fields = {
|
|
||||||
{name = "Loaded plugins",value = "``"..table.concat(loaded_plugins,"``,\n``").."``"},
|
|
||||||
{name = "Unloaded plugins",value = "``"..table.concat(unloaded_plugins,"``,\n``").."``"}
|
|
||||||
}
|
|
||||||
}})
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
if #unloaded_plugins == 0 then
|
||||||
|
table.insert(unloaded_plugins," ")
|
||||||
|
end
|
||||||
|
msg:reply({embed={
|
||||||
|
color = discordia.Color.fromHex("ff5100").value,
|
||||||
|
fields = {
|
||||||
|
{name = "Loaded plugins",value = "``"..table.concat(loaded_plugins,"``,\n``").."``"},
|
||||||
|
{name = "Unloaded plugins",value = "``"..table.concat(unloaded_plugins,"``,\n``").."``"}
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
end
|
||||||
}))
|
}))
|
||||||
plugin:add_command(plugins)
|
plugin:add_command(plugins)
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
return {
|
|
||||||
["pivot"] = {embed={
|
|
||||||
title = "Select a pivot message to manipulate",
|
|
||||||
description = "Pivot is like a message selector which allows easy reaction manipulations",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ",value = "pivot <message link>"},
|
|
||||||
{name = "Perms: ",valeu = "Administartor"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["role-toggle"] = {embed={
|
|
||||||
title = "Add a simple role switch to the pivot",
|
|
||||||
description = "Note: you cannot assign more than one role to a single reaction",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ",value = "role-toggle <emoji> <role ping or role id>"},
|
|
||||||
{name = "Perms: ",value = "administrator"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["remove-reaction"] = {embed={
|
|
||||||
title = "Remove a reaction from a pivot",
|
|
||||||
description = "If you don't specify a reaction to remove, the entire pivot for the message is removed automatically",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ",value = "remove-reaction <emoji>"},
|
|
||||||
{name = "Perms: ",value = "Administrator"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["toggle"] = {embed={
|
|
||||||
title = "Add a toggle that runs specific commands",
|
|
||||||
description = "Note: you cannot assign more than one action to a single reaction \n``$user`` gets replaced with the id of the user that interacted with the reaction.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ",value = "toggle <emoji> <command-on> <command-off>"},
|
|
||||||
{name = "Perms: ",value = "administrator"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["button"] = {embed={
|
|
||||||
title = "Add a button that runs specific command when pressed",
|
|
||||||
description = "Note: you cannot assign more than one action to a single reaction \n``$user`` gets replaced with the id of the user that interacted with the reaction.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ",value = "button <emoji> <command>"},
|
|
||||||
{name = "Perms: ",value = "administrator"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
}
|
|
|
@ -7,300 +7,334 @@ local segment = {}
|
||||||
segment.pivots = config
|
segment.pivots = config
|
||||||
|
|
||||||
local getEmoji = function(id)
|
local getEmoji = function(id)
|
||||||
local emoji = guild:getEmoji(id:match("(%d+)[^%d]*$"))
|
local emoji = guild:getEmoji(id:match("(%d+)[^%d]*$"))
|
||||||
if emoji then
|
if emoji then
|
||||||
return emoji
|
return emoji
|
||||||
else
|
else
|
||||||
return id
|
return id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function count(tab)
|
local function count(tab)
|
||||||
local n = 0
|
local n = 0
|
||||||
for k,v in pairs(tab) do
|
for k,v in pairs(tab) do
|
||||||
n = n + 1
|
n = n + 1
|
||||||
end
|
end
|
||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
|
|
||||||
local pivot = command("pivot",{
|
local pivot = command("pivot",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
args = {
|
title = "Select a pivot message to manipulate",
|
||||||
"messageLink"
|
description = "Pivot is like a message selector which allows easy reaction manipulations",
|
||||||
},
|
fields = {
|
||||||
perms = {
|
{name = "Usage: ",value = "pivot <message link>"},
|
||||||
"administrator"
|
{name = "Perms: ",valeu = "Administartor"}
|
||||||
},
|
}
|
||||||
exec = function(msg,args,opts)
|
}},
|
||||||
if segment.pivot and count(segment.pivot.buttons) == 0 then
|
args = {
|
||||||
log("REACTIONS","Deleting pivot: "..tostring(segment.pivot.message))
|
"messageLink"
|
||||||
segment.pivots[segment.pivot.message] = nil
|
},
|
||||||
end
|
perms = {
|
||||||
local message = args[1]
|
"administrator"
|
||||||
if not message then
|
},
|
||||||
msg:reply("Couldn't find message with id "..args[2])
|
exec = function(msg,args,opts)
|
||||||
return false
|
if segment.pivot and count(segment.pivot.buttons) == 0 then
|
||||||
end
|
print("[REACTIONS] Deleting pivot: "..tostring(segment.pivot.message))
|
||||||
if not segment.pivots[message.id] then
|
segment.pivots[segment.pivot.message] = nil
|
||||||
log("REACTIONS","Creating pivot: "..tostring(message.id))
|
end
|
||||||
segment.pivots[message.id] = {}
|
local message = args[1]
|
||||||
segment.pivots[message.id].message = message.id
|
if not message then
|
||||||
segment.pivots[message.id].channel = message.channel.id
|
msg:reply("Couldn't find message with id "..args[2])
|
||||||
segment.pivots[message.id].buttons = {}
|
return false
|
||||||
end
|
end
|
||||||
segment.pivot = segment.pivots[message.id]
|
if not segment.pivots[message.id] then
|
||||||
return true
|
print("[REACTIONS] Creating pivot: "..tostring(message.id))
|
||||||
end
|
segment.pivots[message.id] = {}
|
||||||
})
|
segment.pivots[message.id].message = message.id
|
||||||
|
segment.pivots[message.id].channel = message.channel.id
|
||||||
|
segment.pivots[message.id].buttons = {}
|
||||||
|
end
|
||||||
|
segment.pivot = segment.pivots[message.id]
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
})
|
||||||
plugin:add_command(pivot)
|
plugin:add_command(pivot)
|
||||||
|
|
||||||
local role_toggle = command("role-toggle",{
|
local role_toggle = command("role-toggle",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
args = {
|
title = "Add a simple role switch to the pivot",
|
||||||
"string",
|
description = "Note: you cannot assign more than one role to a single reaction",
|
||||||
"role",
|
fields = {
|
||||||
},
|
{name = "Usage: ",value = "role-toggle <emoji> <role ping or role id>"},
|
||||||
perms = {
|
{name = "Perms: ",value = "administrator"}
|
||||||
"administrator"
|
}
|
||||||
},
|
}},
|
||||||
exec = function(msg,args,opts)
|
args = {
|
||||||
if not segment.pivot then
|
"string",
|
||||||
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
"role",
|
||||||
return false
|
},
|
||||||
end
|
perms = {
|
||||||
local emoji = getEmoji(args[1])
|
"administrator"
|
||||||
local channel = guild:getChannel(segment.pivot.channel)
|
},
|
||||||
if not channel then
|
exec = function(msg,args,opts)
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
if not segment.pivot then
|
||||||
return false
|
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
||||||
end
|
return false
|
||||||
local message = channel:getMessage(segment.pivot.message)
|
end
|
||||||
if not message then
|
local emoji = getEmoji(args[1])
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
return false
|
if not channel then
|
||||||
end
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
log("REACTIONS","Adding role-toggle listener")
|
return false
|
||||||
local grabEmoji = function(reaction)
|
end
|
||||||
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
type = "role-toggler",
|
if not message then
|
||||||
role = tostring(args[2].id)
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
}
|
return false
|
||||||
end
|
end
|
||||||
message:removeReaction(emoji,client.user.id)
|
print("[REACTIONS] Adding role-toggle listener")
|
||||||
client:once("reactionAdd",grabEmoji)
|
local grabEmoji = function(reaction)
|
||||||
if not message:addReaction(emoji) then
|
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
||||||
client:removeListener("reactionAdd",grabEmoji)
|
type = "role-toggler",
|
||||||
msg:reply("Couldn't add reaction - emoji might be invalid")
|
role = tostring(args[2].id)
|
||||||
return false
|
}
|
||||||
else
|
end
|
||||||
return true
|
message:removeReaction(emoji,client.user.id)
|
||||||
end
|
client:once("reactionAdd",grabEmoji)
|
||||||
end
|
if not message:addReaction(emoji) then
|
||||||
})
|
client:removeListener("reactionAdd",grabEmoji)
|
||||||
|
msg:reply("Couldn't add reaction - emoji might be invalid")
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
plugin:add_command(role_toggle)
|
plugin:add_command(role_toggle)
|
||||||
local remove_reaction = command("remove-reaction",{
|
local remove_reaction = command("remove-reaction",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
perms = {
|
title = "Remove a reaction from a pivot",
|
||||||
"administrator"
|
description = "If you don't specify a reaction to remove, the entire pivot for the message is removed automatically",
|
||||||
},
|
fields = {
|
||||||
exec = function(msg,args,opts)
|
{name = "Usage: ",value = "remove-reaction <emoji>"},
|
||||||
local channel = guild:getChannel(segment.pivot.channel)
|
{name = "Perms: ",value = "Administrator"}
|
||||||
if not channel then
|
}
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
}},
|
||||||
return false
|
perms = {
|
||||||
end
|
"administrator"
|
||||||
local message = channel:getMessage(segment.pivot.message)
|
},
|
||||||
if not message then
|
exec = function(msg,args,opts)
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
return false
|
if not channel then
|
||||||
end
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
log("REACTIONS","Removing reaction listener")
|
return false
|
||||||
if args[1] then
|
end
|
||||||
local emoji = getEmoji(args[1])
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
message:removeReaction(emoji,client.user.id)
|
if not message then
|
||||||
segment.pivot.buttons[((type(emoji) == "table") and emoji.id) or emoji] = nil
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
return true
|
return false
|
||||||
else
|
end
|
||||||
message:clearReactions()
|
print("[REACTIONS] Removing reaction listener")
|
||||||
segment.pivots[tostring(message.id)] = nil
|
if args[1] then
|
||||||
segment.pivot = nil
|
local emoji = getEmoji(args[1])
|
||||||
return true
|
message:removeReaction(emoji,client.user.id)
|
||||||
end
|
segment.pivot.buttons[((type(emoji) == "table") and emoji.id) or emoji] = nil
|
||||||
end
|
return true
|
||||||
})
|
else
|
||||||
|
message:clearReactions()
|
||||||
|
segment.pivots[tostring(message.id)] = nil
|
||||||
|
segment.pivot = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
plugin:add_command(remove_reaction)
|
plugin:add_command(remove_reaction)
|
||||||
local toggle = command("toggle",{
|
local toggle = command("toggle",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
args = {
|
title = "Add a toggle that runs specific commands",
|
||||||
"string",
|
description = "Note: you cannot assign more than one action to a single reaction \n``$user`` gets replaced with the id of the user that interacted with the reaction.",
|
||||||
"string",
|
fields = {
|
||||||
"string",
|
{name = "Usage: ",value = "toggle <emoji> <command-on> <command-off>"},
|
||||||
},
|
{name = "Perms: ",value = "administrator"}
|
||||||
perms = {
|
}
|
||||||
"administrator"
|
}},
|
||||||
},
|
args = {
|
||||||
exec = function(msg,args,opts)
|
"string",
|
||||||
if not segment.pivot then
|
"string",
|
||||||
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
"string",
|
||||||
return false
|
},
|
||||||
end
|
perms = {
|
||||||
local emoji = getEmoji(args[1])
|
"administrator"
|
||||||
local channel = guild:getChannel(segment.pivot.channel)
|
},
|
||||||
if not channel then
|
exec = function(msg,args,opts)
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
if not segment.pivot then
|
||||||
return false
|
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
||||||
end
|
return false
|
||||||
local message = channel:getMessage(segment.pivot.message)
|
end
|
||||||
if not message then
|
local emoji = getEmoji(args[1])
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
return false
|
if not channel then
|
||||||
end
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
log("REACTIONS","Adding toggle listener")
|
return false
|
||||||
local grabEmoji = function(reaction)
|
end
|
||||||
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
type = "toggler",
|
if not message then
|
||||||
on = args[2],
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
off = args[3],
|
return false
|
||||||
}
|
end
|
||||||
end
|
print("[REACTIONS] Adding toggle listener")
|
||||||
message:removeReaction(emoji,client.user.id)
|
local grabEmoji = function(reaction)
|
||||||
client:once("reactionAdd",grabEmoji)
|
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
||||||
if not message:addReaction(emoji) then
|
type = "toggler",
|
||||||
client:removeListener("reactionAdd",grabEmoji)
|
on = args[2],
|
||||||
msg:reply("Couldn't add reaction - emoji might be invalid")
|
off = args[3],
|
||||||
return false
|
}
|
||||||
else
|
end
|
||||||
return true
|
message:removeReaction(emoji,client.user.id)
|
||||||
end
|
client:once("reactionAdd",grabEmoji)
|
||||||
end
|
if not message:addReaction(emoji) then
|
||||||
})
|
client:removeListener("reactionAdd",grabEmoji)
|
||||||
|
msg:reply("Couldn't add reaction - emoji might be invalid")
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
plugin:add_command(toggle)
|
plugin:add_command(toggle)
|
||||||
local button = command("button",{
|
local button = command("button",{
|
||||||
category = "Automation",
|
help = {embed={
|
||||||
args = {
|
title = "Add a button that runs specific command when pressed",
|
||||||
"string",
|
description = "Note: you cannot assign more than one action to a single reaction \n``$user`` gets replaced with the id of the user that interacted with the reaction.",
|
||||||
"string",
|
fields = {
|
||||||
},
|
{name = "Usage: ",value = "button <emoji> <command>"},
|
||||||
perms = {
|
{name = "Perms: ",value = "administrator"}
|
||||||
"administrator"
|
}
|
||||||
},
|
}},
|
||||||
exec = function(msg,args,opts)
|
args = {
|
||||||
if not segment.pivot then
|
"string",
|
||||||
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
"string",
|
||||||
return false
|
},
|
||||||
end
|
perms = {
|
||||||
local emoji = getEmoji(args[1])
|
"administrator"
|
||||||
local channel = guild:getChannel(segment.pivot.channel)
|
},
|
||||||
if not channel then
|
exec = function(msg,args,opts)
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
if not segment.pivot then
|
||||||
return false
|
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
||||||
end
|
return false
|
||||||
local message = channel:getMessage(segment.pivot.message)
|
end
|
||||||
if not message then
|
local emoji = getEmoji(args[1])
|
||||||
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
return false
|
if not channel then
|
||||||
end
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
log("REACTIONS","Adding button listener")
|
return false
|
||||||
local grabEmoji = function(reaction)
|
end
|
||||||
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
type = "button",
|
if not message then
|
||||||
on = args[2],
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
}
|
return false
|
||||||
end
|
end
|
||||||
message:removeReaction(emoji,client.user.id)
|
print("[REACTIONS] Adding button listener")
|
||||||
client:once("reactionAdd",grabEmoji)
|
local grabEmoji = function(reaction)
|
||||||
if not message:addReaction(emoji) then
|
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
||||||
client:removeListener("reactionAdd",grabEmoji)
|
type = "button",
|
||||||
msg:reply("Couldn't add reaction - emoji might be invalid")
|
on = args[2],
|
||||||
return false
|
}
|
||||||
else
|
end
|
||||||
return true
|
message:removeReaction(emoji,client.user.id)
|
||||||
end
|
client:once("reactionAdd",grabEmoji)
|
||||||
end
|
if not message:addReaction(emoji) then
|
||||||
})
|
client:removeListener("reactionAdd",grabEmoji)
|
||||||
|
msg:reply("Couldn't add reaction - emoji might be invalid")
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
plugin:add_command(button)
|
plugin:add_command(button)
|
||||||
|
|
||||||
local buttonOn = function(message,hash,userID)
|
local buttonOn = function(message,hash,userID)
|
||||||
if not message then
|
if not message then
|
||||||
log("ERROR","Attempted to find a deleted message")
|
log("ERROR","Attempted to find a deleted message")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if segment.pivots[tostring(message.id)] and userID ~= client.user.id then
|
if segment.pivots[tostring(message.id)] and userID ~= client.user.id then
|
||||||
local current_pivot = segment.pivots[tostring(message.id)]
|
local current_pivot = segment.pivots[tostring(message.id)]
|
||||||
if current_pivot.buttons[tostring(hash)] then
|
if current_pivot.buttons[tostring(hash)] then
|
||||||
local current_button = current_pivot.buttons[tostring(hash)]
|
local current_button = current_pivot.buttons[tostring(hash)]
|
||||||
local new_content
|
local new_content
|
||||||
if current_button.on then
|
if current_button.on then
|
||||||
new_content = current_button.on:gsub("%$user",userID)
|
new_content = current_button.on:gsub("%$user",userID)
|
||||||
end
|
end
|
||||||
if current_button.type == "role-toggler" then
|
if current_button.type == "role-toggler" then
|
||||||
guild:getMember(userID):addRole(current_button.role)
|
guild:getMember(userID):addRole(current_button.role)
|
||||||
end
|
end
|
||||||
if current_button.type == "toggler" then
|
if current_button.type == "toggler" then
|
||||||
command_handler:handle(fake_message(message,{
|
command_handler:handle(fake_message(message,{
|
||||||
delete = function() end,
|
delete = function() end,
|
||||||
content = new_content
|
content = new_content
|
||||||
}))
|
}))
|
||||||
end
|
end
|
||||||
if current_button.type == "button" then
|
if current_button.type == "button" then
|
||||||
command_handler:handle(fake_message(message,{
|
command_handler:handle(fake_message(message,{
|
||||||
delete = function() end,
|
delete = function() end,
|
||||||
content = new_content
|
content = new_content
|
||||||
}))
|
}))
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local buttonOff = function(message,hash,userID)
|
local buttonOff = function(message,hash,userID)
|
||||||
if not message then
|
if not message then
|
||||||
log("ERROR","Attempted to find a deleted message")
|
log("ERROR","Attempted to find a deleted message")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if segment.pivots[tostring(message.id)] and userID ~= client.user.id then
|
if segment.pivots[tostring(message.id)] and userID ~= client.user.id then
|
||||||
local current_pivot = segment.pivots[tostring(message.id)]
|
local current_pivot = segment.pivots[tostring(message.id)]
|
||||||
if current_pivot.buttons[tostring(hash)] then
|
if current_pivot.buttons[tostring(hash)] then
|
||||||
local current_button = current_pivot.buttons[tostring(hash)]
|
local current_button = current_pivot.buttons[tostring(hash)]
|
||||||
local new_content
|
local new_content
|
||||||
if current_button.off then
|
if current_button.off then
|
||||||
new_content = current_button.off:gsub("%$user",userID)
|
new_content = current_button.off:gsub("%$user",userID)
|
||||||
end
|
end
|
||||||
if current_button.type == "role-toggler" then
|
if current_button.type == "role-toggler" then
|
||||||
guild:getMember(userID):removeRole(current_button.role)
|
guild:getMember(userID):removeRole(current_button.role)
|
||||||
end
|
end
|
||||||
if current_button.type == "toggler" then
|
if current_button.type == "toggler" then
|
||||||
command_handler:handle(fake_message(message,{
|
command_handler:handle(fake_message(message,{
|
||||||
delete = function() end,
|
delete = function() end,
|
||||||
content = new_content
|
content = new_content
|
||||||
}))
|
}))
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
events:on("reactionAdd",function(reaction,userID)
|
events:on("reactionAdd",function(reaction,userID)
|
||||||
local message = reaction.message
|
local message = reaction.message
|
||||||
local hash = tostring(reaction.emojiId or reaction.emojiName)
|
local hash = tostring(reaction.emojiId or reaction.emojiName)
|
||||||
buttonOn(message,hash,userID)
|
buttonOn(message,hash,userID)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
events:on("reactionRemove",function(reaction,userID)
|
events:on("reactionRemove",function(reaction,userID)
|
||||||
local message = reaction.message
|
local message = reaction.message
|
||||||
local hash = tostring(reaction.emojiId or reaction.emojiName)
|
local hash = tostring(reaction.emojiId or reaction.emojiName)
|
||||||
buttonOff(message,hash,userID)
|
buttonOff(message,hash,userID)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
events:on("reactionAddUncached",function(channelId,messageId,hash,userId)
|
events:on("reactionAddUncached",function(channelId,messageId,hash,userId)
|
||||||
local message = client:getChannel(channelId):getMessage(messageId)
|
local message = client:getChannel(channelId):getMessage(messageId)
|
||||||
local hash = tostring(hash)
|
local hash = tostring(hash)
|
||||||
buttonOn(message,hash,userId)
|
buttonOn(message,hash,userId)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
events:on("reactionRemoveUncached",function(channelId,messageId,hash,userId)
|
events:on("reactionRemoveUncached",function(channelId,messageId,hash,userId)
|
||||||
local message = client:getChannel(channelId):getMessage(messageId)
|
local message = client:getChannel(channelId):getMessage(messageId)
|
||||||
local hash = tostring(hash)
|
local hash = tostring(hash)
|
||||||
buttonOff(message,hash,userId)
|
buttonOff(message,hash,userId)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
return {
|
|
||||||
["droleadd"] = "Add a default role to assign for new users",
|
|
||||||
["droledel"] = "Remove a role from the list of default roles",
|
|
||||||
["drolelist"] = "List all default roles",
|
|
||||||
}
|
|
|
@ -9,19 +9,19 @@ client:on("memberJoin",function(member)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local droleadd = command("droleadd",{
|
local droleadd = command("droleadd",{
|
||||||
category = "Automation",
|
help = "Add a default role to assign for new users",
|
||||||
usage = "droleadd <role>",
|
usage = "droleadd <role>",
|
||||||
perms = {"administrator"},
|
perms = {"administrator"},
|
||||||
args = {
|
args = {
|
||||||
"role"
|
"role"
|
||||||
},
|
},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
table.insert(config.default_roles,args[1].id)
|
table.insert(config.default_roles,args[1].id)
|
||||||
msg:reply("Added role "..args[1].name.." to default roles list")
|
msg:reply("Added role "..args[1].name.." to default roles list")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
local droledel = command("droledel",{
|
local droledel = command("droledel",{
|
||||||
category = "Automation",
|
help = "Remove a role from the list of default roles",
|
||||||
usage = "droledel <role>",
|
usage = "droledel <role>",
|
||||||
perms = {"administrator"},
|
perms = {"administrator"},
|
||||||
args = {
|
args = {
|
||||||
|
@ -37,7 +37,7 @@ local droledel = command("droledel",{
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
local drolelist = command("drolelist", {
|
local drolelist = command("drolelist", {
|
||||||
category = "Automation",
|
help = "List all default roles",
|
||||||
usage = "drolelist",
|
usage = "drolelist",
|
||||||
perms = {"administrator"},
|
perms = {"administrator"},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
|
@ -56,6 +56,5 @@ local drolelist = command("drolelist", {
|
||||||
plugin:add_command(droleadd)
|
plugin:add_command(droleadd)
|
||||||
plugin:add_command(droledel)
|
plugin:add_command(droledel)
|
||||||
plugin:add_command(drolelist)
|
plugin:add_command(drolelist)
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
return {
|
|
||||||
["grant-role"] = {embed={
|
|
||||||
title = "Grant a role to the user",
|
|
||||||
description = "If <user> is not provided, the caller is assumed as the <user> argument.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "grant-role <role id> [<user>]"},
|
|
||||||
{name = "Perms:",value = "administrator"},
|
|
||||||
{name = "Options:",value = "-q - quiet (don't print the result)"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["revoke-role"] = {embed={
|
|
||||||
title = "Revoke a role from the user",
|
|
||||||
description = "If <user> is not provided, the caller is assumed as the <user> argument.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "revoke-role <role id> [<user>]"},
|
|
||||||
{name = "Perms:",value = "administrator"},
|
|
||||||
{name = "Options:",value = "-q - quiet (don't print the result)"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["warn"] = {embed={
|
|
||||||
title = "Warn a user",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage:",value = "warn <user> <reason>"},
|
|
||||||
{name = "Perms:",value = "kickMembers"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["infractions"] = { embed = {
|
|
||||||
title = "List user infractions",
|
|
||||||
description = "Infractions include kicks, bans, mutes and warnings.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ", value = "infractions <user> [<startfrom>]"},
|
|
||||||
{name = "Perms: ", value = "kickMembers"},
|
|
||||||
{name = "Options: ", value = "--type=(warn default,ban,kick)"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["purge"] = { embed = {
|
|
||||||
title = "Purge a number of messages",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ", value = "purge <number>"},
|
|
||||||
{name = "Perms: ", value = "manageMessages"},
|
|
||||||
{name = "Options: ", value = "`--regex (regex)` - match content against regex; \n`--user (user)` - match user against id/name; \n`-w` - match webhook messages"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["ban"] = { embed = {
|
|
||||||
title = "Ban members",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ", value = "ban <member>"},
|
|
||||||
{name = "Perms: ", value = "banMembers"},
|
|
||||||
{name = "Options: ", value = "--reason=\"<reason>\""},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
["kick"] = { embed = {
|
|
||||||
title = "Ban members",
|
|
||||||
description = "nuff said.",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ", value = "kick <member>"},
|
|
||||||
{name = "Perms: ", value = "kickMembers"},
|
|
||||||
{name = "Options: ", value = "--reason=\"<reason>\""},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
}
|
|
|
@ -17,7 +17,15 @@ CREATE TABLE infractions(id INTEGER PRIMARY KEY AUTOINCREMENT, user TEXT, desc T
|
||||||
end
|
end
|
||||||
|
|
||||||
local grantrole = command("grant-role",{
|
local grantrole = command("grant-role",{
|
||||||
category = "Security",
|
help = {embed={
|
||||||
|
title = "Grant a role to the user",
|
||||||
|
description = "If <user> is not provided, the caller is assumed as the <user> argument.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "grant-role <role id> [<user>]"},
|
||||||
|
{name = "Perms:",value = "administrator"},
|
||||||
|
{name = "Options:",value = "-q - quiet (don't print the result)"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
perms = {
|
perms = {
|
||||||
"administrator"
|
"administrator"
|
||||||
},
|
},
|
||||||
|
@ -33,7 +41,15 @@ local grantrole = command("grant-role",{
|
||||||
plugin:add_command(grantrole)
|
plugin:add_command(grantrole)
|
||||||
|
|
||||||
local revokerole = command("revoke-role",{
|
local revokerole = command("revoke-role",{
|
||||||
category = "Security",
|
help = {embed={
|
||||||
|
title = "Revoke a role from the user",
|
||||||
|
description = "If <user> is not provided, the caller is assumed as the <user> argument.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "revoke-role <role id> [<user>]"},
|
||||||
|
{name = "Perms:",value = "administrator"},
|
||||||
|
{name = "Options:",value = "-q - quiet (don't print the result)"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
perms = {
|
perms = {
|
||||||
"administrator"
|
"administrator"
|
||||||
},
|
},
|
||||||
|
@ -48,36 +64,15 @@ local revokerole = command("revoke-role",{
|
||||||
})
|
})
|
||||||
plugin:add_command(revokerole)
|
plugin:add_command(revokerole)
|
||||||
|
|
||||||
local ban = command("ban",{
|
|
||||||
category = "Security",
|
|
||||||
perms = {
|
|
||||||
"banMembers"
|
|
||||||
},
|
|
||||||
args = {
|
|
||||||
"member"
|
|
||||||
},
|
|
||||||
exec = function(msg,args,opts)
|
|
||||||
return args[1]:ban(opts["reason"])
|
|
||||||
end
|
|
||||||
})
|
|
||||||
plugin:add_command(ban)
|
|
||||||
|
|
||||||
local kick = command("kick", {
|
|
||||||
category = "Security",
|
|
||||||
perms = {
|
|
||||||
"kickMembers",
|
|
||||||
},
|
|
||||||
args = {
|
|
||||||
"member"
|
|
||||||
},
|
|
||||||
exec = function(msg,args,opts)
|
|
||||||
return args[1]:ban(opts["reason"])
|
|
||||||
end
|
|
||||||
})
|
|
||||||
plugin:add_command(kick)
|
|
||||||
|
|
||||||
local warn = command("warn",{
|
local warn = command("warn",{
|
||||||
category = "Security",
|
help = {embed={
|
||||||
|
title = "Warn a user",
|
||||||
|
description = "nuff said.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage:",value = "warn <user> <reason>"},
|
||||||
|
{name = "Perms:",value = "kickMembers"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
perms = {
|
perms = {
|
||||||
"kickMembers"
|
"kickMembers"
|
||||||
},
|
},
|
||||||
|
@ -104,7 +99,15 @@ local warn = command("warn",{
|
||||||
plugin:add_command(warn)
|
plugin:add_command(warn)
|
||||||
|
|
||||||
local infractions = command("infractions", {
|
local infractions = command("infractions", {
|
||||||
category = "Security",
|
help = { embed = {
|
||||||
|
title = "List user infractions",
|
||||||
|
description = "Infractions include kicks, bans, mutes and warnings.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ", value = "infractions <user> [<startfrom>]"},
|
||||||
|
{name = "Perms: ", value = "kickMembers"},
|
||||||
|
{name = "Options: ", value = "--type=(warn default,ban,kick)"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
perms = {
|
perms = {
|
||||||
"kickMembers"
|
"kickMembers"
|
||||||
},
|
},
|
||||||
|
@ -147,7 +150,15 @@ local infractions = command("infractions", {
|
||||||
plugin:add_command(infractions)
|
plugin:add_command(infractions)
|
||||||
|
|
||||||
local purge = command("purge",{
|
local purge = command("purge",{
|
||||||
category = "Security",
|
help = { embed = {
|
||||||
|
title = "Purge a number of messages",
|
||||||
|
description = "nuff said.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ", value = "purge <number>"},
|
||||||
|
{name = "Perms: ", value = "manageMessages"},
|
||||||
|
{name = "Options: ", value = "`--regex (regex)` - match content against regex; \n`--user (user)` - match user against id/name; \n`-w` - match webhook messages"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
perms = {
|
perms = {
|
||||||
"manageMessages"
|
"manageMessages"
|
||||||
},
|
},
|
||||||
|
@ -199,5 +210,5 @@ local purge = command("purge",{
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
plugin:add_command(purge)
|
plugin:add_command(purge)
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
return {
|
|
||||||
["dice"] = "Simulates a dice throw, prints the value of each die",
|
|
||||||
["cards"] = "Draw a specific amount of playing cards and display them",
|
|
||||||
["calculate"] = {embed={
|
|
||||||
title = "Calculate an expression",
|
|
||||||
description = "Calculates maths using libqalculate. https://qalculate.github.io/ for more info",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage",value = [[calculate "<expression>"]]},
|
|
||||||
{name = "Perms: ",value = "All"},
|
|
||||||
{name = "Options",value = "`-e` - exact mode"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["pfp"] = "Show the profile picture of a user, or if none is specified, of yourself",
|
|
||||||
["markpov"] = { embed = {
|
|
||||||
title = "Generate some text using markov chains",
|
|
||||||
description = "Generates text using the markov chain rule applied to a predefined set of words",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage: ", value = "markov <text to start with>"},
|
|
||||||
{name = "Options: ", value = [[
|
|
||||||
--preseteset> - Select a text preset. Currently available:
|
|
||||||
``defaul- Generated from a wikipedia page on markov chains
|
|
||||||
``freud`The largest one, generated from a page on Sigmund Freud
|
|
||||||
``reddit Generated from reddit comments
|
|
||||||
``travist`` - Generated from transcript of a video by PlasticPills on travis scott burger
|
|
||||||
]] },
|
|
||||||
{name = "Perms: ", value = "any"}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
["embed"] = {embed={
|
|
||||||
title = "Convert JSON objects into embeds",
|
|
||||||
description = "If you've worked with discord.js before, this might be simple. If you haven't, then check out https://github.com/512mb-org/512mb.org-bot/wiki/Embeds",
|
|
||||||
fields = {
|
|
||||||
{name = "Usage",value = [[embed {code}]]},
|
|
||||||
{name = "Perms: ",value = "All"},
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
}
|
|
|
@ -28,134 +28,152 @@ function to_bit_string(num)
|
||||||
end
|
end
|
||||||
|
|
||||||
local flip = command("flip",{
|
local flip = command("flip",{
|
||||||
category = "Miscellaneous",
|
help = "Flips a coin, obv.",
|
||||||
help = "Flips a coin, obv.",
|
usage = "flip",
|
||||||
usage = "flip",
|
exec = function(msg,args,opts)
|
||||||
exec = function(msg,args,opts)
|
local coin = math.random(1,100)%2
|
||||||
local coin = math.random(1,100)%2
|
if coin > 0 then
|
||||||
if coin > 0 then
|
msg:reply("Heads")
|
||||||
msg:reply("Heads")
|
else
|
||||||
else
|
msg:reply("Tails")
|
||||||
msg:reply("Tails")
|
end
|
||||||
end
|
end,
|
||||||
end,
|
|
||||||
})
|
})
|
||||||
plugin:add_command(flip)
|
plugin:add_command(flip)
|
||||||
local dice = command("dice",{
|
local dice = command("dice",{
|
||||||
category = "Miscellaneous",
|
help = "Simulates a dice throw, prints the value of each die",
|
||||||
usage = "dice <2d6,d30,d20+4,etc>",
|
usage = "dice <2d6,d30,d20+4,etc>",
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local out = {embed = {
|
local out = {embed = {
|
||||||
fields = {},
|
fields = {},
|
||||||
footer = {
|
footer = {
|
||||||
text = 0
|
text = 0
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
for I = 1,#args do
|
for I = 1,#args do
|
||||||
local v = args[I]
|
local v = args[I]
|
||||||
for J = 1,(v:match("(%d+)d%d+") or 1) do
|
for J = 1,(v:match("(%d+)d%d+") or 1) do
|
||||||
local value = math.random(1,tonumber(v:match("d(%d+)")))
|
local value = math.random(1,tonumber(v:match("d(%d+)")))
|
||||||
if v:find("d%d+[%+%-]%d+") then
|
if v:find("d%d+[%+%-]%d+") then
|
||||||
if v:match("d%d+([%+%-])") == "+" then
|
if v:match("d%d+([%+%-])") == "+" then
|
||||||
value = value + tonumber(v:match("d%d+[%+%-](%d+)"))
|
value = value + tonumber(v:match("d%d+[%+%-](%d+)"))
|
||||||
else
|
else
|
||||||
value = value - tonumber(v:match("d%d+[%+%-](%d+)"))
|
value = value - tonumber(v:match("d%d+[%+%-](%d+)"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
out.embed.fields[#out.embed.fields+1] = {name = "d"..v:match("d(%d+)"),value = value, inline = true}
|
out.embed.fields[#out.embed.fields+1] = {name = "d"..v:match("d(%d+)"),value = value, inline = true}
|
||||||
out.embed.footer.text = out.embed.footer.text+value
|
out.embed.footer.text = out.embed.footer.text+value
|
||||||
if #out.embed.fields >= 25 then
|
if #out.embed.fields >= 25 then
|
||||||
break
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
if #out.embed.fields >= 25 then
|
||||||
if #out.embed.fields >= 25 then
|
break
|
||||||
break
|
end
|
||||||
end
|
end
|
||||||
end
|
out.embed.footer.text = "Total: "..out.embed.footer.text
|
||||||
out.embed.footer.text = "Total: "..out.embed.footer.text
|
msg:reply(out)
|
||||||
msg:reply(out)
|
end,
|
||||||
end,
|
|
||||||
})
|
})
|
||||||
plugin:add_command(dice)
|
plugin:add_command(dice)
|
||||||
local cards = command("cards",{
|
local cards = command("cards",{
|
||||||
category = "Miscellaneous",
|
help = "Draw a specific amount of playing cards and display them",
|
||||||
usage = "cards <amount>",
|
usage = "cards <amount>",
|
||||||
args = {"number"},
|
args = {"number"},
|
||||||
exec = function(msg,args,opts)
|
exec = function(msg,args,opts)
|
||||||
local out = {embed = {
|
local out = {embed = {
|
||||||
fields = {}
|
fields = {}
|
||||||
}}
|
}}
|
||||||
local random = math.random
|
local random = math.random
|
||||||
for I = 1,(args[1] < 25 and args[1]) or 25 do
|
for I = 1,(args[1] < 25 and args[1]) or 25 do
|
||||||
local suits = {"spades","clubs","diamonds","hearts"}
|
local suits = {"spades","clubs","diamonds","hearts"}
|
||||||
local values = {
|
local values = {
|
||||||
"A","1","2","3","4","5",
|
"A","1","2","3","4","5",
|
||||||
"6","7","8","9","J","Q","K"
|
"6","7","8","9","J","Q","K"
|
||||||
}
|
}
|
||||||
out.embed.fields[I] = {name = "card", value = " :"..suits[random(1,4)]..":"..values[random(1,11)].." ",inline = true}
|
out.embed.fields[I] = {name = "card", value = " :"..suits[random(1,4)]..":"..values[random(1,11)].." ",inline = true}
|
||||||
end
|
end
|
||||||
msg:reply(out)
|
msg:reply(out)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(cards)
|
plugin:add_command(cards)
|
||||||
local calculate = command("calculate",{
|
local calculate = command("calculate",{
|
||||||
category = "Miscellaneous",
|
help = "Calculates maths using libqalculate. https://qalculate.github.io/ for more info",
|
||||||
args = {
|
usage = [[
|
||||||
"string"
|
calculate "<expression>"
|
||||||
},
|
``-e`` - exact mode
|
||||||
exec = function(msg,args,opts)
|
]],
|
||||||
msg:reply(qalculator.qalc(table.concat(args," "),opts["e"]))
|
args = {
|
||||||
end,
|
"string"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
msg:reply(qalculator.qalc(args[1],opts["e"]))
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(calculate)
|
plugin:add_command(calculate)
|
||||||
local pfp = command("pfp",{
|
local pfp = command("pfp",{
|
||||||
category = "Miscellaneous",
|
help = "Show the profile picture of a user, or if none is specified, of yourself",
|
||||||
exec = function(msg,args,opts)
|
usage = "pfp <user or none>",
|
||||||
local user = client:getUser((args[1] or ""):match("%d+"))
|
exec = function(msg,args,opts)
|
||||||
if user then
|
local user = client:getUser((args[1] or ""):match("%d+"))
|
||||||
msg:reply(user:getAvatarURL().."?size=2048")
|
if user then
|
||||||
else
|
msg:reply(user:getAvatarURL().."?size=2048")
|
||||||
msg:reply(msg.author:getAvatarURL().."?size=2048")
|
else
|
||||||
end
|
msg:reply(msg.author:getAvatarURL().."?size=2048")
|
||||||
end,
|
end
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
plugin:add_command(pfp)
|
plugin:add_command(pfp)
|
||||||
local markov = command("markov",{
|
local markov = command("markov",{
|
||||||
category = "Miscellaneous",
|
help = { embed = {
|
||||||
exec = function(msg,args,opts)
|
title = "Generate some text using markov chains",
|
||||||
local preset,code,err = import("file").readJSON("./resources/"..(opts["preset"] or "default"):match("%w+")..".json",{system_failed = true})
|
description = "Generates text using the markov chain rule applied to a predefined set of words",
|
||||||
if preset.system_failed then
|
fields = {
|
||||||
msg:reply("No such preset")
|
{name = "Usage: ", value = "markov <text to start with>"},
|
||||||
return
|
{name = "Options: ", value = [[
|
||||||
|
--preset=<preset> - Select a text preset. Currently available:
|
||||||
|
``default`` - Generated from a wikipedia page on markov chains
|
||||||
|
``freud`` - The largest one, generated from a page on Sigmund Freud
|
||||||
|
``reddit`` - Generated from reddit comments
|
||||||
|
``travisscott`` - Generated from transcript of a video by PlasticPills on travis scott burger
|
||||||
|
]] },
|
||||||
|
{name = "Perms: ", value = "any"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local preset,code,err = import("file").readJSON("./resources/"..(opts["preset"] or "default"):match("%w+")..".json",{system_failed = true})
|
||||||
|
if preset.system_failed then
|
||||||
|
msg:reply("No such preset")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
markov_instance:load_state(preset)
|
||||||
|
local output = markov_instance:run("The",100)
|
||||||
|
msg:reply(output)
|
||||||
end
|
end
|
||||||
markov_instance:load_state(preset)
|
|
||||||
local output = markov_instance:run("The",100)
|
|
||||||
msg:reply(output)
|
|
||||||
end
|
|
||||||
})
|
})
|
||||||
plugin:add_command(markov)
|
plugin:add_command(markov)
|
||||||
local embed = command("embed",{
|
local embed = command("embed",{
|
||||||
category = "Miscellaneous",
|
help = "Convert JSON objects into embeds",
|
||||||
args = {
|
usage = "If you've worked with discord.js before, this might be simple. If you haven't, then check out https://github.com/yessiest/SuppaBot/wiki/Embeds",
|
||||||
"string"
|
args = {
|
||||||
},
|
"string"
|
||||||
exec = function(msg,args,opts)
|
},
|
||||||
local embed = msg.content:match("{.+}")
|
exec = function(msg,args,opts)
|
||||||
if not embed then
|
local embed = msg.content:match("{.+}")
|
||||||
msg:reply("Invalid embed object")
|
if not embed then
|
||||||
return
|
msg:reply("Invalid embed object")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local embed_obj,code,err = import("json").decode(embed)
|
||||||
|
if not embed_obj then
|
||||||
|
msg:reply("Error while decoding JSON object: "..tostring(err))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if pcall(discordia.Color.fromHex,embed_obj.color) then
|
||||||
|
embed_obj.color = discordia.Color.fromHex(embed_obj.color).value
|
||||||
|
end
|
||||||
|
msg:reply({embed = embed_obj})
|
||||||
end
|
end
|
||||||
local embed_obj,code,err = import("json").decode(embed)
|
|
||||||
if not embed_obj then
|
|
||||||
msg:reply("Error while decoding JSON object: "..tostring(err))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if pcall(discordia.Color.fromHex,embed_obj.color) then
|
|
||||||
embed_obj.color = discordia.Color.fromHex(embed_obj.color).value
|
|
||||||
end
|
|
||||||
msg:reply({embed = embed_obj})
|
|
||||||
end
|
|
||||||
})
|
})
|
||||||
plugin:add_command(embed)
|
plugin:add_command(embed)
|
||||||
plugin:load_helpdb(plugin_path.."help.lua")
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
|
@ -0,0 +1,478 @@
|
||||||
|
--TODO: Add domain-specific manuals, Document
|
||||||
|
local air = require("air")
|
||||||
|
local json = require("json")
|
||||||
|
local file = require("file")
|
||||||
|
file.activate_json(json)
|
||||||
|
local segment = {}
|
||||||
|
segment.setnames = {}
|
||||||
|
segment.name = "enforcer"
|
||||||
|
segment.settings = {
|
||||||
|
automod = {
|
||||||
|
list = {
|
||||||
|
|
||||||
|
},
|
||||||
|
status = false,
|
||||||
|
warn_limit = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if globals.enofrcer then
|
||||||
|
if globals.enforcer.setnames then
|
||||||
|
segment.setnames = globals.enforcer.setnames
|
||||||
|
end
|
||||||
|
if globals.enforcer.settings then
|
||||||
|
segment.settings = global.enforcer.settings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
segment.warns = file.readJSON("./servers/"..id.."/warns.json",{})
|
||||||
|
|
||||||
|
events:on("serverSaveConfig",function()
|
||||||
|
if not globals.enforcer then
|
||||||
|
globals.enforcer = {}
|
||||||
|
end
|
||||||
|
globals.enforcer.setnames = segment.setnames
|
||||||
|
globals.enforcer.settings = segment.settings
|
||||||
|
file.writeJSON("./servers/"..id.."/warns.json",segment.warns)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local warn = function(ID,reason)
|
||||||
|
local guild = client:getGuild(id)
|
||||||
|
local member = guild:getMember(tostring(ID))
|
||||||
|
if not segment.warns[tostring(ID)] then segment.warns[tostring(ID)] = {} end
|
||||||
|
table.insert(segment.warns[tostring(ID)],1,reason)
|
||||||
|
if segment.settings.warn_limit and (#segment.warns[tostring(ID)] >= segment.settings.warn_limit) and guild:getMember(tostring(ID)) then
|
||||||
|
if segment.settings.warn_punishment == "kick" then
|
||||||
|
member:kick("Warning quota exceeded.")
|
||||||
|
elseif segment.settings.warn_punishment == "ban" then
|
||||||
|
member:ban("Warning quota exceeded.",segment.settings.ban_days)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
_ = (client:getUser(tostring(ID)) and client:getUser(tostring(ID)):send("__You have been warned.__\nReason: "..reason))
|
||||||
|
signals:emit("warn",function(args)
|
||||||
|
if args[1] and member.name:find(args[1],1,true) then
|
||||||
|
return true
|
||||||
|
elseif not args[1] then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,{
|
||||||
|
user = member.id,
|
||||||
|
name = member.name
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
segment.commands = {
|
||||||
|
["change-name"] = {
|
||||||
|
help = {embed = {
|
||||||
|
title = "Enforce a name upon a specific user",
|
||||||
|
description = "Whenever the user attempts to change their name, it will be changed back",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "change-name <user> <name>"},
|
||||||
|
{name = "Perms: ",value = "manageNicknames"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageNicknames"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member",
|
||||||
|
"string"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
name = args[2]
|
||||||
|
args[1]:setNickname(name)
|
||||||
|
segment.setnames[tostring(args[1].id)] = name
|
||||||
|
msg:reply("Now assigning an enforced name upon "..args[1].name)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["reset-name"] = {
|
||||||
|
help = {embed = {
|
||||||
|
title = "Stop enforcing a name upon a user",
|
||||||
|
description = "Reverses the effect of ``change-name``",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "reset-name"},
|
||||||
|
{name = "Perms: ",value = "manageNicknames"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageNicknames"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if segment.setnames[tostring(args[1].id)] then
|
||||||
|
segment.setnames[tostring(args[1].id)] = nil
|
||||||
|
args[1]:setNickname(nil)
|
||||||
|
msg:reply("No longer tracking "..args[1].name)
|
||||||
|
else
|
||||||
|
msg:reply("This user haven't been assigned an enforced name")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["wipe"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Wipe user messages",
|
||||||
|
description = "Searches and deletes all messages of a specific user in a specified range",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "wipe-user <range> <user mention or id>"},
|
||||||
|
{name = "Perms: ",value = "manageMessages"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageMessages"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"number",
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if tonumber(args[1]) and tonumber(args[1]) > 101 then
|
||||||
|
msg:reply("Search limit is too high")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local messages = {}
|
||||||
|
msg.channel:getMessages(args[1]):forEach(function(v) messages[#messages+1] = v.id end)
|
||||||
|
msg.channel:bulkDelete(messages)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["wipe-user"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Wipe user messages",
|
||||||
|
description = "Searches and deletes all messages of a specific user in a specified range",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "wipe-user <range> <user mention or id>"},
|
||||||
|
{name = "Perms: ",value = "manageMessages"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageMessages"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"number",
|
||||||
|
"member"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if tonumber(args[1]) and tonumber(args[1]) > 101 then
|
||||||
|
msg:reply("Search limit is too high")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local messages = {}
|
||||||
|
local target = args[2].user
|
||||||
|
msg.channel:getMessages(args[1]):forEach(function(v)
|
||||||
|
if v.author.id == target.id then
|
||||||
|
messages[#messages+1] = v.id
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
msg.channel:bulkDelete(messages)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["wipe-pattern"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Wipe by pattern",
|
||||||
|
description = "Searches for a specific pattern in a range of messages, and wipes if certain conditions are met",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "wipe-pattern <range> <pattern>"},
|
||||||
|
{name = "Perms: ",value = "manageMessages"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageMessages"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"number",
|
||||||
|
"string"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if tonumber(args[1]) and tonumber(args[1]) > 101 then
|
||||||
|
msg:reply("Search limit is too high")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local messages = {}
|
||||||
|
msg.channel:getMessages(args[1]):forEach(function(v)
|
||||||
|
if v.content:find(args[2],1,true) then
|
||||||
|
messages[#messages+1] = v.id
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
msg.channel:bulkDelete(messages)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["kick"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Kick a member",
|
||||||
|
description = "Self-descriptive",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "kick <member> [<reason>]"},
|
||||||
|
{name = "Perms: ",value= "kickMembers"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"kickMembers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local member = args[1]
|
||||||
|
signals:emit("kick",function(args)
|
||||||
|
if args[1] and member.name:find(args[1],1,true) then
|
||||||
|
return true
|
||||||
|
elseif not args[1] then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,{
|
||||||
|
user = member.id,
|
||||||
|
name = member.name,
|
||||||
|
reason = args[2]
|
||||||
|
})
|
||||||
|
member:kick(args[2])
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["ban"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Ban a member",
|
||||||
|
description = "Self-descriptive",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "ban <member> [<reason> [<days>]]"},
|
||||||
|
{name = "Perms: ",value= "banMembers"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"banMembers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local member = args[1]
|
||||||
|
signals:emit("kick",function(args)
|
||||||
|
if args[1] and member.name:find(args[1],1,true) then
|
||||||
|
return true
|
||||||
|
elseif not args[1] then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end,{
|
||||||
|
user = member.id,
|
||||||
|
name = member.name,
|
||||||
|
reason = args[2],
|
||||||
|
days = args[3]
|
||||||
|
})
|
||||||
|
member:ban(args[2],tonumber(args[3]))
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["purge"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Purge bot messages",
|
||||||
|
description = "If a number is provided, the bot will search through that amount of messages, or through 100 of them by default",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "ban <member> [<reason> [<days>]]"},
|
||||||
|
{name = "Perms: ",value= "manageMessages"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageMessages"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local messages = {}
|
||||||
|
if tonumber(args[1]) and tonumber(args[1]) > 101 then
|
||||||
|
msg:reply("Search limit is too high")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
msg.channel:getMessages(tonumber(args[1]) or 100):forEach(function(v)
|
||||||
|
if (v.author.id == client.user.id) or (v.content:find(globals.prefix)==1) then
|
||||||
|
messages[#messages+1] = v.id
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
msg.channel:bulkDelete(messages)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["warn"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Warn a user",
|
||||||
|
descriptions = "Warnings by themselves don't do any punishment to the user, but they allow managing users",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "warn <user> <reason>"},
|
||||||
|
{name = "Perms: ",value = "kickMembers"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"kickMembers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member",
|
||||||
|
"string"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local reason = table.concat(args," ",2)
|
||||||
|
warn(args[1].id,reason)
|
||||||
|
msg:reply({embed = {
|
||||||
|
title = "User "..args[1].name.." warned",
|
||||||
|
description = "Reason: ```"..reason.."```"
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["warns"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "List warnings",
|
||||||
|
descriptions = "self-descriptive",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "warns <member> [<page>]"},
|
||||||
|
{name = "Perms: ",value = "kickMembers"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"kickMembers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member",
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local page = (tonumber(args[2]) or 1)-1
|
||||||
|
local new_embed = {
|
||||||
|
title = "Warnings for "..args[1].name,
|
||||||
|
fields = {}
|
||||||
|
}
|
||||||
|
if page < 0 then
|
||||||
|
new_embed.description = "Page "..page.." not found, reverting to first page"
|
||||||
|
page = 0
|
||||||
|
end
|
||||||
|
if segment.warns[tostring(args[1].id)] and #segment.warns[tostring(args[1].id)] > 0 then
|
||||||
|
for I = 1+(page*5),5+(page*5) do
|
||||||
|
local warn = segment.warns[tostring(args[1].id)][I]
|
||||||
|
if warn then
|
||||||
|
table.insert(new_embed.fields,{name = "ID: "..tostring(I),value = warn})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
msg:reply({embed = new_embed})
|
||||||
|
else
|
||||||
|
msg:reply("This user has no warnings")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["unwarn"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Revoke a warning issued to a user",
|
||||||
|
descriptions = "self-descriptive",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "unwarn <user> [<warn id>]"},
|
||||||
|
{name = "Perms: ",value = "kickMembers"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"kickMembers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member",
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local warn_id = (tonumber(args[2]) or 1)
|
||||||
|
if segment.warns[tostring(args[1].id)][warn_id] then
|
||||||
|
table.remove(segment.warns[tostring(args[1].id)],warn_id)
|
||||||
|
msg:reply("Revoked warning #"..warn_id)
|
||||||
|
else
|
||||||
|
msg:reply("No warning with id "..warn_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["add-role"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Give some specific user a role",
|
||||||
|
descriptions = "self-descriptive",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "unwarn <member> <role>"},
|
||||||
|
{name = "Perms: ",value = "manageRoles"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageRoles"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member",
|
||||||
|
"role"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
args[1]:addRole(tostring(args[2].id))
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["remove-role"] = {
|
||||||
|
help = {embed={
|
||||||
|
title = "Revoke a role from a user",
|
||||||
|
descriptions = "self-descriptive",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "remove-role <member> <role>"},
|
||||||
|
{name = "Perms: ",value = "manageRoles"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"manageRoles"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"member",
|
||||||
|
"role"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
args[1]:removeRole(tostring(args[2].id))
|
||||||
|
end
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
events:on("memberUpdate",function(member)
|
||||||
|
if segment.setnames[tostring(member.id)] and member.nickname ~= segment.setnames[tostring(member.id)] then
|
||||||
|
member:setNickname(segment.setnames[tostring(member.id)])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
--old automod code
|
||||||
|
--[[
|
||||||
|
events:on("messageCreate",function(msg)
|
||||||
|
if segment.settings.automod.status then
|
||||||
|
local trigger = ""
|
||||||
|
for k,v in pairs(segment.settings.automod.list) do
|
||||||
|
if msg.content:find(v) and msg.author ~= client.user then
|
||||||
|
trigger = trigger..v..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if trigger ~= "" then
|
||||||
|
full_text,author = msg.content.."",msg.author
|
||||||
|
msg:delete()
|
||||||
|
msg.author:send("The words \""..trigger.."\" are banned on this server.\nThis is the text that these words were found in: ```"..full_text.."```")
|
||||||
|
if segment.settings.automod.punishment == "kick" then
|
||||||
|
msg.author:kick("Usage of banned words")
|
||||||
|
elseif segment.settings.automod.punishment == "warn" then
|
||||||
|
warn(msg.author.id,"Usage of banned words",msg.guild)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
]]
|
||||||
|
return segment
|
|
@ -0,0 +1,340 @@
|
||||||
|
local segment = {}
|
||||||
|
local emulate = require("emulate")({
|
||||||
|
client = client,
|
||||||
|
discordia = discordia,
|
||||||
|
})
|
||||||
|
local file = require("file")
|
||||||
|
file.activate_json(require("json"))
|
||||||
|
local guild = client:getGuild(id)
|
||||||
|
segment.pivots = file.readJSON("./servers/"..id.."/reactions.json",{})
|
||||||
|
local getEmoji = function(id)
|
||||||
|
local emoji = guild:getEmoji(id:match("(%d+)[^%d]*$"))
|
||||||
|
if emoji then
|
||||||
|
return emoji
|
||||||
|
else
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function count(tab)
|
||||||
|
local n = 0
|
||||||
|
for k,v in pairs(tab) do
|
||||||
|
n = n + 1
|
||||||
|
end
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
|
||||||
|
segment.commands = {
|
||||||
|
["pivot"] = {
|
||||||
|
help = {
|
||||||
|
title = "Select a pivot message to manipulate",
|
||||||
|
description = "Pivot is like a message selector which allows easy reaction manipulations",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "pivot <message link>"},
|
||||||
|
{name = "Perms: ",valeu = "Administartor"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"messageLink"
|
||||||
|
},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if segment.pivot and count(segment.pivot.buttons) == 0 then
|
||||||
|
segment.pivots[segment.pivot.message] = nil
|
||||||
|
end
|
||||||
|
local message = args[1]
|
||||||
|
if not message then
|
||||||
|
msg:reply("Couldn't find message with id "..args[2])
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if not segment.pivots[message.id] then
|
||||||
|
segment.pivots[message.id] = {}
|
||||||
|
segment.pivots[message.id].message = message.id
|
||||||
|
segment.pivots[message.id].channel = message.channel.id
|
||||||
|
segment.pivots[message.id].buttons = {}
|
||||||
|
end
|
||||||
|
segment.pivot = segment.pivots[message.id]
|
||||||
|
msg:reply("Pivot message set to "..message.link)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["role-toggle"] = {
|
||||||
|
help = {
|
||||||
|
title = "Add a simple role switch to the pivot",
|
||||||
|
description = "Note: you cannot assign more than one role to a single reaction",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "role-toggle <emoji> <role ping or role id>"},
|
||||||
|
{name = "Perms: ",value = "administrator"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"string",
|
||||||
|
"role",
|
||||||
|
},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if not segment.pivot then
|
||||||
|
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local emoji = getEmoji(args[1])
|
||||||
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
|
if not channel then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
|
if not message then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local grabEmoji = function(reaction)
|
||||||
|
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
||||||
|
type = "role-toggler",
|
||||||
|
role = tostring(args[2].id)
|
||||||
|
}
|
||||||
|
msg:reply("Role toggler added successfully")
|
||||||
|
end
|
||||||
|
message:removeReaction(emoji,client.user.id)
|
||||||
|
client:once("reactionAdd",grabEmoji)
|
||||||
|
if not message:addReaction(emoji) then
|
||||||
|
client:removeListener("reactionAdd",grabEmoji)
|
||||||
|
msg:reply("Couldn't add reaction - emoji might be invalid")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["remove-reaction"] = {
|
||||||
|
help = {
|
||||||
|
title = "Remove a reaction from a pivot",
|
||||||
|
description = "If you don't specify a reaction to remove, the entire pivot for the message is removed automatically",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "remove-reaction <emoji>"},
|
||||||
|
{name = "Perms: ",value = "Administrator"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
|
if not channel then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
|
if not message then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if args[1] then
|
||||||
|
local emoji = getEmoji(args[1])
|
||||||
|
message:removeReaction(emoji,client.user.id)
|
||||||
|
segment.pivot.buttons[((type(emoji) == "table") and emoji.id) or emoji] = nil
|
||||||
|
msg:reply("Action successfully removed")
|
||||||
|
else
|
||||||
|
message:clearReactions()
|
||||||
|
segment.pivots[tostring(message.id)] = nil
|
||||||
|
segment.pivot = nil
|
||||||
|
msg:reply("Pivot successfully removed")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["toggle"] = {
|
||||||
|
help = {
|
||||||
|
title = "Add a toggle that runs specific commands",
|
||||||
|
description = "Note: you cannot assign more than one action to a single reaction \n``$user`` gets replaced with the id of the user that interacted with the reaction.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "toggle <emoji> <command-on> <command-off>"},
|
||||||
|
{name = "Perms: ",value = "administrator"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"string",
|
||||||
|
"string",
|
||||||
|
"string",
|
||||||
|
},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if not segment.pivot then
|
||||||
|
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local emoji = getEmoji(args[1])
|
||||||
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
|
if not channel then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
|
if not message then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local grabEmoji = function(reaction)
|
||||||
|
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
||||||
|
type = "toggler",
|
||||||
|
on = args[2],
|
||||||
|
off = args[3],
|
||||||
|
}
|
||||||
|
msg:reply("Toggler added successfully")
|
||||||
|
end
|
||||||
|
message:removeReaction(emoji,client.user.id)
|
||||||
|
client:once("reactionAdd",grabEmoji)
|
||||||
|
if not message:addReaction(emoji) then
|
||||||
|
client:removeListener("reactionAdd",grabEmoji)
|
||||||
|
msg:reply("Couldn't add reaction - emoji might be invalid")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["button"] = {
|
||||||
|
help = {
|
||||||
|
title = "Add a button that runs specific command when pressed",
|
||||||
|
description = "Note: you cannot assign more than one action to a single reaction \n``$user`` gets replaced with the id of the user that interacted with the reaction.",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "button <emoji> <command>"},
|
||||||
|
{name = "Perms: ",value = "administrator"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"string",
|
||||||
|
"string",
|
||||||
|
},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if not segment.pivot then
|
||||||
|
msg:reply("Pivot not selected. Use "..globals.prefix.."pivot to select it and then try again")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local emoji = getEmoji(args[1])
|
||||||
|
local channel = guild:getChannel(segment.pivot.channel)
|
||||||
|
if not channel then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local message = channel:getMessage(segment.pivot.message)
|
||||||
|
if not message then
|
||||||
|
msg:reply("Something went horribly wrong, but it's not your fault. This incident has been (hopefully) reported")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local grabEmoji = function(reaction)
|
||||||
|
segment.pivot.buttons[tostring(reaction.emojiId or reaction.emojiName)] = {
|
||||||
|
type = "button",
|
||||||
|
on = args[2],
|
||||||
|
}
|
||||||
|
msg:reply("Button added successfully")
|
||||||
|
end
|
||||||
|
message:removeReaction(emoji,client.user.id)
|
||||||
|
client:once("reactionAdd",grabEmoji)
|
||||||
|
if not message:addReaction(emoji) then
|
||||||
|
client:removeListener("reactionAdd",grabEmoji)
|
||||||
|
msg:reply("Couldn't add reaction - emoji might be invalid")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local buttonOn = function(message,hash,userID)
|
||||||
|
if not message then
|
||||||
|
log("ERROR","Attempted to find a deleted message")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if segment.pivots[tostring(message.id)] and userID ~= client.user.id then
|
||||||
|
local current_pivot = segment.pivots[tostring(message.id)]
|
||||||
|
if current_pivot.buttons[tostring(hash)] then
|
||||||
|
local current_button = current_pivot.buttons[tostring(hash)]
|
||||||
|
local new_content
|
||||||
|
if current_button.on then
|
||||||
|
new_content = current_button.on:gsub("%$user",userID)
|
||||||
|
end
|
||||||
|
if current_button.type == "role-toggler" then
|
||||||
|
guild:getMember(userID):addRole(current_button.role)
|
||||||
|
end
|
||||||
|
if current_button.type == "toggler" then
|
||||||
|
emulate.send(message,{
|
||||||
|
delete = function() end,
|
||||||
|
content = new_content
|
||||||
|
})
|
||||||
|
end
|
||||||
|
if current_button.type == "button" then
|
||||||
|
emulate.send(message,{
|
||||||
|
delete = function() end,
|
||||||
|
content = new_content
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local buttonOff = function(message,hash,userID)
|
||||||
|
if not message then
|
||||||
|
log("ERROR","Attempted to find a deleted message")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if segment.pivots[tostring(message.id)] and userID ~= client.user.id then
|
||||||
|
local current_pivot = segment.pivots[tostring(message.id)]
|
||||||
|
if current_pivot.buttons[tostring(hash)] then
|
||||||
|
local current_button = current_pivot.buttons[tostring(hash)]
|
||||||
|
local new_content
|
||||||
|
if current_button.off then
|
||||||
|
new_content = current_button.off:gsub("%$user",userID)
|
||||||
|
end
|
||||||
|
if current_button.type == "role-toggler" then
|
||||||
|
guild:getMember(userID):removeRole(current_button.role)
|
||||||
|
end
|
||||||
|
if current_button.type == "toggler" then
|
||||||
|
emulate.send(message,{
|
||||||
|
delete = function() end,
|
||||||
|
content = new_content
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
events:on("reactionAdd",function(reaction,userID)
|
||||||
|
local message = reaction.message
|
||||||
|
local hash = tostring(reaction.emojiId or reaction.emojiName)
|
||||||
|
buttonOn(message,hash,userID)
|
||||||
|
end)
|
||||||
|
|
||||||
|
events:on("reactionRemove",function(reaction,userID)
|
||||||
|
local message = reaction.message
|
||||||
|
local hash = tostring(reaction.emojiId or reaction.emojiName)
|
||||||
|
buttonOff(message,hash,userID)
|
||||||
|
end)
|
||||||
|
|
||||||
|
events:on("reactionAddUncached",function(channelId,messageId,hash,userId)
|
||||||
|
local message = client:getChannel(channelId):getMessage(messageId)
|
||||||
|
local hash = tostring(hash)
|
||||||
|
buttonOn(message,hash,userId)
|
||||||
|
end)
|
||||||
|
|
||||||
|
events:on("reactionRemoveUncached",function(channelId,messageId,hash,userId)
|
||||||
|
local message = client:getChannel(channelId):getMessage(messageId)
|
||||||
|
local hash = tostring(hash)
|
||||||
|
buttonOff(message,hash,userId)
|
||||||
|
end)
|
||||||
|
|
||||||
|
events:on("serverSaveConfig",function()
|
||||||
|
file.writeJSON("./servers/"..id.."/reactions.json",segment.pivots)
|
||||||
|
end)
|
||||||
|
|
||||||
|
return segment
|
|
@ -0,0 +1,120 @@
|
||||||
|
segment = {}
|
||||||
|
local check_perms = require("check_perms")
|
||||||
|
local fake_server = {
|
||||||
|
id = id
|
||||||
|
}
|
||||||
|
local file = require("file")
|
||||||
|
file.activate_json(require("json"))
|
||||||
|
local overlay = file.readJSON("./servers/"..id.."/overlay.json",{})
|
||||||
|
local cached_commands = {}
|
||||||
|
events:on("commandPoolUpdate",function()
|
||||||
|
local commands = plugins.get()["commands"]
|
||||||
|
for k,v in pairs(commands) do
|
||||||
|
if not cached_commands[k] then
|
||||||
|
if overlay[k] then
|
||||||
|
if not v.perms then
|
||||||
|
v.perms = {}
|
||||||
|
end
|
||||||
|
v.perms.users = overlay[k].users or v.perms.users
|
||||||
|
v.perms.roles = overlay[k].roles or v.perms.roles
|
||||||
|
end
|
||||||
|
cached_commands[k] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k,v in pairs(cached_commands) do
|
||||||
|
if not commands[k] then
|
||||||
|
cached_commands[k] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
events:on("serverSaveConfig",function()
|
||||||
|
file.writeJSON("./servers/"..id.."/overlay.json",overlay)
|
||||||
|
end)
|
||||||
|
|
||||||
|
segment.commands = {
|
||||||
|
["rules"] = {
|
||||||
|
args = {
|
||||||
|
"string",
|
||||||
|
"string",
|
||||||
|
},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local target,command = args[1],args[2]
|
||||||
|
local commands = plugins.get()["commands"]
|
||||||
|
if not commands[target] then
|
||||||
|
msg:reply("Target command not found")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = target
|
||||||
|
target = commands[target]
|
||||||
|
if command == "list" then
|
||||||
|
local roles = "```"
|
||||||
|
for k,v in pairs(target.perms.roles or {}) do
|
||||||
|
roles = roles..((v > 0 and "allow ") or (v < 0 and "disallow "))..k.."\n"
|
||||||
|
end
|
||||||
|
roles = roles.." ```"
|
||||||
|
local users = "```"
|
||||||
|
for k,v in pairs(target.perms.users or {}) do
|
||||||
|
users = users..((v > 0 and "allow ") or (v < 0 and "disallow "))..k.."\n"
|
||||||
|
end
|
||||||
|
users = users.." ```"
|
||||||
|
msg:reply({embed={
|
||||||
|
title = "Custom permissions for command ``"..name.."``",
|
||||||
|
fields = {
|
||||||
|
{name = "Roles",value = roles},
|
||||||
|
{name = "Users",value = users}
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
else
|
||||||
|
if not check_perms(fake_server,target,msg,require("discordia")) then
|
||||||
|
msg:reply("You don't have a high enough permission to change rules for this command")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local type,id = args[3],args[4]
|
||||||
|
if not id then
|
||||||
|
msg:reply("Type and ID are needed to create a proper rule")
|
||||||
|
end
|
||||||
|
if (type ~= "user") and (type ~= "role") then
|
||||||
|
msg:reply("Type can only be ``user`` or ``role``")
|
||||||
|
end
|
||||||
|
id = id:match("%d+")
|
||||||
|
local state = 0
|
||||||
|
if command == "allow" then
|
||||||
|
state = 1
|
||||||
|
elseif command == "disallow" then
|
||||||
|
state = -1
|
||||||
|
elseif command == "reset" then
|
||||||
|
state = nil
|
||||||
|
end
|
||||||
|
if not overlay[name] then
|
||||||
|
overlay[name] = {}
|
||||||
|
overlay[name].users = {}
|
||||||
|
overlay[name].roles = {}
|
||||||
|
end
|
||||||
|
if not target.perms then
|
||||||
|
target.perms = {}
|
||||||
|
end
|
||||||
|
if type == "user" then
|
||||||
|
if not target.perms.users then
|
||||||
|
target.perms.users = {}
|
||||||
|
end
|
||||||
|
target.perms.users[id] = state
|
||||||
|
overlay[name].users[id] = state
|
||||||
|
elseif type == "role" then
|
||||||
|
if not target.perms.roles then
|
||||||
|
target.perms.roles = {}
|
||||||
|
end
|
||||||
|
target.perms.roles[id] = state
|
||||||
|
overlay[name].roles[id] = state
|
||||||
|
end
|
||||||
|
msg:reply("Changes applied.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segment
|
|
@ -0,0 +1,362 @@
|
||||||
|
--haha yes time to make cron in lua
|
||||||
|
local segment = {}
|
||||||
|
segment.help = "Add tasks to be executed later"
|
||||||
|
local file = require("file")
|
||||||
|
file.activate_json(require("json"))
|
||||||
|
local utils = require("bot_utils")
|
||||||
|
local emulate = require("emulate")({
|
||||||
|
client = client,
|
||||||
|
discordia = discordia
|
||||||
|
})
|
||||||
|
segment.name = "task"
|
||||||
|
local preload_tab = file.readJSON("./servers/"..id.."/crontab.json",{})
|
||||||
|
segment.tab = {}
|
||||||
|
globals.utc = globals.utc or 0
|
||||||
|
globals.utc_minutes = globals.utc_minutes or 0
|
||||||
|
segment.coroutines = {}
|
||||||
|
local absolute_fake_generator = require("absolute_fake")
|
||||||
|
local function cronTime(time)
|
||||||
|
if type(time) ~= "string" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local mask = {60,24,32,13}
|
||||||
|
local tokens = {}
|
||||||
|
local err = false
|
||||||
|
time:gsub("[%d%*]+",function(c) table.insert(tokens,c) end,4)
|
||||||
|
for I = 1,4 do --check if date/time format matches
|
||||||
|
if not ((tokens[I]:match("%d+") and tonumber(tokens[I]) < mask[I]) or ((tokens[I] == "*") and (I > 1))) then
|
||||||
|
err = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not err then
|
||||||
|
return tokens
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getFakeMessageOf(channel,member,content)
|
||||||
|
return absolute_fake_generator(client,discordia,member,channel,id,content)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addEventTask(task)
|
||||||
|
if task.event and task.channel and task.member then
|
||||||
|
task.coroutineID = math.random(1000000000,9999999999)
|
||||||
|
while segment.coroutines[task.coroutineID] do
|
||||||
|
task.coroutineID = math.random(1000000000,9999999999)
|
||||||
|
end
|
||||||
|
local taskID = #segment.tab+1
|
||||||
|
segment.coroutines[task.coroutineID] = function(check,args)
|
||||||
|
local check_func = ((type(check) == "function") and check) or (function() return true end)
|
||||||
|
if (not task.args) or (type(task.args) == "table" and check_func(task.args)) then
|
||||||
|
local content = task.task
|
||||||
|
for k,v in pairs(args or {}) do
|
||||||
|
content = content:gsub("%$"..k,tostring(v))
|
||||||
|
end
|
||||||
|
local dupeable = getFakeMessageOf(task.channel,task.member)
|
||||||
|
if not dupeable then
|
||||||
|
log("ERROR","Failed to dupe a message properly")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
emulate.send(dupeable,{
|
||||||
|
content = content,
|
||||||
|
delete = function() end
|
||||||
|
})
|
||||||
|
if task.once then
|
||||||
|
signals:removeListener(task.event,segment.coroutines[task.coroutineID])
|
||||||
|
table.remove(segment.tab,taskID)
|
||||||
|
segment.coroutines[task.coroutineID] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
signals:on(task.event,segment.coroutines[task.coroutineID])
|
||||||
|
table.insert(segment.tab,task)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addTimeTask(task)
|
||||||
|
if type(task.time) == "table" then
|
||||||
|
table.insert(segment.tab,task)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in pairs(preload_tab) do
|
||||||
|
if v.type == "event" then
|
||||||
|
addEventTask(v)
|
||||||
|
else
|
||||||
|
addTimeTask(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
segment.commands = {
|
||||||
|
["task"] = {
|
||||||
|
help = {embed = {
|
||||||
|
title = "Add tasks",
|
||||||
|
description = "Tasks are like cron tasks, in a sense that you specify when to execute them and what command to execute",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "task (\"minute hour day month\" or @<event name> \"argument1\" \"argument2\") \"command\""},
|
||||||
|
{name = "Perms: ",value = "Administrator"},
|
||||||
|
{name = "Opts: ",value = [[
|
||||||
|
--description=\"description here\" - self-descriptive
|
||||||
|
--once - remove the task after completion
|
||||||
|
]]},
|
||||||
|
{name = "Examples: ",value = [[
|
||||||
|
``task "5 10 * *" "]]..globals.prefix..[[speak hi"`` -- sends "hi" to the current channel at 10:05 every day every month
|
||||||
|
``task "5 10 15 *" "]]..globals.prefix..[[speak hi"`` -- sends "hi" to the current channel at 10:05 every 15th day of the month
|
||||||
|
``task --once "5 10 15 *" "]]..globals.prefix..[[speak hi"`` -- same as before, except the task gets removed after sending the message
|
||||||
|
additional examples can be found at https://github.com/yessiest/SuppaBot/wiki/Tasks
|
||||||
|
]]}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"string",
|
||||||
|
"string"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local command = args[#args]
|
||||||
|
if args[1]:match("^@%w+") then
|
||||||
|
local event = args[1]:match("^@(%w+)")
|
||||||
|
local conditions = utils.slice(args,2,#args-1)
|
||||||
|
local status = addEventTask({
|
||||||
|
type = "event",
|
||||||
|
channel = tostring(msg.channel.id),
|
||||||
|
member = tostring(msg.member.id),
|
||||||
|
event = event,
|
||||||
|
args = conditions,
|
||||||
|
task = command,
|
||||||
|
description = opts["description"] or "",
|
||||||
|
once = opts["once"]
|
||||||
|
})
|
||||||
|
if status then
|
||||||
|
msg:reply("Task "..(#segment.tab).." added")
|
||||||
|
else
|
||||||
|
msg:reply("Failed to add task")
|
||||||
|
end
|
||||||
|
elseif args[1]:match("^ ?%d+ [%d*]+ [%d*]+ [%d*]+ ?$") then
|
||||||
|
local status = addTimeTask({
|
||||||
|
type = "time",
|
||||||
|
time = cronTime(args[1]:match("^ ?%d+ [%d*]+ [%d*]+ [%d*]+ ?$")),
|
||||||
|
channel = tostring(msg.channel.id),
|
||||||
|
member = tostring(msg.member.id),
|
||||||
|
task = command,
|
||||||
|
description = opts["description"] or "",
|
||||||
|
once = opts["once"]
|
||||||
|
})
|
||||||
|
if status then
|
||||||
|
msg:reply("Task "..(#segment.tab).." added")
|
||||||
|
else
|
||||||
|
msg:reply("Failed to add task")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
msg:reply("Syntax error")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["tasks"] = {
|
||||||
|
help = {embed = {
|
||||||
|
title = "List all tasks",
|
||||||
|
description = "Bold white text is conditions for the task, code block is the command to be executed",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "tasks"},
|
||||||
|
{name = "Perms: ",value = "Administrator"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
msg:reply({embed = {
|
||||||
|
title = "Tasks: ",
|
||||||
|
fields = (function()
|
||||||
|
local output = {}
|
||||||
|
for k,v in pairs(segment.tab) do
|
||||||
|
if v.type == "event" then
|
||||||
|
table.insert(output,{
|
||||||
|
name = tostring(k)..": @"..v.event.." "..table.concat(v.args," "),
|
||||||
|
value = "```"..v.task.."```\n"..tostring(v.description),
|
||||||
|
inline = true
|
||||||
|
})
|
||||||
|
elseif v.type == "time" then
|
||||||
|
table.insert(output,{
|
||||||
|
name = tostring(k)..": "..table.concat(v.time," "),
|
||||||
|
value = "```"..v.task.."```\n"..tostring(v.description),
|
||||||
|
inline = true
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return output
|
||||||
|
end)()
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["task-remove"] = {
|
||||||
|
help = {embed = {
|
||||||
|
title = "Remove a task",
|
||||||
|
description = "That one is self-descriptive",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "remove-task <task id>"},
|
||||||
|
{name = "Perms: ",value = "Administrator"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"number"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if segment.tab[args[1]] then
|
||||||
|
local task = segment.tab[args[1]]
|
||||||
|
if task.type == "event" then
|
||||||
|
signals:removeListener(task.event,segment.coroutines[task.coroutineID])
|
||||||
|
segment.coroutines[task.coroutineID] = nil
|
||||||
|
end
|
||||||
|
table.remove(segment.tab,args[2])
|
||||||
|
msg:reply("Task "..args[1].." removed")
|
||||||
|
else
|
||||||
|
msg:reply("Task "..args[1].." not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["utc"] = {
|
||||||
|
help = {embed = {
|
||||||
|
title = "Set the UTC time offset",
|
||||||
|
description = "If your UTC time offset is x:45 or x:30 simply add \":30\" or \"45\" to the number accordingly",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "utc <hour>[:<minute>]"},
|
||||||
|
{name = "Perms: ",value = "Administrator"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
perms = {
|
||||||
|
perms = {
|
||||||
|
"administrator"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args = {
|
||||||
|
"string"
|
||||||
|
},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
if args[1]:match("^%d+$") then
|
||||||
|
globals.utc = tonumber(args[1]:match("^(%d+)$"))
|
||||||
|
msg:reply("UTC offset set")
|
||||||
|
elseif args[1]:match("^%d+:%d+$") then
|
||||||
|
globals.utc = tonumber(args[1]:match("^(%d+):%d+$"))
|
||||||
|
globals.utc_minutes = tonumber(args[1]:match("^%d+:(%d+)$"))
|
||||||
|
msg:reply("UTC offset set")
|
||||||
|
else
|
||||||
|
msg:reply("Invalid syntax")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
["time"] = {
|
||||||
|
help = {embed = {
|
||||||
|
title = "View the internal bot time",
|
||||||
|
description = "If you've set a time offset previously, it will get accounted",
|
||||||
|
fields = {
|
||||||
|
{name = "Usage: ",value = "time"},
|
||||||
|
{name = "Perms: ",value = "all"},
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
exec = function(msg,args,opts)
|
||||||
|
local utc_time = os.date("%c",os.time()+(3600)*(globals.utc-4)+(60)*(globals.utc_minutes))
|
||||||
|
msg:reply(utc_time)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
segment.unload = function()
|
||||||
|
for k,v in pairs(segment.tab) do
|
||||||
|
if v.type == "event" then
|
||||||
|
signals:removeListener(v.event,segment.coroutines[v.coroutineID])
|
||||||
|
segment.coroutines[v.coroutineID] = nil
|
||||||
|
segment.tab[k] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check_time(date,crondate)
|
||||||
|
local mask = {"min","hour","day","month"}
|
||||||
|
local output = true
|
||||||
|
for I = 1,4 do
|
||||||
|
if not (tonumber(crondate[I]) == tonumber(date[mask[I]]) or crondate[I] == "*") then
|
||||||
|
output = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
events:on("messageCreate",function(msg)
|
||||||
|
signals:emit("message",function(args)
|
||||||
|
local output = true
|
||||||
|
if not args[1] then
|
||||||
|
output = true
|
||||||
|
elseif msg.content:find(args[1],1,true) then
|
||||||
|
output = true
|
||||||
|
else
|
||||||
|
output = false
|
||||||
|
end
|
||||||
|
if output and (tostring(msg.author.id) == tostring(client.user.id)) then
|
||||||
|
output = false
|
||||||
|
end
|
||||||
|
if output and (msg.emulated) then
|
||||||
|
output = false
|
||||||
|
end
|
||||||
|
if output and (not args[2]) then
|
||||||
|
output = true
|
||||||
|
elseif output and (msg.author.name:find(args[2],1,true)) then
|
||||||
|
output = true
|
||||||
|
else
|
||||||
|
output = false
|
||||||
|
end
|
||||||
|
return output
|
||||||
|
end,{
|
||||||
|
user = msg.author.id,
|
||||||
|
content = msg.content,
|
||||||
|
name = msg.author.name,
|
||||||
|
ctxid = msg.id
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end)
|
||||||
|
|
||||||
|
events:on("serverSaveConfig",function()
|
||||||
|
file.writeJSON("./servers/"..id.."/crontab.json",segment.tab)
|
||||||
|
end)
|
||||||
|
|
||||||
|
events:on("clock",function()
|
||||||
|
if tonumber(os.time())%60 == 30 then
|
||||||
|
local utc_time = os.date("*t",os.time()+(3600)*(globals.utc-4)+(60)*(globals.utc_minutes))
|
||||||
|
for k,v in pairs(segment.tab) do
|
||||||
|
if (v.type == "time") and check_time(utc_time,v.time) then
|
||||||
|
emulate_message = getFakeMessageOf(v.channel,v.member)
|
||||||
|
if emulate_message then
|
||||||
|
emulate.send(emulate_message,{
|
||||||
|
content = v.task,
|
||||||
|
delete = function() end
|
||||||
|
})
|
||||||
|
else
|
||||||
|
log("ERROR","There are no messages to dupe a new one from")
|
||||||
|
end
|
||||||
|
if v.once then
|
||||||
|
table.remove(segment.tab,k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return segment
|
Loading…
Reference in New Issue