fixed minor issues

This commit is contained in:
Yessiest 2021-11-27 02:24:53 +04:00
parent 1c50d56210
commit 0df6656d4f
12 changed files with 402 additions and 70 deletions

3
.gitignore vendored
View File

@ -1 +1,4 @@
/token
/servers
/discordia.log
/gateway.json

View File

@ -12,13 +12,14 @@ local server = import("classes.server-handler")
client:on("ready",function()
print("starting test")
local new_server = server(client,client:getGuild("640251445949759499"),{
autosave_frequency = 20,
autosave_frequency = 5,
default_plugins = {
"meta",
"help",
"plugins",
"esolang",
"tools"
"tools",
"reactions"
}
})
end)

View File

@ -1,29 +0,0 @@
2021-11-26 20:38:37 | [INFO] | Discordia 2.8.4
2021-11-26 20:38:37 | [INFO] | Connecting to Discord...
2021-11-26 20:38:38 | [INFO] | Authenticated as 512mb.org#1582
2021-11-26 20:38:38 | [INFO] | Launching shard 0 (1 out of 1)...
2021-11-26 20:38:39 | [INFO] | Shard 0 : Connected to wss://gateway.discord.gg
2021-11-26 20:38:39 | [INFO] | Shard 0 : Received HELLO
2021-11-26 20:38:39 | [INFO] | Shard 0 : Received READY
2021-11-26 20:42:01 | [INFO] | Discordia 2.8.4
2021-11-26 20:42:01 | [INFO] | Connecting to Discord...
2021-11-26 20:42:01 | [INFO] | Authenticated as 512mb.org#1582
2021-11-26 20:42:01 | [INFO] | Launching shard 0 (1 out of 1)...
2021-11-26 20:42:01 | [INFO] | Shard 0 : Connected to wss://gateway.discord.gg
2021-11-26 20:42:01 | [INFO] | Shard 0 : Received HELLO
2021-11-26 20:42:02 | [INFO] | Shard 0 : Received READY
2021-11-26 20:43:30 | [INFO] | Discordia 2.8.4
2021-11-26 20:43:30 | [INFO] | Connecting to Discord...
2021-11-26 20:43:30 | [INFO] | Authenticated as 512mb.org#1582
2021-11-26 20:43:30 | [INFO] | Launching shard 0 (1 out of 1)...
2021-11-26 20:43:31 | [INFO] | Shard 0 : Connected to wss://gateway.discord.gg
2021-11-26 20:43:31 | [INFO] | Shard 0 : Received HELLO
2021-11-26 20:43:31 | [INFO] | Shard 0 : Received READY
2021-11-26 20:49:51 | [INFO] | Discordia 2.8.4
2021-11-26 20:49:51 | [INFO] | Connecting to Discord...
2021-11-26 20:49:51 | [INFO] | Authenticated as 512mb.org#1582
2021-11-26 20:49:51 | [INFO] | Launching shard 0 (1 out of 1)...
2021-11-26 20:49:51 | [INFO] | Shard 0 : Connected to wss://gateway.discord.gg
2021-11-26 20:49:51 | [INFO] | Shard 0 : Received HELLO
2021-11-26 20:49:52 | [INFO] | Shard 0 : Received READY
2021-11-26 20:50:10 | [ERROR] | 400 - Bad Request : GET https://discord.com/api/v7/guilds/640251445949759499/members/nil

View File

@ -1 +0,0 @@
{"url":"wss://gateway.discord.gg","913818433748086784":{"owner":{"discriminator":"7452","public_flags":0,"id":"245973168257368076","username":"Yessiest","avatar":"f8e9fa5b64a0333da12b9ece6d636db3","flags":0},"timestamp":1637944718,"shards":1}}

View File

@ -90,8 +90,6 @@ function command_handler:get_commands_metadata()
return table_utils.deepcopy(self.command_meta)
end
function command_handler:handle(message)
print("msg: "..tostring(message.content))
print("author: "..tostring(message.author.name))
for name,command in pairs(self.command_pool) do
if command.options.regex then
if message.content:match(command.options.regex) then
@ -101,13 +99,13 @@ function command_handler:handle(message)
else
if command.options.prefix then
for _,prefix in pairs(self.prefixes) do
if message.content:find(prefix..name.."$") == 1 or message.content:find(prefix..name.."%s") then
if message.content:match("^"..prefix..name.."$") or message.content:match("^"..prefix..name.."%s") then
command:exec(message)
return
end
end
else
if message.content:find(name.."$") == 1 or message.content:find(name.."%s") then
if message.content:match("^"..name.."$") or message.content:match("^"..name.."%s") then
command:exec(message)
return
end

View File

@ -10,13 +10,29 @@ local file = import("file")
local json = import("json")
local core = import("core")
local emitter_proxy = import("classes.emitter-proxy")
local table_utils = import("table-utils")
local table_utils = import("table-utils")
function plugin_handler:__init(parent_server)
assert(parent_server,"server handler to assign the plugin handler to has not been provided")
self.server_handler = parent_server
self.plugins = {}
self.plugin_info = {}
self.plugin_paths = {}
self.server_handler.event_emitter:on("serverSaveConfig",function()
print("[SERVER] Saving plugins configs")
for name,plugin in pairs(self.plugins) do
self:save_plugin_config(name)
end
end)
end
function plugin_handler:load_plugin_config(name)
return file.readJSON(self.server_handler.config_path..name..".json",{})
end
function plugin_handler:save_plugin_config(name)
if self.plugins[name] then
file.writeJSON(self.server_handler.config_path..name..".json",self.plugins[name].__env.config)
end
end
function plugin_handler:add_plugin_folder(path)
@ -83,6 +99,7 @@ function plugin_handler:load(name)
command_handler = self.server_handler.command_handler,
plugin_handler = self.server_handler.plugin_handler,
log = function() end,
config = self:load_plugin_config(name),
import = import,
},{__index = _G})
local plugin_meta = self.plugin_info[name]
@ -108,7 +125,7 @@ function plugin_handler:load(name)
else
return false, "File specified as the main file is inaccessible"
end
end
end
function plugin_handler:unload(name)
if self.plugins[name] then

View File

@ -3,6 +3,7 @@ local plugin = class("Plugin")
function plugin:__init()
self.command_pool = {}
self.config = {}
end
function plugin:load(environment)

View File

@ -33,19 +33,19 @@ function server_handler:__init(client,guild,options)
self.plugin_handler = plugin_handler(self)
self.command_handler = command_handler(self)
self.id = guild.id
self.config = {}
--conifgurable properties
self.config_path = options.path or "./servers/%id/"
self.autosave = options.path or true
self.autosave_frequency = options.autosave_frequency or 10
self.plugin_search_paths = options.plugin_search_paths or {"./plugins/"}
self.default_plugins = options.default_plugins or {"test"}
self.default_prefixes = options.default_prefixes or {"<@!"..self.client.user.id..">","&"}
self.config_path = self.config_path:gsub("%id",self.id)
self.default_prefixes = options.default_prefixes or {"&","<@!"..self.client.user.id..">"}
self.config = {}
self.config_path = self.config_path:gsub("%%id",self.id)
self:load_config()
self.config["prefix"] = self.config["prefix"] or self.default_prefixes[1] or "(missing prefix)"
self.message_counter = 0
if 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
@ -74,7 +74,7 @@ function server_handler:__init(client,guild,options)
end
self.plugin_handler:update_plugin_info()
for _,plugin_name in pairs(self.default_plugins) do
print(self.plugin_handler:load(plugin_name))
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)
@ -82,19 +82,22 @@ function server_handler:__init(client,guild,options)
end
function server_handler:load_config(path)
print("[SERVER] Loading config")
if path then
self.config = file.readJSON(path,{})
else
self.config = file.readJSON(self.config_path.."config.json")
end
self.event_emitter:emit("serverLoadConfig",self.config)
end
function server_handler:save_config(path)
print("[SERVER] Saving config")
if path then
file.writeJSON(path,self.config)
else
file.writeJSON(self.config_path.."config.json",self.config)
end
self.event_emitter("serverSaveConfig")
self.event_emitter:emit("serverSaveConfig",self.config)
end
return server_handler

View File

@ -18,12 +18,13 @@ end
local function register_words(str,word_list)
local word_list = word_list or {}
str:gsub("%S+",function(word)
str:gsub("%S+",function(word)
if not word_list[word] then
word_list[word] = {}
end
local current_word = word_list[word]
str:gsub(escape(word) .. "%s+(%S+)",function(word2)
local escaped_word = escape(word)
str:gsub("%s+" .. escaped_word .. "%s+(%S+)",function(word2)
if not current_word[word2] then
current_word[word2] = {}
end
@ -33,7 +34,7 @@ local function register_words(str,word_list)
current_word[word2].occurences = current_word[word2].occurences + 1
end
end)
end)
end)
for k,v in pairs(word_list) do
word_list[k] = node(v)
end

View File

@ -1,5 +1,10 @@
local plugin_c = import("classes.plugin")
local plugin = import("classes.plugin")("debug")
local command = import("classes.command")
local plugin = plugin_c()
local save = command("save",{
help = "Force-save config data",
exec = function()
server:save_config()
end
})
plugin:add_command(save)
return plugin

View File

@ -1,13 +1,12 @@
segment = {}
segment.help = "This is a set of commands that add some features specific to this bot"
local map = {}
local aliases = {}
local fake_message = import("fake_message")
local last_message_arrived = discordia.Stopwatch()
local unixToString = import("unixToString")
local command = import("classes.command")
local plugin = import("classes.plugin")("meta")
if not config.aliases then
config.aliases = {}
end
client:on("messageCreate",function(msg)
last_message_arrived:reset()
@ -22,15 +21,17 @@ for k,v in pairs(command_handler:get_prefixes()) do
end
local function add_alias(name,comm,prefix,description)
if (not map[name]) then
map[name] = {comm = comm,prefix = prefix}
if (not aliases[name]) then
print("[ALIAS] Adding alias \""..name.."\" for \""..comm.."\"")
config.aliases[name] = {comm = comm,prefix = prefix}
aliases[name] = command(name,{
help = "Alias for ``"..comm.."``",
usage = ((prefix and globals.prefix) or "")..name,
exec = function(msg,args2,opts)
local str = msg.content:gsub(name.." ","")
aftersub = comm:gsub("%.%.%.",str)
aftersub = aftersub:gsub("%$prefix",prefix)
print("[ALIAS] Triggerting alias "..tostring(comm).." with args \""..tostring(msg.content).."\"")
local str = msg.content:gsub("^%S+ ?","")
aftersub = comm:gsub("%.%.%.",str or "")
aftersub = aftersub:gsub("%$prefix",prefix or "&")
local status,args = require("air").parse(str)
for k,v in pairs(args) do
aftersub = aftersub:gsub("([^\\])%$"..k,"%1"..v)
@ -52,8 +53,8 @@ local function add_alias(name,comm,prefix,description)
end
local function remove_alias(name)
if map[name] then
map[name] = nil
if config.aliases[name] then
config.aliases[name] = nil
plugin:remove_command(aliases[name])
return true
else
@ -86,7 +87,7 @@ local function purify_strings(msg,input)
return text
end
for k,v in pairs(import("file").readJSON("./servers/"..id.."/aliasmap.json",{})) do
for k,v in pairs(config.aliases) do
commdata = v
if type(v) == "string" then --legacy format conversion
commdata = {comm = v, prefix = false}
@ -180,7 +181,7 @@ local c_aliases = command("aliases", {
title = "Aliases for this server",
fields = (function()
local fields = {}
for k,v in pairs(map) do
for k,v in pairs(config.aliases) do
table.insert(fields,{name = ((v["prefix"] and prefix) or "")..k,value = v["comm"]})
end
return fields
@ -331,18 +332,16 @@ local c_echo = command("echo",{
plugin:add_command(c_echo)
plugin.removal_callback = function()
for k,v in pairs(map) do
for k,v in pairs(config.aliases) do
remove_alias(k)
end
end
local helpdb = import(plugin_path:sub(3,-1).."help")
plugin:for_all_commands(function(command)
command:set_help(helpdb[command.name])
end)
events:on("serverSaveConfig",function()
import("file").writeJSON("./servers/"..id.."/aliasmap.json",map)
if helpdb[command.name] then
command:set_help(helpdb[command.name])
end
end)
return plugin

334
plugins/reactions/init.lua Normal file
View File

@ -0,0 +1,334 @@
local file = require("file")
local guild = client:getGuild(id)
local fake_message = require("fake_message")
local command = import("classes.command")
local plugin = import("classes.plugin")("reactions")
local segment = {}
segment.pivots = config
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
local pivot = command("pivot",{
help = {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"}
}
}},
args = {
"messageLink"
},
perms = {
"administrator"
},
exec = function(msg,args,opts)
if segment.pivot and count(segment.pivot.buttons) == 0 then
print("[REACTIONS] Deleting pivot: "..tostring(segment.pivot.message))
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
print("[REACTIONS] Creating pivot: "..tostring(segment.pivot.message))
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
})
plugin:add_command(pivot)
local role_toggle = command("role-toggle",{
help = {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"}
}
}},
args = {
"string",
"role",
},
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
print("[REACTIONS] Adding role-toggle listener")
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
})
plugin:add_command(role_toggle)
local remove_reaction = command("remove-reaction",{
help = {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"}
}
}},
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
print("[REACTIONS] Removing reaction listener")
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
})
plugin:add_command(remove_reaction)
local toggle = command("toggle",{
help = {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"}
}
}},
args = {
"string",
"string",
"string",
},
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
print("[REACTIONS] Adding toggle listener")
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
})
plugin:add_command(toggle)
local button = command("button",{
help = {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"}
}
}},
args = {
"string",
"string",
},
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
print("[REACTIONS] Adding button listener")
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
})
plugin:add_command(button)
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
command_handler:handle(fake_message(message,{
delete = function() end,
content = new_content
}))
end
if current_button.type == "button" then
command_handler:handle(fake_message(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
command_handler:handle(fake_message(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)
return plugin