diff --git a/plugins/512mbsc/help.lua b/plugins/512mbsc/help.lua new file mode 100644 index 0000000..3f58ecb --- /dev/null +++ b/plugins/512mbsc/help.lua @@ -0,0 +1,18 @@ +return { + ["scc-score"] = { embed = { + title = "Check SCC score", + description = "nuff said.", + fields = { + {name = "Usage: ", value = "scc-score []"}, + {name = "Perms: ", value = "any"}, + } + }}, + ["scc-rules"] = { embed = { + title = "Change SCC system rules", + description = "If no arguments are given the command displays rules instead", + fields = { + {name = "Usage: ", value = "scc-rules [ ]"}, + {name = "Perms: ", value = "administrator"}, + } + }} +} diff --git a/plugins/512mbsc/init.lua b/plugins/512mbsc/init.lua index 5e98010..5391229 100644 --- a/plugins/512mbsc/init.lua +++ b/plugins/512mbsc/init.lua @@ -1,340 +1,143 @@ 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 = {} +local plugin = import("classes.plugin")("scc") +local sql = import("sqlite3") +local db = sql.open(server.config_path.."scc.sqlite") +local cache = { + users = {}, + rules = {}, + usermsg = {} +} + +if not db:rowexec("SELECT name FROM sqlite_master WHERE type='table' AND name='score'") then + db:exec [[ +CREATE TABLE score(user TEXT PRIMARY KEY, score INTEGER); +CREATE TABLE rules(rulename TEXT NOT NULL PRIMARY KEY, value TEXT); +INSERT INTO rules VALUES("bump", 50); +INSERT INTO rules VALUES("message", 5); +INSERT INTO rules VALUES("bumpchannel","0"); +INSERT INTO rules VALUES("bumpbot","0"); +]] end -client:on("messageCreate",function(msg) - last_message_arrived:reset() - last_message_arrived:start() +local update_entry = db:prepare([[INSERT INTO score VALUES(?, ?) ON CONFLICT(user) DO UPDATE SET score = ?]]) +local update_rules = db:prepare([[UPDATE rules SET value = ? WHERE rulename = ?]]) +local get_rule = db:prepare("SELECT value FROM rules WHERE rulename = ?") +cache.rules.message = tonumber(get_rule:reset():bind("message"):step()[1]) +cache.rules.bump = tonumber(get_rule:reset():bind("bump"):step()[1]) +cache.rules.bumpchannel = get_rule:reset():bind("bumpchannel"):step()[1] +cache.rules.bumpbot = get_rule:reset():bind("bumpbot"):step()[1] +local score_init = db:exec("SELECT * FROM score;") +if score_init then + for id,uid in ipairs(score_init.user) do + cache.users[uid] = tonumber(score_init.score[id]) + end +end + +local timer = discordia.Clock() +timer:on("min", function() + if os.date("*t")["min"]%5 == 0 then + log("SCC","Saving SCC data") + for uname,uscore in pairs(cache.users) do + update_entry:reset():bind(uname,uscore,uscore):step() + end + end +end) +timer:start(true) + +events:on("typingStart",function(userid,channelid) + if cache.rules.bumpchannel == tostring(channelid) then + cache.last_typing_user = userid + end end) -local prefix -for k,v in pairs(command_handler:get_prefixes()) do - if (not prefix) or prefix:len() > v:len() then - prefix = v - end -end - -local function add_alias(name,comm,prefix,description) - 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) - 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) +events:on("messageCreate",function(msg) + if (not msg.author.bot) and + msg.content and + (msg.content:len() > 10) then + local stripped_content = msg.content:match("^%s*(.-)%s*$") + if not (stripped_content == cache.usermsg[msg.author.id]) then + cache.users[msg.author.id] = (cache.users[msg.author.id] or 0) + + cache.rules.message end - command_handler:handle(fake_message(msg,{ - content = aftersub - })) - end, - options = { - prefix = prefix, - custom = true - } - }) - plugin:add_command(aliases[name]) - return true - else - return false - end -end - -local function remove_alias(name) - if config.aliases[name] then - config.aliases[name] = nil - plugin:remove_command(aliases[name]) - return true - else - 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 + cache.usermsg[msg.author.id] = stripped_content end - if substitution == "" then - substitution = "<\\@"..obj..id..">" + if msg.author.bot and (msg.author.id == tostring(cache.rules.bumpbot)) then + if cache.last_typing_user and msg.embed and msg.embed.description and msg.embed.description:match("Bump done") then + cache.users[cache.last_typing_user] = (cache.users[cache.last_typing_user] or 0) + cache.rules.bump + end end - text = text:gsub("<@(%D*)"..id..">",substitution) - end - text = text:gsub("@everyone","") - return text -end +end) -for k,v in pairs(config.aliases) do - commdata = v - if type(v) == "string" then --legacy format conversion - commdata = {comm = v, prefix = false} - end - add_alias(k,commdata.comm,commdata.prefix) -end - -local prefix = command("prefix",{ - help = "Set prefix", - usage = "prefix [(add | remove | list (default)) []]", - users = { - [client.owner.id] = 1 - }, - roles = { - ["747042157185073182"] = 1 - }, - perms = { - "administrator" - }, - exec = function(msg,args,opts) - local function list_prefixes(msg) - local prefixes = "" - for k,v in pairs(command_handler:get_prefixes()) do - prefixes = prefixes..v.."\n" - end - msg:reply({embed = { - title = "Prefixes for this server", - description = prefixes - }}) - 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") +local c_sccrules = command("scc-rules", { + category = "Utilities", + perms = { + "administrator" + }, + exec = function(msg,args,opts) + if not args[1] then + msg:reply({embed = { + title = "Current score rules: ", + fields = { + { name = "message", value = tostring(cache.rules.message) }, + { name = "bump", value = tostring(cache.rules.bump) }, + { name = "bumpbot", value = tostring(cache.rules.bumpbot) }, + { name = "bumpchannel", value = tostring(cache.rules.bumpchannel) } + } + }}) else - msg:reply(err) + local valid_params = { + message = tonumber, + bump = tonumber, + bumpchannel = tostring, + bumpbot = tostring + } + if valid_params[args[1]] then + if valid_params[args[1]](args[2]) then + local value = valid_params[args[1]](args[2]) + cache.rules[args[1]] = value + update_rules:reset():bind(args[2],args[1]):step() + else + msg:reply("Invalid parameter: "..tostring(args[2])) + return false + end + else + msg:reply("Invalid rule name: "..tostring(args[1])) + return false + end + return true 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(c_sccrules) -local c_alias = command("alias", { - args = { - "string","string" - }, - perms = { - "administrator" - }, - exec = function(msg,args,opts) - 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].."``") - else - msg:reply("``"..args[1].."`` is already bound") - end - end -}) -plugin:add_command(c_alias) - -local c_unalias = command("unalias", { - args = { - "string" - }, - perms = { - "administrator" - }, - exec = function(msg,args,opts) - if remove_alias(args[1]) then - msg:reply("Removed the ``"..args[1].."`` alias") - else - msg:reply("No such alias") - end - end -}) -plugin:add_command(c_unalias) - -local c_aliases = command("aliases", { - exec = function(msg,args,opts) - msg:reply({embed = { - title = "Aliases for this server", - fields = (function() - local fields = {} - for k,v in pairs(config.aliases) do - table.insert(fields,{name = ((v["prefix"] and prefix) or "")..k,value = v["comm"]}) - end - return fields - end)() - }}) - end -}) -plugin:add_command(c_aliases) - -local c_ping = command("ping", { - exec = function(msg,args,opts) - local before = msg:getDate() - local reply = msg:reply("Pong!") - if not reply then - log("ERROR","Couldn't send the ping reply for some reason") - 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 -}) -plugin:add_command(c_ping) - -local c_about = command("about", { - exec = function(msg,args,opts) - local rand = math.random - local author = client:getUser("245973168257368076") - msg:reply({embed = { - title = "About 512mb.org bot", - thumbnail = { - url = client.user:getAvatarURL() - }, - 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.", - fields = { - {name = "Source Code: ",value = "https://github.com/512mb-xyz/512mb.org-bot"}, - {name = "Author: ",value = author.tag}, - {name = "Invite: ",value = "Not available yet"} - }, - footer = { - text = "For any information regarding the bot, contact yessiest on 512mb.org discord." - } - }}) - end -}) -plugin:add_command(c_about) - -local c_server = command("server", { - exec = function(msg,args,opts) - msg:reply({embed = { - thumbnail = { - url = msg.guild.iconURL - }, - title = msg.guild.name, - description = msg.guild.description, - fields = { - {name = "Members",value = msg.guild.totalMemberCount,inline = true}, - {name = "Owner",value = (msg.guild.owner and msg.guild.owner.user.tag..":"..msg.guild.owner.user.id),inline = true}, - {name = "Created At",value = os.date("!%c",msg.guild.createdAt).." (UTC+0)",inline = true}, - {name = "Text Channels",value = msg.guild.textChannels:count(),inline = true}, - {name = "Voice Channels",value = msg.guild.voiceChannels:count(),inline = true} - } - }}) - end, -}) -plugin:add_command(c_server) - -local c_user = command("user", { - exec = function(msg,args,opts) - local member = msg.guild:getMember((args[1] or ""):match("%d+")) or msg.guild:getMember(msg.author.id) - local roles = "" - for k,v in pairs(member.roles) do - roles = roles..v.mentionString.."\n" - end - msg:reply({embed = { - title = member.user.tag..":"..member.user.id, - thumbnail = { - url = member.user:getAvatarURL() - }, - fields = { - {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 = "Boosting",value = ((member.premiumSince and "Since "..member.premiumSince) or "No"),inline = true}, - {name = "Highest Role",value = member.highestRole.mentionString,inline = true}, - {name = "Roles",value = roles,inline = true} - } - }}) - end, -}) -plugin:add_command(c_user) - -local c_speak = command("speak", { - args = { - "string" - }, +local c_sccscore = command("scc-score", { + category = "Utilities", exec = function(msg,args,opts) - local text = purify_strings(msg, table.concat(args," ")) - if opts["unescape"] or opts["u"] then - text = text:gsub("\\","") + if not args[1] then + msg:reply({embed = { + title="Your score: "..tostring(cache.users[msg.author.id] or 0), + color = discordia.Color.fromHex("2FC02A").value + }}) + else + local user = msg.guild:getMember(args[1]:match("^%d*")) + if not user then + msg:reply("Invalid user") + return false + end + msg:reply({embed={ + title = tostring(user.name).."'s score: "..tostring(cache.users[user] or 0), + color = discordia.Color.fromHex("2FC02A").value + }}) end - msg:reply(text) - msg:delete() - end, + end }) -plugin:add_command(c_speak) - -local c_adminSpeak = command("adminSpeak", { - args = { - "string" - }, - exec = function(msg,args,opts) - local text = table.concat(args," ") - if opts["unescape"] or opts["u"] then - text = text:gsub("\\","") - end - msg:reply(text) - msg:delete() - end, - perms = { - "mentionEveryone" - } -}) -plugin:add_command(c_adminSpeak) - -local c_echo = command("echo",{ - args = { - "string" - }, - exec = function(msg,args,opts) - local text = purify_strings(msg, table.concat(args," ")) - if opts["unescape"] or opts["u"] then - text = text:gsub("\\","") - end - msg:reply(text) - end, -}) -plugin:add_command(c_echo) +plugin:add_command(c_sccscore) plugin.removal_callback = function() - for k,v in pairs(config.aliases) do - remove_alias(k) - end + for uname,uscore in pairs(cache.users) do + update_entry:reset():bind(uname,uscore,uscore):step() + end end local helpdb = import(plugin_path:sub(3,-1).."help") diff --git a/plugins/security/help.lua b/plugins/security/help.lua index 6bc69e5..b7a3ef1 100644 --- a/plugins/security/help.lua +++ b/plugins/security/help.lua @@ -25,6 +25,14 @@ return { {name = "Perms:",value = "kickMembers"}, } }}, + ["pardon"] = {embed={ + title = "Pardon a user", + description = "Like warn, but in reverse", + fields = { + {name = "Usage:",value = "pardon "}, + {name = "Perms:",value = "kickMembers"}, + } + }}, ["infractions"] = { embed = { title = "List user infractions", description = "Infractions include kicks, bans, mutes and warnings.", diff --git a/plugins/security/init.lua b/plugins/security/init.lua index bcb6093..82c353e 100644 --- a/plugins/security/init.lua +++ b/plugins/security/init.lua @@ -103,6 +103,46 @@ local warn = command("warn",{ }) plugin:add_command(warn) +local pardon = command("pardon",{ + category = "Security", + perms = { + "kickMembers" + }, + args = { + "member", + "number" + }, + exec = function(msg,args,opts) + local countst = db:prepare("SELECT id FROM infractions WHERE user = ? AND id = ?") + local inf = countst:reset():bind(tostring(args[1].id),args[2]):step() + local found = (inf ~= nil) + if not found then + msg:reply("No infraction "..tostring(args[2]).." found on user "..tostring(args[1].name)) + return false + end + local reasonst = db:prepare("SELECT desc, timestamp FROM infractions WHERE id = ?") + local infra = reasonst:reset():bind(args[2]):step() + if not infra then + msg:reply("Unknown id: "..tostring(args[2])) + return false + end + local reason = infra[1] + local timestamp = infra[2] + local rmst = db:prepare("DELETE FROM infractions WHERE id = ?") + rmst:reset():bind(args[2]):step() + msg:reply({embed = { + title = "User has been pardoned", + description = args[1].name.." has been pardoned for warning "..tostring(args[2]), + fields = { + { name = "Warning count: ", value = tostring(#inf-1)}, + { name = "Reason: ", value = reason }, + { name = "Timestamp: ", value = tostring(timestamp) } + }, + }}) + end +}) +plugin:add_command(pardon) + local infractions = command("infractions", { category = "Security", perms = {