diff --git a/install_discordia.bat b/install_discordia.bat index bacc19a..407a56a 100644 --- a/install_discordia.bat +++ b/install_discordia.bat @@ -1,3 +1,3 @@ .\exes\lit.exe install SinisterRectus/discordia -.\exes\lit.exe install GitSparTV/discordia-slash -git clone https://github.com/Bilal2453/discordia-interactions.git ./deps/discordia-interactions \ No newline at end of file +git clone git@github.com:GitSparTV/discordia-slash.git ./deps/discordia-slash +git clone git@github.com:Bilal2453/discordia-interactions.git ./deps/discordia-interactions \ No newline at end of file diff --git a/src/MessageCommands/_Example.lua b/src/MessageCommands/_Example.lua new file mode 100644 index 0000000..0c51af1 --- /dev/null +++ b/src/MessageCommands/_Example.lua @@ -0,0 +1,15 @@ +local SlashCommandTools = require('discordia-slash').util.tools() + +local GetProfilePictureCommand = SlashCommandTools.messageCommand('Copy message', 'Says the same exact message (text only)') + +local function Callback(Interaction, Command, Message) + local MessageContent = Message.content + if MessageContent then + return Interaction:reply(MessageContent) + end +end + +return { + Command = GetProfilePictureCommand, + Callback = Callback +} \ No newline at end of file diff --git a/src/SlashCommands/Minecraft.lua b/src/SlashCommands/Minecraft.lua new file mode 100644 index 0000000..08910b8 --- /dev/null +++ b/src/SlashCommands/Minecraft.lua @@ -0,0 +1,139 @@ +local Discordia = require('discordia') +local json = require('json') +local http_request = require('../Modules/http.lua') +Discordia.extensions() + +local ApplicationCommandOptionTypes = Discordia.enums.appCommandOptionType + +local SlashCommandTools = require('discordia-slash').util.tools() + +local MinecraftMainCommand = SlashCommandTools.slashCommand('minecraft', 'Minecraft server related commands') + +local MinecraftStatusSubCommand = SlashCommandTools.subCommand('status', 'Get the Minecraft server status according to the preferred IP address set for this server') +local MinecraftSetIpSubCommand = SlashCommandTools.subCommand('setip', 'Set the preferred Minecraft server IP address for this server') + +local MinecraftSetIpOptions = SlashCommandTools.string('ip', 'The IP address of the server') +MinecraftSetIpOptions:setRequired(true) +MinecraftSetIpSubCommand:addOption(MinecraftSetIpOptions) + +MinecraftMainCommand:addOption(MinecraftSetIpSubCommand) +MinecraftMainCommand:addOption(MinecraftStatusSubCommand) + +local COLOURS = { + GREEN = 0x00ff00, + RED = 0xff0000 +} + +--initialize minecraft ip data +local MinecraftDataFile = io.open('minecraft_data.json', 'r') +if not MinecraftDataFile or (MinecraftDataFile and MinecraftDataFile:read('*a') == '') then + print('no such file exists! so make it') + io.open('minecraft_data.json', 'w+'):write(json.encode({})):close() +end +if MinecraftDataFile then + MinecraftDataFile:close() +end + +local SubCommandCallbacks = {} +local function Status(Interaction, Command, Args) + local GuildId = Interaction.guild and Interaction.guild.id + if not GuildId then + return Interaction:reply('You cannot use this command outside of a Discord server', true) + end + + local GlobalMinecraftData = json.decode(io.open('minecraft_data.json', 'r'):read('*a')) + if not GlobalMinecraftData then + return Interaction:reply('Could not read server data', true) + end + + local ServerMinecraftData = GlobalMinecraftData[GuildId] + if not ServerMinecraftData then + return Interaction:reply('There is no data for this Discord server', true) + end + + local ServerIPStr = ServerMinecraftData.IP..':'..ServerMinecraftData.PORT + local Response, Headers = http_request('GET', ('https://api.mcsrvstat.us/3/%s'):format(ServerIPStr)) + + local IsOnline = Response.online + local EmbedData + if IsOnline then + local MaxPlayers = Response.players.max + local OnlinePlayers = Response.players.online + local AnonymousPlayers = OnlinePlayers + local Players = {} + if OnlinePlayers>0 then + for PlayerIndex, PlayerData in next, Response.players.list do + table.insert(Players, PlayerData.name) + AnonymousPlayers = AnonymousPlayers-1 + end + else + table.insert(Players, 'No players online') + end + if AnonymousPlayers>0 then + for AnonymousPlayerIndex = 1, AnonymousPlayers do + table.insert(Players, 'Anonymous Player') + end + end + EmbedData = { + title = 'Server Status for '..ServerIPStr, + description = Response.motd.clean[1]..' ('..Response.version..')', + fields = { + {name = 'Players', value = OnlinePlayers..'/'..MaxPlayers, inline = true}, + {name = 'List of players', value = table.concat(Players, '\n'), inline = true} + }, + color = COLOURS.GREEN + } + else + EmbedData = { + title = 'Server Status for '..ServerIPStr, + description = 'Server is offline', + color = COLOURS.RED + } + end + return Interaction:reply({embed = EmbedData}) +end + +local function SetIp(Interaction, Command, Args) + local ServerIPStr = Args.ip + + local GuildId = Interaction.guild and Interaction.guild.id + if not GuildId then + return Interaction:reply('You cannot use this command outside of a Discord server') + end + + local ServerIP = ServerIPStr:match("(%d+%.%d+%.%d+%.%d+)") or ServerIPStr:match("(%w*%.?%w+%.%w+)") + if not ServerIP then + return Interaction:reply('Invalid server IP') + end + local ServerPort = ServerIPStr:match(ServerIP..':(%d+)') or 25565 + + local GuildMinecraftData = {IP = ServerIP, PORT = ServerPort} + + local GlobalMinecraftData = json.decode(io.open('minecraft_data.json','r'):read('*a')) + GlobalMinecraftData[GuildId] = GuildMinecraftData + io.open('minecraft_data.json','w+'):write(json.encode(GlobalMinecraftData)):close() + + return Interaction:reply('Successfully added `'..ServerIP..':'..ServerPort..'` for ServerId='..GuildId) +end +SubCommandCallbacks.status = Status +SubCommandCallbacks.setip = SetIp + + + +local function Callback(Interaction, Command, Args) + local SubCommandOption = Command.options[1] + if SubCommandOption.type == ApplicationCommandOptionTypes.subCommand then + local SubCommandName = SubCommandOption.name + local SubCommandCallback = SubCommandCallbacks[SubCommandName] + local SubCommandArgs = Args[SubCommandName] + if SubCommandCallback then + SubCommandCallback(Interaction, Command, SubCommandArgs) + end + end + +end + +return { + Command = MinecraftMainCommand, + Callback = Callback +} \ No newline at end of file diff --git a/src/modules/commands/user.lua b/src/SlashCommands/User.lua similarity index 75% rename from src/modules/commands/user.lua rename to src/SlashCommands/User.lua index 514da35..7f4081b 100644 --- a/src/modules/commands/user.lua +++ b/src/SlashCommands/User.lua @@ -1,30 +1,21 @@ -local discordia=require('discordia') -local date = discordia.Date -local API=require('./../strafes_net.lua') -local commands=require('./../commands.lua') ---[[ - { - "description": "string", - "created": "2022-08-22T02:55:01.607Z", - "isBanned": true, - "externalAppDisplayName": "string", - "hasVerifiedBadge": true, - "id": 0, - "name": "string", - "displayName": "string" -}]] ---[[ -{"GameId":null, -"IsOnline":false, -"LastLocation":"Offline", -"LastOnline":"2022-08-21T22:32:23.4-05:00", -"LocationType":2, -"PlaceId":null, -"VisitorId":1455906620, -"PresenceType":0, -"UniverseId":null, -"Visibility":0} -]] +local SlashCommandTools = require('discordia-slash').util.tools() + +local Discordia = require('discordia') +local Date = Discordia.Date +Discordia.extensions() + +local API = require('../Modules/strafes_net.lua') + +local UserCommand = SlashCommandTools.slashCommand('user', 'Looks up specified user on Roblox') + +local UsernameOption = SlashCommandTools.string('username', 'Username to look up') +local UserIdOption = SlashCommandTools.integer('user_id', 'User ID to look up') +local MemberOption = SlashCommandTools.user('member', 'User to look up') + +UserCommand:addOption(UsernameOption) +UserCommand:addOption(UserIdOption) +UserCommand:addOption(MemberOption) + Badges = { '275640532', --Bhop, pre-group '363928432', --Surf, pre-group @@ -42,7 +33,7 @@ local function round(x,n) end local function FromYMD(ymd) - return date.fromISO(ymd.."T00:00:00")[1] + return Date.fromISO(ymd.."T00:00:00")[1] end local function leftpad(s,n,p) return string.rep(p,n-#tostring(s))..s @@ -84,18 +75,30 @@ local function GuessDateFromAssetID(AssetID) return "Before "..ToYMD(IDToDate[1][2]) end -discordia.extensions() -commands:Add('user',{},'user ', function(t) - local args=t.args - local message=t.message - local user=args[1] or 'me' - local user_info=API:GetUserFromAny(user,message) - if type(user_info)=='string' then return message:reply('```'..user_info..'```') end +local function Callback(Interaction, Command, Args) + local user_info + if Args then + local username = Args.username + local user_id = Args.user_id + local member = Args.member + if username then + user_info = API:GetRobloxInfoFromUsername(username) + elseif user_id then + user_info = API:GetRobloxInfoFromUserId(user_id) + elseif member then + user_info = API:GetRobloxInfoFromDiscordId(member.id) + end + else + local user = Interaction.member or Interaction.user + if user then + user_info = API:GetRobloxInfoFromDiscordId(user.id) + end + end local description = user_info.description=='' and 'This user has no description' or user_info.description -- table.foreach(user_info,print) - local created = tostring(date.fromISO(user_info.created):toSeconds()) - local current = date():toSeconds() + local created = tostring(Date.fromISO(user_info.created):toSeconds()) + local current = Date():toSeconds() local accountAge = round((current-created)/86400) local isBanned = user_info.isBanned local id = user_info.id @@ -114,7 +117,7 @@ commands:Add('user',{},'user ', function(t) local LastLocation = onlineStatus_info.lastLocation if onlineStatus_info.userPresenceType==2 then LastLocation="Ingame" end - local LastOnline = date.fromISO(onlineStatus_info.lastOnline):toSeconds() + local LastOnline = Date.fromISO(onlineStatus_info.lastOnline):toSeconds() local verificationAssetId = API:GetVerificationItemID(id) local verificationDate = "Not verified" @@ -132,7 +135,7 @@ commands:Add('user',{},'user ', function(t) local firstBadge,firstBadgeDate = 0,math.huge for _,badge in next,badgeData do local badgeId = badge.badgeId - local awardedDate = tonumber(date.fromISO(badge.awardedDate):toSeconds()) + local awardedDate = tonumber(Date.fromISO(badge.awardedDate):toSeconds()) if firstBadgeDate>awardedDate then firstBadge=badgeId firstBadgeDate=awardedDate @@ -163,5 +166,10 @@ commands:Add('user',{},'user ', function(t) table.insert(embed.fields,{name='FQG',value=BadgesToName[firstBadge],inline=true}) table.insert(embed.fields,{name='Joined',value='',inline=true}) end - message:reply({embed=embed}) -end) \ No newline at end of file + Interaction:reply({embed=embed}) +end + +return { + Command = UserCommand, + Callback = Callback +} \ No newline at end of file diff --git a/src/SlashCommands/_Example.lua b/src/SlashCommands/_Example.lua new file mode 100644 index 0000000..0732a66 --- /dev/null +++ b/src/SlashCommands/_Example.lua @@ -0,0 +1,17 @@ +local SlashCommandTools = require('discordia-slash').util.tools() + +local PongCommand = SlashCommandTools.slashCommand('ping', 'Replies with pong') + +local MessageOption = SlashCommandTools.string('message', 'What the bot will append to the message') + +PongCommand:addOption(MessageOption) + +local function Callback(Interaction, Command, Args) + local Message = Args.message + return Interaction:reply('Pong! '..Message) +end + +return { + Command = PongCommand, + Callback = Callback +} \ No newline at end of file diff --git a/src/UserCommands/GetProfilePicture.lua b/src/UserCommands/GetProfilePicture.lua new file mode 100644 index 0000000..0898ed1 --- /dev/null +++ b/src/UserCommands/GetProfilePicture.lua @@ -0,0 +1,15 @@ +local SlashCommandTools = require('discordia-slash').util.tools() + +local GetProfilePictureCommand = SlashCommandTools.userCommand('Get profile picture', 'Gets user avatar') + +local function Callback(Interaction, Command, Member) + local AvatarURL = Member:getAvatarURL(1024) + if AvatarURL then + return Interaction:reply(AvatarURL, true) + end +end + +return { + Command = GetProfilePictureCommand, + Callback = Callback +} \ No newline at end of file diff --git a/src/main.lua b/src/main.lua index ba2209d..e80d873 100644 --- a/src/main.lua +++ b/src/main.lua @@ -1,80 +1,45 @@ -local discordia = require('discordia') -local dcmd = require('discordia-slash') -local token = require('./modules/token.lua') -local commands=require('./modules/commands.lua') -local prefix = ',' -local client = discordia.Client() -client:useSlashCommands() -_G.dcmd=dcmd -_G.client = client -_G.locked = false +local Discordia = require('discordia') +local DiscordiaSlash = require('discordia-slash') +local Token = require('./Modules/Token.lua') +local CommandCollector = require('./Modules/CommandCollector.lua') +local Client = Discordia.Client():useApplicationCommands() +Discordia.extensions() -discordia.extensions() +local MessageCommandCollector = CommandCollector.new('Message'):Collect() +local SlashCommandCollector = CommandCollector.new('Slash'):Collect() +local UserCommandCollector = CommandCollector.new('User'):Collect() -client:on('ready',function() - commands:INIT() - local f=io.open('restart.txt','r+'):read() - local t=tostring(f):split(',') - if #t==3 then - client:getGuild(t[1]):getChannel(t[2]):send( - { - content='bot ready', - reference={ - message=client:getChannel(t[2]):getMessage(t[3]), - mention=true - } - } - ) - io.open('restart.txt','w+'):write(''):close() - else - print('restart.txt is empty or something so probably a first start') - end +Client:on('ready', function() + -- local GlobalCommands = Client:getGlobalApplicationCommands() + + -- for CommandId in pairs(GlobalCommands) do + -- Client:deleteGlobalApplicationCommand(CommandId) + -- end + + MessageCommandCollector:Publish(Client) + SlashCommandCollector:Publish(Client) + UserCommandCollector:Publish(Client) end) -function parseMentions(message) - local content=message.content - local usersMentioned={} - if #message.mentionedUsers>0 then - for user in message.mentionedUsers:iter() do - usersMentioned[user.id]=user - end - end - local msgSplit=content:split(' ') - for i,v in next, msgSplit do - if v:match('<@![0-9]+>') then - local id=v:match('<@!([0-9]+)>') - if usersMentioned[id] then - msgSplit[i]=usersMentioned[id].mentionString - end - end - end - return table.concat(msgSplit,' ') or '',usersMentioned -end -client:on('messageCreate', function(message) - if message.author.bot then return end - local content,mentions=parseMentions(message) - if content:sub(1,#prefix)==prefix and content~=prefix then - local cmd=content:sub(#prefix+1,#content) - local args=cmd:split(' ') - local cmdName=args[1] - table.remove(args,1) - local command=commands.command_list[cmdName] - if command~=nil then - if message.guild~=nil then - local tb - local s,e=xpcall(function() - command.exec({message=message,args=args,mentions=mentions,t={client,discordia,token}}) - end,function(err) - tb = debug.traceback() - return err - end) - if not s then - message:reply('tripped : '..e:split('/')[#e:split('/')]) - print(e,tb) - end - end - end +Client:on('slashCommand', function(Interaction, Command, Args) + local SlashCommand = SlashCommandCollector:Get(Command.name) + if SlashCommand then + SlashCommand.Callback(Interaction, Command, Args) end end) -client:run('Bot '..token) \ No newline at end of file +Client:on('messageCommand', function(Interaction, Command, Message) + local MessageCommand = MessageCommandCollector:Get(Command.name) + if MessageCommand then + MessageCommand.Callback(Interaction, Command, Message) + end +end) + +Client:on('userCommand', function(Interaction, Command, Member) + local UserCommand = UserCommandCollector:Get(Command.name) + if UserCommand then + UserCommand.Callback(Interaction, Command, Member) + end +end) + +Client:run('Bot '..Token) \ No newline at end of file diff --git a/src/modules/CommandCollector.lua b/src/modules/CommandCollector.lua new file mode 100644 index 0000000..b80550c --- /dev/null +++ b/src/modules/CommandCollector.lua @@ -0,0 +1,73 @@ +local RELATIVE_PATH_TO_COMMANDS = '../' --this is because the require function will call to a path relative to this current file :D +local IGNORE_STARTING_FILE_NAME = '_' + +local CommandCollector = {} +CommandCollector.__index = CommandCollector + +function CommandCollector.new(Prefix) + local self = setmetatable({}, CommandCollector) + + self.Prefix = Prefix + self.Collected = false + self.Collection = {} + + return self +end + +function CommandCollector:Get(CommandName) + for CommandIndex, CommandData in next, self.Collection do + if CommandName == CommandData.Command.name then + return CommandData + end + end +end + +function CommandCollector:Collect() + if self.Collected then + print('Command collector for', self.Prefix, 'commands was already collected') + return + end + + local CommandsContainerPath = self.Prefix..'Commands/' + + for File in io.popen('dir "./src/'..CommandsContainerPath..'" /b'):lines() do + if File:sub(1, 1) ~= IGNORE_STARTING_FILE_NAME then + local Success, Return = pcall(require, RELATIVE_PATH_TO_COMMANDS..CommandsContainerPath..File) + if Success then + if not Return.Command or not Return.Callback then + print('Malformed command data in', CommandsContainerPath..File, 'Reason: returned command data table is missing a Command or Callback field') + return + end + print('Loaded', CommandsContainerPath..File) + table.insert(self.Collection, {Command = Return.Command, Callback = Return.Callback}) + else + print('Error loading', CommandsContainerPath..File, 'Error:', Return) + end + end + end + + print('Loaded a total of '..#self.Collection..' '..self.Prefix..' command'..(#self.Collection ~= 1 and 's' or '')) + + self.Collected = true + return self +end + +function CommandCollector:Publish(Client) + if not Client.createGlobalApplicationCommand then + print('Client does not have the method \'createGlobalApplicationCommand\'') + return + end + + for CommandIndex, CommandData in next, self.Collection do + local Success, Return = pcall(Client.createGlobalApplicationCommand, Client, CommandData.Command) + if Success then + print('Published command', CommandData.Command.name) + else + print('Failed to publish command', CommandData.Command.name, 'Error:', Return) + end + end + + return self +end + +return CommandCollector \ No newline at end of file diff --git a/src/modules/commands.lua b/src/modules/commands.lua deleted file mode 100644 index a802bf3..0000000 --- a/src/modules/commands.lua +++ /dev/null @@ -1,34 +0,0 @@ -local discordia=require('discordia') -discordia.extensions() -local commands={command_list={}} -setmetatable(commands.command_list,{__index=function(self,index) - for i,v in pairs(self) do - for i2,v2 in pairs(v.alias) do - if v2==index then - return self[i] - end - end - end - return nil -end}) -function commands:Add(name,alias,desc,exec) - name=type(name)=='string' and name or ('Command'..#self.command_list) - self.command_list[name]={ - name=name, - alias=type(alias)=='table'and alias or {'None'}, - desc=type(desc)=='string'and desc or ('No description provided'), - exec=type(exec)=='function'and exec or function(message) - return message:reply('No command assigned') - end - } - return self.command_list[name] -end -function commands:Get(name) - return self.command_list[name] -end -function commands:INIT() - for file in io.popen([[dir "./src/modules/commands" /b]]):lines() do require('./commands/'..file) end - print('commands done') -end - -return commands \ No newline at end of file diff --git a/src/modules/commands/cmds.lua b/src/modules/commands/cmds.lua deleted file mode 100644 index 7a0f5e8..0000000 --- a/src/modules/commands/cmds.lua +++ /dev/null @@ -1,14 +0,0 @@ -local discordia=require('discordia') -local commands=require('./../commands.lua') -discordia.extensions() -commands:Add('cmds',{'commands','cmd','help'},'Returns a list of all commands',function(t) - local final='```\n' - for i,v in pairs(commands.command_list) do - local name=v.name - local alias=table.concat(v.alias,', ') or 'None' - local desc=v.desc - final=final..'Name: '..name..'\nDescription: '..desc..'\n'..'Aliases: '..alias..'\n\n' - end - final=final..'```' - t.message:reply(final) -end) \ No newline at end of file diff --git a/src/modules/commands/download.lua b/src/modules/commands/download.lua deleted file mode 100644 index 34c2ac1..0000000 --- a/src/modules/commands/download.lua +++ /dev/null @@ -1,78 +0,0 @@ -local discordia=require('discordia') -local commands=require('./../commands.lua') -discordia.extensions() - -function split(s,d) - local t,c,i={},'',0 - for k in s:gmatch('.') do - i=i+1 - if k==d and string.sub(s,i+1)~='' then - t[#t+1]=c - c='' - goto continue - end - c=c..k - ::continue:: - end - t[#t+1]=c - return t -end - -function clearTmp() - for file in io.popen([[dir "./tmp" /b]]):lines() do - if file then - os.remove('./tmp/'..file) - end - end -end -function isTmpEmpty() - local dir = io.popen([[dir "./tmp" /b]]):read() - return dir==nil, dir, dir~=nil and split(dir,'\n') or {} -end - -commands:Add('sc',{},'download soundcloud song (usage: "sc [link]")', function(t) - local args = t.args - local message = t.message - if args[1] then - if args[1]:match('https://soundcloud.com/[%w-_]+/[%w-_]+') then - clearTmp() - local link=args[1]:match('https://soundcloud.com/[%w-_]+/[%w-_]+') - message:reply('Attempting to download song from <'..link..'>') - local filepath = '' - local s=io.popen('ytdl.exe -o "./tmp/%(uploader_id)s-%(display_id)s.%(ext)s" '..link) - local songName - repeat - local str = s:read() - if str then - local tag = str:match('^%[(.+)%]') - if tag=='soundcloud' then - local song = str:match('^%[soundcloud%] (.+):') - if song:match('%d+')~=song then - songName = song:match('.+/(.+)') - end - end - end - until s:read()==nil - s:close() - if type(songName)=='string' and songName~='' then - message:reply('found song: '..songName) - local empty,file = isTmpEmpty() - if not empty then - message:reply({file='./tmp/'..file}) - os.remove('./tmp/'..file) - end - end - else - message:reply('Invalid URL') - end - else - message:reply('No URL provided') - end -end) - --- commands:Add('ct',{},'',function() --- clearTmp() --- end) --- commands:Add('ft',{},'',function() --- filterTmp() --- end) \ No newline at end of file diff --git a/src/modules/commands/map.lua b/src/modules/commands/map.lua deleted file mode 100644 index 9552d23..0000000 --- a/src/modules/commands/map.lua +++ /dev/null @@ -1,28 +0,0 @@ -local discordia=require('discordia') -local API=require('./../strafes_net.lua') -local commands=require('./../commands.lua') -discordia.extensions() - -commands:Add('map',{},'get map info', function(t) - local args = t.args - local message = t.message - - local game = API.GAMES[args[1]] - local map - if not game then - local str = table.concat(args,' ') - map = API.MAPS[1][str] or API.MAPS[2][str] - else - map = API.MAPS[game][table.concat(args,' ',2)] - end - - if not map then return message:reply('```No map found```') end - local formatted_message = '```'.. - 'Map: '..map.DisplayName..' ('..API.GAMES[map.Game]..')\n'.. - 'ID: '..map.ID..'\n'.. - 'Creator: '..map.Creator..'\n'.. - 'PlayCount: '..map.PlayCount..'\n'.. - 'Published: '..os.date('%A, %B %d %Y @ %I:%M (%p)',map.Date).. - '```' - return message:reply(formatted_message) -end) \ No newline at end of file diff --git a/src/modules/commands/maps_init.lua b/src/modules/commands/maps_init.lua deleted file mode 100644 index e9ec84b..0000000 --- a/src/modules/commands/maps_init.lua +++ /dev/null @@ -1,71 +0,0 @@ --- local discordia=require('discordia') --- local API=require('./../strafes_net.lua') --- discordia.extensions() --- API.MAPS={} - --- local function insert(t, value) --- local start, ending, mid, state = 1, #t, 1, 0 - --- while start <= ending do --- mid = math.floor((start + ending) / 2) --- if #value.DisplayName < #t[mid].DisplayName then --- ending, state = mid - 1, 0 --- else --- start, state = mid + 1, 1 --- end --- end - --- table.insert(t, mid + state, value) --- end - --- for _, game in next, API.GAMES do --- if type(tonumber(game)) == 'number' then --- local count = 0 -- add into the maps table afterwards --- local maps = {} --- local res, headers = API:GetMaps(game) --- local pages = tonumber(headers['Pagination-Count']) - --- count = count + #res - --- for _, v in next, res do --- insert(maps, v) --- end - --- if pages > 1 then --- for i = 2, pages do --- res, headers = API:GetMaps(game, i) --- count = count + #res - --- for _, j in next, res do --- insert(maps, j) --- end --- end --- end - --- setmetatable(maps, {__index = function(self, k) --- if k=='count' then return self.count end - --- -- Just to make sure it goes in the right order --- if type(k)=='string' then --- for i = 1, self.count do --- local v = self[i] --- if type(v) == 'table' and v.DisplayName:lower():find(tostring(k:gsub('%%', '%%%%'):gsub('^%^', '%%^'):gsub('%$$', '%%$'):gsub('%(', '%%('):gsub('%)', '%%)'):gsub('%.', '%%.'):gsub('%[', '%%['):gsub('%]', '%%]'):gsub('%*', '%%*'):gsub('%+', '%%+'):gsub('%-', '%%-'):gsub('%?', '%%?')):lower()) then --- return v --- end --- end --- elseif type(k)=='number' then --- for i = 1, self.count do --- local v = self[i] - --- if type(v) == 'table' and v.ID==k then --- return v --- end --- end --- end --- end}) - --- maps.count = count --- API.MAPS[game] = maps --- print('map init done for game:', API.GAMES[game], 'count:', API.MAPS[game].count) --- end --- end \ No newline at end of file diff --git a/src/modules/commands/minecraft.lua b/src/modules/commands/minecraft.lua deleted file mode 100644 index 0f0d1a4..0000000 --- a/src/modules/commands/minecraft.lua +++ /dev/null @@ -1,114 +0,0 @@ -local discordia=require('discordia') -local json=require('json') -local http_request=require('./../http.lua') -local Commands=require('./../commands.lua') -discordia.extensions() - -local COLOURS={ - GREEN=0x00ff00, - RED=0xff0000 -} - ---initialize minecraft ip data -local MinecraftDataFile=io.open('minecraft_data.json','r') -if not MinecraftDataFile or (MinecraftDataFile and MinecraftDataFile:read('*a')=='') then - print('no such file exists! so make it') - io.open('minecraft_data.json','w+'):write(json.encode({})):close() -end -if MinecraftDataFile then - MinecraftDataFile:close() -end - -Commands:Add('setip',{},'set ip for status',function(CommandData) - local CommandArgs=CommandData.args - local CommandMessage=CommandData.message - local ServerIPStr=CommandArgs[1] - if not ServerIPStr then - return CommandMessage:reply('No IP provided') - end - - local ServerIP=ServerIPStr:match("(%d+%.%d+%.%d+%.%d+)") or ServerIPStr:match("(%w*%.?%w+%.%w+)") - if not ServerIP then - return CommandMessage:reply('Invalid server IP') - end - local ServerPort=ServerIPStr:match(ServerIP..':(%d+)') or 25565 - - local GuildId=CommandMessage.guild.id - if not GuildId then - return CommandMessage:reply('You cannot use this command outside of a Discord server') - end - - local GuildMinecraftData={IP=ServerIP,PORT=ServerPort} - - local GlobalMinecraftData=json.decode(io.open('minecraft_data.json','r'):read('*a')) - GlobalMinecraftData[GuildId]=GuildMinecraftData - io.open('minecraft_data.json','w+'):write(json.encode(GlobalMinecraftData)):close() - - return CommandMessage:reply({ - content='Successfully added `'..ServerIP..':'..ServerPort..'` for ServerId='..GuildId, - reference={ - message=CommandMessage, - mention=true - } - }) -end) - -Commands:Add('status',{},'get status for minecraft server',function(CommandData) - local CommandMessage=CommandData.message - - local GuildId=CommandMessage.guild.id - if not GuildId then - return CommandMessage:reply('You cannot use this command outside of a Discord server') - end - - local GlobalMinecraftData=json.decode(io.open('minecraft_data.json','r'):read('*a')) - if not GlobalMinecraftData then - return CommandMessage:reply('Could not read server data') - end - - local ServerMinecraftData=GlobalMinecraftData[GuildId] - if not ServerMinecraftData then - return CommandMessage:reply('There is no data for this Discord server') - end - - local ServerIPStr=ServerMinecraftData.IP..':'..ServerMinecraftData.PORT - local Response,Headers=http_request('GET',('https://api.mcsrvstat.us/3/%s'):format(ServerIPStr)) - - local IsOnline=Response.online - local EmbedData - if IsOnline then - local MaxPlayers=Response.players.max - local OnlinePlayers=Response.players.online - local AnonymousPlayers=OnlinePlayers - local Players={} - if OnlinePlayers>0 then - for PlayerIndex,PlayerData in next,Response.players.list do - table.insert(Players,PlayerData.name) - AnonymousPlayers=AnonymousPlayers-1 - end - else - table.insert(Players,'No players online') - end - if AnonymousPlayers>0 then - for AnonymousPlayerIndex=1,AnonymousPlayers do - table.insert(Players,'Anonymous Player') - end - end - EmbedData={ - title='Server Status for '..ServerIPStr, - description=Response.motd.clean[1]..' ('..Response.version..')', - fields={ - {name='Players',value=OnlinePlayers..'/'..MaxPlayers,inline=true}, - {name='List of players',value=table.concat(Players,'\n'),inline=true} - }, - color=COLOURS.GREEN - } - else - EmbedData={ - title='Server Status for '..ServerIPStr, - description='Server is offline', - color=COLOURS.RED - } - end - return CommandMessage:reply({embed=EmbedData}) -end) \ No newline at end of file diff --git a/src/modules/commands/pb.lua b/src/modules/commands/pb.lua deleted file mode 100644 index bb306f7..0000000 --- a/src/modules/commands/pb.lua +++ /dev/null @@ -1,60 +0,0 @@ -local discordia=require('discordia') -local API=require('./../strafes_net.lua') -local commands=require('./../commands.lua') -local pad = API.Pad - -discordia.extensions() - --- args: user, game, style, map -commands:Add('pb', {}, 'get placement on map', function(t) - local args = t.args - local message = t.message - - if #args < 4 then return message:reply('invalid arguments') end - - local user = API:GetUserFromAny(args[1],message) - local sn_info = API:GetUser(user.id) - local game = API.GAMES[args[2]] - local style = API.STYLES[args[3]] - local map = API.MAPS[game][table.concat(args,' ',4)] - - -- i love checks - if not game then return message:reply('invalid game') end - if not style then return message:reply('invalid style') end - if not map then return message:reply('invalid map') end - if not sn_info.ID then return message:reply('```No data with StrafesNET is associated with that user.```') end - if sn_info.State==2 then return message:reply('```This user is currently blacklisted```') end - - local time = API:GetUserTimes(user.id, map.ID, style, game)[1] - - if not time then return message:reply('```No time was found.```') end - - local rank = API:GetTimeRank(time.ID).Rank - local count = tonumber(API:GetMapCompletionCount(time.Map, style)) - - if not rank or not count then - rank = 1 - count = 1 - end - - local time_formatted = API.FormatTime(time.Time) - local date = os.date("%x", time.Date) - local placement = rank .. '/' .. count - local points = API.CalculatePoint(rank, count) - - local t_n, d_n, p_n= #time_formatted, 8, math.max(#placement, 10) - - local first_line = 'PB Time for map: '..map.DisplayName..' ('..API.GAMES[game]..', '..API.STYLES_LIST[style]..')' - - local second_line = pad('Time:', t_n + 1) .. '| ' - .. pad('Date:', d_n + 1) .. '| ' - .. pad('Placement:', p_n + 1) .. '| ' - .. 'Points:' - - local third_line = pad(time_formatted, t_n + 1) .. '| ' - .. pad(date, d_n + 1) .. '| ' - .. pad(placement, p_n + 1) .. '| ' - .. tostring(points) - - return message:reply('```' .. first_line .. '\n' .. second_line .. '\n' .. third_line .. '```') -end) diff --git a/src/modules/commands/rank.lua b/src/modules/commands/rank.lua deleted file mode 100644 index e13e930..0000000 --- a/src/modules/commands/rank.lua +++ /dev/null @@ -1,40 +0,0 @@ -local discordia=require('discordia') -local API=require('./../strafes_net.lua') -local commands=require('./../commands.lua') -function dump(a,b,c,d)b=b or 50;d=d or("DUMP START "..tostring(a))c=c or 0;for e,f in next,a do local g;if type(f)=="string"then g="\""..f.."\""else g=tostring(f)end;d=d.."\nD "..string.rep(" ",c*2)..tostring(e)..": "..g;if type(f)=="table"then if c>=b then d=d.." [ ... ]"else d=dump(f,b,c+1,d)end end end;return d end -discordia.extensions() -commands:Add('rank',{},'rank