forked from tommy/tommy-bot
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
7b3ab8e115
|
|||
54d588b43a
|
|||
f072b14735
|
|||
e2ee24898f
|
|||
1c08e5fd47
|
|||
d2eded99a1
|
|||
5eb9f82bfe
|
|||
708a5364a9
|
|||
328a9ed5b7 |
.gitignore
src
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,6 @@
|
|||||||
discordia.log
|
discordia.log
|
||||||
gateway.json
|
gateway.json
|
||||||
apikey.lua
|
APIKeys.lua
|
||||||
Token.lua
|
Token.lua
|
||||||
deps
|
deps
|
||||||
sensdb.lua
|
sensdb.lua
|
||||||
|
88
src/Modules/HttpRequest.lua
Normal file
88
src/Modules/HttpRequest.lua
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
local Http = require('coro-http')
|
||||||
|
local HTTPRequest = Http.request
|
||||||
|
|
||||||
|
local json = require('json')
|
||||||
|
|
||||||
|
local METHODS = {
|
||||||
|
GET = true,
|
||||||
|
POST = true
|
||||||
|
}
|
||||||
|
|
||||||
|
local function QueryParams(Params) -- {Name = Value, ...}
|
||||||
|
if not Params then return "" end
|
||||||
|
local QueryString = "?"
|
||||||
|
|
||||||
|
for ParamName, ParamValue in next, Params do
|
||||||
|
if ParamValue ~= nil then
|
||||||
|
QueryString = QueryString .. tostring(ParamName) .. "=" .. tostring(ParamValue) .. "&"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return string.sub(QueryString, 1, -2) -- Remove last character (will always be a "&")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function CreateHeaders(Headers) -- {Name = Value, ...}
|
||||||
|
if not Headers then return {} end
|
||||||
|
local RequestHeaders = {}
|
||||||
|
|
||||||
|
for HeaderName, HeaderValue in next, Headers do
|
||||||
|
RequestHeaders[#RequestHeaders + 1] = { tostring(HeaderName), tostring(HeaderValue) }
|
||||||
|
end
|
||||||
|
|
||||||
|
return RequestHeaders
|
||||||
|
end
|
||||||
|
|
||||||
|
local function TryDecodeJson(Body)
|
||||||
|
local Success, Result = pcall(json.decode, Body)
|
||||||
|
if not Success then
|
||||||
|
return Body
|
||||||
|
end
|
||||||
|
return Result
|
||||||
|
end
|
||||||
|
|
||||||
|
local function NormalizeHeaders(Response)
|
||||||
|
for Index, Header in next, Response do
|
||||||
|
if type(Header) == "table" and #Header == 2 then
|
||||||
|
local HeaderName, HeaderValue = table.unpack(Header)
|
||||||
|
Response[HeaderName] = HeaderValue
|
||||||
|
Response[Index] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Request(Method, Url, Params, RequestHeaders, RequestBody, Callback)
|
||||||
|
if not METHODS[Method] then
|
||||||
|
error("[HTTP] Method " .. Method .. " is not supported.")
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(Url) ~= "string" then
|
||||||
|
error("[HTTP] Url is not a string")
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(RequestBody) == "table" then
|
||||||
|
RequestBody = json.encode(RequestBody)
|
||||||
|
end
|
||||||
|
|
||||||
|
local QueryString = QueryParams(Params) -- at worse (I think), this is an empty string (which cannot mess up the request)
|
||||||
|
|
||||||
|
local FormattedHeaders = CreateHeaders(RequestHeaders) -- At worse, this will just be an empty table (which cannot mess up the request)
|
||||||
|
|
||||||
|
local RequestUrl = Url .. QueryString
|
||||||
|
print(RequestUrl)
|
||||||
|
|
||||||
|
if Callback and type(Callback) == "function" then
|
||||||
|
return coroutine.wrap(function()
|
||||||
|
local Headers, Body = HTTPRequest(Method, RequestUrl, FormattedHeaders, RequestBody)
|
||||||
|
NormalizeHeaders(Headers)
|
||||||
|
Callback(Headers, TryDecodeJson(Body))
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
local Headers, Body = HTTPRequest(Method, RequestUrl, FormattedHeaders, RequestBody)
|
||||||
|
NormalizeHeaders(Headers)
|
||||||
|
return Headers, TryDecodeJson(Body)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
Request = Request
|
||||||
|
}
|
251
src/Modules/StrafesNET.lua
Normal file
251
src/Modules/StrafesNET.lua
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
local HttpRequest = require("./HttpRequest.lua")
|
||||||
|
local Request = HttpRequest.Request
|
||||||
|
local APIKeys = require("./APIKeys.lua")
|
||||||
|
|
||||||
|
local Headers = {
|
||||||
|
["Content-Type"] = "application/json",
|
||||||
|
["X-API-Key"] = APIKeys.StrafesNET
|
||||||
|
}
|
||||||
|
|
||||||
|
function L1Copy(t, b)
|
||||||
|
b = b or {}
|
||||||
|
for x, y in next, t do b[x] = y end
|
||||||
|
return b
|
||||||
|
end
|
||||||
|
|
||||||
|
local STRAFESNET_API_URL = "https://api.strafes.net/api/v1/"
|
||||||
|
local FIVEMAN_API_URL = 'https://api.fiveman1.net/v1/'
|
||||||
|
local ROBLOX_API_URL = 'https://users.roblox.com/v1/'
|
||||||
|
local ROBLOX_BADGES_API = 'https://badges.roblox.com/v1/'
|
||||||
|
local ROBLOX_PRESENCE_URL = 'https://presence.roblox.com/v1/'
|
||||||
|
local ROBLOX_THUMBNAIL_URL = 'https://thumbnails.roblox.com/v1/'
|
||||||
|
local ROBLOX_INVENTORY_API = 'https://inventory.roblox.com/v1/'
|
||||||
|
local ROBLOX_GROUPS_ROLES_URL = 'https://groups.roblox.com/v2/users/%s/groups/roles'
|
||||||
|
|
||||||
|
ROBLOX_THUMBNAIL_SIZES = {
|
||||||
|
[48] = '48x48',
|
||||||
|
[50] = '50x50',
|
||||||
|
[60] = '60x60',
|
||||||
|
[75] = '75x75',
|
||||||
|
[100] = '100x100',
|
||||||
|
[110] = '110x110',
|
||||||
|
[150] = '150x150',
|
||||||
|
[180] = '180x180',
|
||||||
|
[352] = '352x352',
|
||||||
|
[420] = '420x420',
|
||||||
|
[720] = '720x720'
|
||||||
|
}
|
||||||
|
ROBLOX_THUMBNAIL_TYPES = {
|
||||||
|
AVATAR = 'avatar',
|
||||||
|
BUST = 'avatar-bust',
|
||||||
|
HEADSHOT = 'avatar-headshot'
|
||||||
|
}
|
||||||
|
|
||||||
|
local STRAFESNET_API_ENDPOINTS = {
|
||||||
|
MAPS = {
|
||||||
|
LIST = "map",
|
||||||
|
GET = "map/%d"
|
||||||
|
},
|
||||||
|
RANKS = {
|
||||||
|
LIST = "rank"
|
||||||
|
},
|
||||||
|
TIMES = {
|
||||||
|
LIST = "time",
|
||||||
|
GET = "time/%d"
|
||||||
|
},
|
||||||
|
USERS = {
|
||||||
|
LIST = "user",
|
||||||
|
GET = "user/%d",
|
||||||
|
RANKS = {
|
||||||
|
GET = "user/%d/rank"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local StrafesNET = {}
|
||||||
|
|
||||||
|
function StrafesNET.ListMaps(GameId, PageSize, PageNumber)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.MAPS.LIST
|
||||||
|
local Params = { game_id = GameId, page_size = PageSize or 10, page_number = PageNumber or 1 }
|
||||||
|
return Request("GET", RequestUrl, Params, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetMap(MapId)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.MAPS.GET:format(MapId)
|
||||||
|
local Params = { id = MapId }
|
||||||
|
return Request("GET", RequestUrl, Params, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.ListRanks(GameId, ModeId, StyleId, SortBy, PageSize, PageNumber)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.RANKS.LIST
|
||||||
|
local Params = {
|
||||||
|
gameId = GameId,
|
||||||
|
modeId = ModeId,
|
||||||
|
styleId = StyleId,
|
||||||
|
sort_by = SortBy or 1,
|
||||||
|
page_size = PageSize or 10,
|
||||||
|
page_number = PageNumber or 1
|
||||||
|
}
|
||||||
|
return Request("GET", RequestUrl, Params, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.ListTimes(UserId, MapId, GameId, ModeId, StyleId, SortBy, PageSize, PageNumber)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.TIMES.LIST
|
||||||
|
local Params = {
|
||||||
|
user_id = UserId,
|
||||||
|
map_id = MapId,
|
||||||
|
game_id = GameId,
|
||||||
|
mode_id = ModeId,
|
||||||
|
style_id = StyleId,
|
||||||
|
sort_by = SortBy or 1,
|
||||||
|
page_size = PageSize or 10,
|
||||||
|
page_number = PageNumber or 0
|
||||||
|
}
|
||||||
|
return Request("GET", RequestUrl, Params, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetTime(TimeId)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.TIMES.GET:format(TimeId)
|
||||||
|
return Request("GET", RequestUrl, nil, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.ListUsers(StateId, PageSize, PageNumber)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.USERS.LIST
|
||||||
|
local Params = {
|
||||||
|
state_id = StateId,
|
||||||
|
page_size = PageSize or 10,
|
||||||
|
page_number = PageNumber or 1,
|
||||||
|
}
|
||||||
|
return Request("GET", RequestUrl, Params, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetUser(UserId)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.USERS.GET:format(UserId)
|
||||||
|
return Request("GET", RequestUrl, nil, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetUserRank(UserId, GameId, ModeId, StyleId)
|
||||||
|
local RequestUrl = STRAFESNET_API_URL .. STRAFESNET_API_ENDPOINTS.USERS.RANKS.GET:format(UserId)
|
||||||
|
local Params = {
|
||||||
|
game_id = GameId,
|
||||||
|
mode_id = ModeId,
|
||||||
|
style_id = StyleId,
|
||||||
|
}
|
||||||
|
return Request("GET", RequestUrl, Params, Headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetRobloxInfoFromUserId(USER_ID)
|
||||||
|
if not USER_ID then return 'empty id' end
|
||||||
|
return Request("GET", ROBLOX_API_URL .. "users/" .. USER_ID)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetRobloxInfoFromUsername(USERNAME)
|
||||||
|
if not USERNAME then return 'empty username' end
|
||||||
|
if #USERNAME > 32 then return 'Username too long' end
|
||||||
|
|
||||||
|
local headers, body = Request("POST", ROBLOX_API_URL .. "usernames/users", nil,
|
||||||
|
{ ["Content-Type"] = "application/json" }, { usernames = { USERNAME } })
|
||||||
|
if not body or not body.data or not body.data[1] then
|
||||||
|
return 'Username \'' .. USERNAME .. '\' not found.'
|
||||||
|
end
|
||||||
|
|
||||||
|
return StrafesNET.GetRobloxInfoFromUserId(body.data[1].id)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetRobloxInfoFromDiscordId(DISCORD_ID)
|
||||||
|
if not DISCORD_ID then return 'empty id' end
|
||||||
|
-- table.foreach(DISCORD_ID, print)
|
||||||
|
local headers, body = Request("GET", FIVEMAN_API_URL .. "users/" .. DISCORD_ID)
|
||||||
|
if headers.status == "error" then return headers.messages end
|
||||||
|
|
||||||
|
return Request("GET", ROBLOX_API_URL .. "users/" .. body.result.robloxId)
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetUserFromAny(user, message)
|
||||||
|
local str = user:match('^["\'](.+)[\'"]$')
|
||||||
|
local num = user:match('^(%d+)$')
|
||||||
|
|
||||||
|
if str then
|
||||||
|
local roblox_user = StrafesNET.GetRobloxInfoFromUsername(str)
|
||||||
|
if not roblox_user.id then return 'User not found' end
|
||||||
|
return roblox_user
|
||||||
|
elseif num then
|
||||||
|
local roblox_user = StrafesNET.GetRobloxInfoFromUserId(user)
|
||||||
|
if not roblox_user.id then return 'Invalid user id' end
|
||||||
|
return roblox_user
|
||||||
|
elseif user == 'me' then
|
||||||
|
local me = message.author
|
||||||
|
local roblox_user = StrafesNET.GetRobloxInfoFromDiscordId(me.id)
|
||||||
|
if not roblox_user.id then
|
||||||
|
return
|
||||||
|
'You are not registered with the fiveman1 api, use !link with the rbhop bot to link your roblox account'
|
||||||
|
end
|
||||||
|
return roblox_user
|
||||||
|
elseif user:match('<@%d+>') then
|
||||||
|
local user_id = user:match('<@(%d+)>')
|
||||||
|
local member = message.guild:getMember(user_id)
|
||||||
|
local roblox_user = StrafesNET.GetRobloxInfoFromDiscordId(member.id)
|
||||||
|
if not roblox_user.id then
|
||||||
|
return
|
||||||
|
'User is not registered with the fiveman1 api, use !link with the rbhop bot to link your roblox account'
|
||||||
|
end
|
||||||
|
return roblox_user
|
||||||
|
else
|
||||||
|
local roblox_user = StrafesNET.GetRobloxInfoFromUsername(user)
|
||||||
|
if not roblox_user.id then return 'User not found' end
|
||||||
|
return roblox_user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetUserOnlineStatus(USER_ID)
|
||||||
|
if not USER_ID then return 'empty id' end
|
||||||
|
|
||||||
|
local presence = Request("POST", ROBLOX_PRESENCE_URL .. "presence/users", { userIds = { USER_ID } }).userPresences
|
||||||
|
[1]
|
||||||
|
|
||||||
|
local last_online = Request("POST", ROBLOX_PRESENCE_URL .. "presence/last-online", { userIds = { USER_ID } })
|
||||||
|
.lastOnlineTimestamps[1]
|
||||||
|
|
||||||
|
L1Copy(last_online, presence)
|
||||||
|
return presence
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetUserUsernameHistory(USER_ID)
|
||||||
|
if not USER_ID then return 'empty id' end
|
||||||
|
return Request("GET", ROBLOX_API_URL .. "users/" .. USER_ID .. "/username-history",
|
||||||
|
{ limit = 50, sortOrder = 'Desc' })
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetBadgesAwardedDates(USER_ID, BADGE_LIST)
|
||||||
|
if not USER_ID then return 'empty id' end
|
||||||
|
return Request("GET", ROBLOX_BADGES_API .. "users/" .. USER_ID .. "/badges/awarded-dates",
|
||||||
|
{ badgeIds = table.concat(BADGE_LIST, ",") })
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetVerificationItemID(USER_ID)
|
||||||
|
if not USER_ID then return 'empty id' end
|
||||||
|
|
||||||
|
local headers1, body1 = Request("GET", ROBLOX_INVENTORY_API .. "users/" .. USER_ID .. "/items/Asset/102611803")
|
||||||
|
if body1.errors then return body1 end
|
||||||
|
|
||||||
|
local headers2, body2 = Request("GET", ROBLOX_INVENTORY_API .. "users/" .. USER_ID .. "/items/Asset/1567446")
|
||||||
|
if body2.errors then return body2 end
|
||||||
|
|
||||||
|
local data = {}
|
||||||
|
if body2.data and body2.data[1] then data[#data + 1] = body2.data[1] end
|
||||||
|
if body1.data and body1.data[1] then data[#data + 1] = body1.data[1] end
|
||||||
|
|
||||||
|
return { data = data }
|
||||||
|
end
|
||||||
|
|
||||||
|
function StrafesNET.GetUserThumbnail(USER_ID, TYPE, SIZE)
|
||||||
|
if not USER_ID then return 'empty id' end
|
||||||
|
|
||||||
|
local _TYPE = ROBLOX_THUMBNAIL_TYPES[TYPE] or "avatar"
|
||||||
|
local _SIZE = ROBLOX_THUMBNAIL_SIZES[SIZE] or "180x180"
|
||||||
|
|
||||||
|
return Request("GET", ROBLOX_THUMBNAIL_URL .. "users/" .. _TYPE,
|
||||||
|
{ userIds = USER_ID, size = _SIZE, format = "Png", isCircular = false })
|
||||||
|
end
|
||||||
|
|
||||||
|
return StrafesNET
|
@ -1,40 +0,0 @@
|
|||||||
local http = require('coro-http')
|
|
||||||
local json = require('json')
|
|
||||||
function wait(n)local c=os.clock local t=c()while c()-t<=n do end;end
|
|
||||||
--[[
|
|
||||||
1: method
|
|
||||||
2: url
|
|
||||||
3: headers
|
|
||||||
4: body
|
|
||||||
5: options]]
|
|
||||||
local STRAFES_NET_RATELIMIMT = {
|
|
||||||
HOUR = 3000,
|
|
||||||
MINUTE = 100,
|
|
||||||
}
|
|
||||||
local remaining_timeout = 0
|
|
||||||
local function request(method,url,headers,body,options)
|
|
||||||
if type(body)=='table' then body=json.encode(body) end
|
|
||||||
local headers,body=http.request(method,url,headers,body,options)
|
|
||||||
local rbody=json.decode(body) or body
|
|
||||||
local rheaders={}
|
|
||||||
for _,t in pairs(headers) do
|
|
||||||
if type(t)=='table' then
|
|
||||||
rheaders[t[1]]=t[2]
|
|
||||||
else
|
|
||||||
rheaders[_]=t
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local remaining = tonumber(rheaders['RateLimit-Remaining'])
|
|
||||||
local remaining_hour = tonumber(rheaders['X-RateLimit-Remaining-Hour'])
|
|
||||||
local reset = tonumber(rheaders['RateLimit-Reset'])
|
|
||||||
local retry_after = tonumber(rheaders['Retry-After'])
|
|
||||||
if remaining and reset then
|
|
||||||
local t = remaining==0 and reset or .38
|
|
||||||
if retry_after then t = retry_after end
|
|
||||||
wait(t)
|
|
||||||
end
|
|
||||||
return rbody,rheaders
|
|
||||||
end
|
|
||||||
|
|
||||||
-- local urlparamencode=function()
|
|
||||||
return request
|
|
@ -1,348 +0,0 @@
|
|||||||
local http_request = require('./http.lua')
|
|
||||||
local API = {}
|
|
||||||
local API_KEY = require('./apikey.lua')
|
|
||||||
local API_HEADER = { {'Content-Type','application/json'}, { 'api-key', API_KEY }, {'secretkey', '7b320736'} }
|
|
||||||
local STRAFESNET_API_URL = 'https://api.strafes.net/v1/'
|
|
||||||
local FIVEMAN_API_URL = 'https://api.fiveman1.net/v1/'
|
|
||||||
local ROBLOX_API_URL = 'https://users.roblox.com/v1/'
|
|
||||||
local ROBLOX_BADGES_API = 'https://badges.roblox.com/v1/'
|
|
||||||
local ROBLOX_PRESENCE_URL = 'https://presence.roblox.com/v1/'
|
|
||||||
local ROBLOX_THUMBNAIL_URL = 'https://thumbnails.roblox.com/v1/'
|
|
||||||
local ROBLOX_INVENTORY_API = 'https://inventory.roblox.com/v1/'
|
|
||||||
local ROBLOX_GROUPS_ROLES_URL = 'https://groups.roblox.com/v2/users/%s/groups/roles'
|
|
||||||
local ROBLOX_SENS_DB = 'http://oef.ddns.net:9017/rbhop/sens/'
|
|
||||||
|
|
||||||
|
|
||||||
local RANK_CONSTANT_A, RANK_CONSTANT_B, RANK_CONSTANT_C, RANK_CONSTANT_D, RANK_CONSTANT_E = 0.215, 0.595, 0.215, 0.215, 0.71
|
|
||||||
|
|
||||||
local t=tostring
|
|
||||||
local r=function(n,nd) return tonumber(string.format('%.' .. (nd or 0) .. 'f', n))end
|
|
||||||
|
|
||||||
local GAMES={BHOP=1,SURF=2,[1]='bhop',[2]='surf'}
|
|
||||||
local STATES={[0]='Default',[1]='Whitelisted',[2]='Blacklisted',[3]='Pending'}
|
|
||||||
local RANKS={'New (1)','Newb (2)','Bad (3)','Okay (4)','Not Bad (5)','Decent (6)','Getting There (7)','Advanced (8)','Good (9)','Great (10)','Superb (11)','Amazing (12)','Sick (13)','Master (14)','Insane (15)','Majestic (16)','Baby Jesus (17)','Jesus (18)','Half God (19)','God (20)'}
|
|
||||||
local STYLES_LIST={'Autohop','Scroll','Sideways','Half-Sideways','W-Only','A-Only','Backwards'}
|
|
||||||
local STYLES={AUTOHOP=1,SCROLL=2,SIDEWAYS=3,HALFSIDEWAYS=4,WONLY=5,AONLY=6,BACKWARDS=7}
|
|
||||||
|
|
||||||
setmetatable(STYLES,{__index=function(self,i)
|
|
||||||
if type(i)=='number' then return STYLES_LIST[i] or 'Unknown' end
|
|
||||||
if i=='a' then i='auto'elseif i=='hsw'then i='half'elseif i=='s'then i='scroll'elseif i=='sw'then i='side'elseif i=='bw'then i='back'end
|
|
||||||
for ix,v in pairs(self) do
|
|
||||||
if string.sub(ix:lower(),1,#i):find(i:lower()) then
|
|
||||||
return self[ix]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end})
|
|
||||||
setmetatable(GAMES,{__index=function(self,i)
|
|
||||||
for ix,v in pairs(self) do
|
|
||||||
if tostring(ix):lower()==i:lower() then
|
|
||||||
return self[ix]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end})
|
|
||||||
|
|
||||||
API.GAMES=GAMES
|
|
||||||
API.STYLES=STYLES
|
|
||||||
API.STYLES_LIST=STYLES_LIST
|
|
||||||
API.STATES=STATES
|
|
||||||
|
|
||||||
API.ROBLOX_LOCATION_TYPES={
|
|
||||||
[0]='Mobile Website',
|
|
||||||
[1]='Mobile In-Game',
|
|
||||||
[2]='Website',
|
|
||||||
[3]='Roblox Studio',
|
|
||||||
[4]='In-Game',
|
|
||||||
[5]='XboxApp',
|
|
||||||
[6]='TeamCreate'
|
|
||||||
}
|
|
||||||
|
|
||||||
API.ROBLOX_THUMBNAIL_SIZES={
|
|
||||||
[48]='48x48',
|
|
||||||
[50]='50x50',
|
|
||||||
[60]='60x60',
|
|
||||||
[75]='75x75',
|
|
||||||
[100]='100x100',
|
|
||||||
[110]='110x110',
|
|
||||||
[150]='150x150',
|
|
||||||
[180]='180x180',
|
|
||||||
[352]='352x352',
|
|
||||||
[420]='420x420',
|
|
||||||
[720]='720x720'
|
|
||||||
}
|
|
||||||
API.ROBLOX_THUMBNAIL_TYPES = {
|
|
||||||
AVATAR='avatar',
|
|
||||||
BUST='avatar-bust',
|
|
||||||
HEADSHOT='avatar-headshot'
|
|
||||||
}
|
|
||||||
|
|
||||||
-- insyri make this BTW
|
|
||||||
-- use as local err, res = parseToURLArgs(), thanks golang for this idea
|
|
||||||
function parseToURLArgs(tb) local function Err(err) return err, nil end local function Ok(res) return nil, res end if not tb then return Err('got nothing') end if type(tb) ~= 'table' then return Err('expected table, got '..type(tb)) end local str = '?' local index = 1 for key, value in pairs(tb) do if index == 1 then str = str..key..'='..t(value) else str = str..'&'..key..'='..t(value) end index = index + 1 end return Ok(str) end
|
|
||||||
-- fiveman made these (converted to lua from python)
|
|
||||||
-- function format_helper(a,b)a=tostring(a)while#a<b do a='0'..a end;return a end
|
|
||||||
-- function formatTime(a)if a>86400000 then return'>1 day'end;local c=format_helper(a%1000,3)local d=format_helper(math.floor(a/1000)%60,2)local e=format_helper(math.floor(a/(1000*60))%60,2)local f=format_helper(math.floor(a/(1000*60*60))%24,2)if f=='00'then return e..':'..d..'.'..c else return f..':'..e..':'..d end end
|
|
||||||
function formatTime(time) -- chatgpt THIS IS FOR SECONDS! NOT MILLISECONDS
|
|
||||||
local hours = math.floor(time / 3600)
|
|
||||||
local minutes = math.floor((time % 3600) / 60)
|
|
||||||
local seconds = math.floor(time % 60)
|
|
||||||
local milliseconds = math.floor(((time % 1) * 1000)+.5)
|
|
||||||
|
|
||||||
-- if hours > 0 then
|
|
||||||
-- return string.format("%02d:%02d:%02d", hours, minutes, seconds)
|
|
||||||
-- else
|
|
||||||
-- return string.format("%02d:%02d.%03d", minutes, seconds, milliseconds)
|
|
||||||
-- end
|
|
||||||
return string.format(hours and '%02d:%02d:%02d' or '%02d:%02d.%03d', hours and hours or minutes,hours and minutes or seconds, hours and seconds or milliseconds)
|
|
||||||
end
|
|
||||||
function L1Copy(t,b) b=b or {} for x,y in next,t do b[x]=y end return b end
|
|
||||||
|
|
||||||
|
|
||||||
-- [[ STRAFESNET API ]] --
|
|
||||||
|
|
||||||
-- Get rank string from rank point
|
|
||||||
function API.FormatRank(n) return RANKS[1+math.floor(n*19)] end
|
|
||||||
-- Get skill percentage from skill point
|
|
||||||
function API.FormatSkill(n) return r(n*100,3)..'%' end
|
|
||||||
function API.FormatTime(n) return formatTime(n) end
|
|
||||||
|
|
||||||
-- Time from id.
|
|
||||||
function API:GetTime(ID)
|
|
||||||
if not ID then return 'empty id' end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'time/'..ID, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Time rank from id.
|
|
||||||
function API:GetTimeRank(TIME_ID)
|
|
||||||
if not TIME_ID then return 'empty id' end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'time/'..TIME_ID..'/rank', API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- 10 recent world records.
|
|
||||||
function API:GetRecentWrs(STYLE_ID, GAME_ID, WHITELIST_FILTER)
|
|
||||||
if not STYLE_ID or not GAME_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({style=STYLE_ID, game=GAME_ID, whitelist=WHITELIST_FILTER})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'time/recent/wr'..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Time by map id. Sorted in ascending order.
|
|
||||||
function API:GetMapTimes(MAP_ID, STYLE_ID, PAGE)
|
|
||||||
if not MAP_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({style=STYLE_ID, page=PAGE})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'time/map/'..MAP_ID..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Get WR of map.
|
|
||||||
function API:GetMapWr(MAP_ID, STYLE_ID)
|
|
||||||
if not MAP_ID or not STYLE_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({style=STYLE_ID})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'time/map/'..MAP_ID..'/wr'..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Time by user id.
|
|
||||||
function API:GetUserTimes(USER_ID, MAP_ID, STYLE_ID, GAME_ID, PAGE)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({map=MAP_ID, style=STYLE_ID, game=GAME_ID, page=PAGE})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'time/user/'..USER_ID..res , API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- World records by user id.
|
|
||||||
function API:GetUserWrs(USER_ID,GAME_ID,STYLE_ID)
|
|
||||||
if not USER_ID or not GAME_ID or not STYLE_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({game=GAME_ID, style=STYLE_ID})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'time/user/'..USER_ID..'/wr'..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- User from id.
|
|
||||||
function API:GetUser(USER_ID)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'user/'..USER_ID, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Top ranked players, paged at 50 per page.
|
|
||||||
function API:GetRanks(STYLE_ID,GAME_ID,PAGE)
|
|
||||||
if not STYLE_ID or not GAME_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({style=STYLE_ID, game=GAME_ID, page=PAGE})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'rank'..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Get rank of user by their id.
|
|
||||||
function API:GetRank(USER_ID,GAME_ID,STYLE_ID)
|
|
||||||
if not USER_ID or not STYLE_ID or not GAME_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({style=STYLE_ID, game=GAME_ID})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'rank/'..USER_ID..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Get list of maps.
|
|
||||||
function API:GetMaps(GAME_ID,PAGE)
|
|
||||||
if not GAME_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({game=GAME_ID, page=PAGE})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'map'..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
-- Get map by ID.
|
|
||||||
function API:GetMap(MAP_ID)
|
|
||||||
if not MAP_ID then return 'empty id' end
|
|
||||||
local response,headers = http_request('GET', STRAFESNET_API_URL..'map/'..MAP_ID, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
|
|
||||||
-- [[ CUSTOM ]] --
|
|
||||||
|
|
||||||
function API:GetMapCompletionCount(MAP_ID,STYLE_ID)
|
|
||||||
if not MAP_ID or not STYLE_ID then return 'empty id' end
|
|
||||||
local _,headers = self:GetMapTimes(MAP_ID,STYLE_ID)
|
|
||||||
local pages = headers['Pagination-Count']
|
|
||||||
local res,h = self:GetMapTimes(MAP_ID,STYLE_ID,pages)
|
|
||||||
if not res then
|
|
||||||
table.foreach(h,print)
|
|
||||||
end
|
|
||||||
return ((pages-1)*200)+#res
|
|
||||||
end
|
|
||||||
--cool doggo, aidan and me
|
|
||||||
function API.CalculatePoint(rank,count) --??wtf
|
|
||||||
return RANK_CONSTANT_A*(math.exp(RANK_CONSTANT_B)-1)/(1-math.exp(math.max(-700, -RANK_CONSTANT_C*count)))*math.exp(math.max(-700, -RANK_CONSTANT_D*rank))+(1-RANK_CONSTANT_E)*(1+2*(count-rank))/(count*count)
|
|
||||||
end
|
|
||||||
|
|
||||||
function API.Pad(str,n)
|
|
||||||
n = n or 20
|
|
||||||
str = tostring(str)
|
|
||||||
return str..string.rep(' ',n-#str)
|
|
||||||
end
|
|
||||||
|
|
||||||
function API.CalculateDifference(v1,v2)
|
|
||||||
return math.abs(v1-v2)
|
|
||||||
end
|
|
||||||
|
|
||||||
function API.CalculateDifferencePercent(v1,v2)
|
|
||||||
return math.abs((1-(v1/v2))*100)..'%'
|
|
||||||
end
|
|
||||||
function API:GetUserFromAny(user,message)
|
|
||||||
local str = user:match('^["\'](.+)[\'"]$')
|
|
||||||
local num = user:match('^(%d+)$')
|
|
||||||
if str then
|
|
||||||
local roblox_user=self:GetRobloxInfoFromUsername(str)
|
|
||||||
if not roblox_user.id then return 'User not found' end
|
|
||||||
return roblox_user
|
|
||||||
elseif num then
|
|
||||||
local roblox_user = self:GetRobloxInfoFromUserId(user)
|
|
||||||
if not roblox_user.id then return 'Invalid user id' end
|
|
||||||
return roblox_user
|
|
||||||
elseif user=='me' then
|
|
||||||
local me=message.author
|
|
||||||
local roblox_user=self:GetRobloxInfoFromDiscordId(me.id)
|
|
||||||
if not roblox_user.id then return 'You are not registered with the fiveman1 api, use !link with the rbhop bot to link your roblox account' end
|
|
||||||
return roblox_user
|
|
||||||
elseif user:match('<@%d+>') then
|
|
||||||
local user_id=user:match('<@(%d+)>')
|
|
||||||
local member=message.guild:getMember(user_id)
|
|
||||||
local roblox_user=self:GetRobloxInfoFromDiscordId(member.id)
|
|
||||||
if not roblox_user.id then return 'User is not registered with the fiveman1 api, use !link with the rbhop bot to link your roblox account' end
|
|
||||||
return roblox_user
|
|
||||||
else
|
|
||||||
local roblox_user=self:GetRobloxInfoFromUsername(user)
|
|
||||||
if not roblox_user.id then return 'User not found' end
|
|
||||||
return roblox_user
|
|
||||||
end
|
|
||||||
return 'Something went wrong (this should generally not happen)'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- [[ ROBLOX / FIVEMAN AND OTHER APIs ]] --
|
|
||||||
|
|
||||||
function API:GetRobloxInfoFromUserId(USER_ID)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local response,headers = http_request('GET', ROBLOX_API_URL..'users/'..USER_ID, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetRobloxInfoFromUsername(USERNAME)
|
|
||||||
if not USERNAME then return 'empty username' end
|
|
||||||
if #USERNAME > 32 then return 'Username too long' end
|
|
||||||
local response,headers = http_request('POST', ROBLOX_API_URL..'usernames/users', API_HEADER, {usernames={USERNAME}})
|
|
||||||
if not response.data[1] then return 'Username \''..USERNAME..'\' not found.' end
|
|
||||||
return self:GetRobloxInfoFromUserId(response.data[1].id)
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetRobloxInfoFromDiscordId(DISCORD_ID)
|
|
||||||
if not DISCORD_ID then return 'empty id' end
|
|
||||||
local response,headers = http_request('GET', FIVEMAN_API_URL..'users/'..DISCORD_ID, API_HEADER)
|
|
||||||
if response.status=='error' then return response.messages end
|
|
||||||
local response2 = http_request('GET', ROBLOX_API_URL..'users/'..response.result.robloxId, API_HEADER)
|
|
||||||
return response2
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetUserOnlineStatus(USER_ID)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local response1 = http_request('POST', ROBLOX_PRESENCE_URL..'presence/users', API_HEADER, {userIds={USER_ID}}).userPresences[1] --For LastLocation
|
|
||||||
local response2 = http_request('POST', ROBLOX_PRESENCE_URL..'presence/last-online', API_HEADER, {userIds={USER_ID}}).lastOnlineTimestamps[1] --For a more accurate LastOnline
|
|
||||||
L1Copy(response2, response1)
|
|
||||||
return response1
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetUserUsernameHistory(USER_ID)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local err, res = parseToURLArgs({limit=50,sortOrder='Desc'})
|
|
||||||
if err then return err end
|
|
||||||
local response1 = http_request('GET', ROBLOX_API_URL..'users/'..USER_ID..'/username-history'..res,API_HEADER)
|
|
||||||
return response1
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetBadgesAwardedDates(USER_ID,BADGE_LIST)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local err,res = parseToURLArgs({badgeIds=table.concat(BADGE_LIST,',')})
|
|
||||||
if err then return end
|
|
||||||
local response,headers = http_request('GET',ROBLOX_BADGES_API..'users/'..USER_ID..'/badges/awarded-dates'..res)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetVerificationItemID(USER_ID)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local response1,headers1 = http_request('GET', ROBLOX_INVENTORY_API..'users/'..USER_ID.."/items/Asset/102611803", API_HEADER)
|
|
||||||
if response1.errors then return response1,headers1 end
|
|
||||||
local response2,headers2 = http_request('GET', ROBLOX_INVENTORY_API..'users/'..USER_ID.."/items/Asset/1567446", API_HEADER)
|
|
||||||
if response2.errors then return response2,headers2 end
|
|
||||||
local data = {}
|
|
||||||
data[#data+1] = response2.data[1] -- Do the older item first if present
|
|
||||||
data[#data+1] = response1.data[1]
|
|
||||||
return {data=data},headers1
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetUserThumbnail(USER_ID,TYPE,SIZE) -- https://thumbnails.roblox.com/v1/users/avatar?userIds=1455906620&size=180x180&format=Png&isCircular=false
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local _TYPE = self.ROBLOX_THUMBNAIL_TYPES[TYPE] or 'avatar'
|
|
||||||
local _SIZE = self.ROBLOX_THUMBNAIL_SIZES[SIZE] or '180x180'
|
|
||||||
local err, res = parseToURLArgs({userIds=USER_ID,size=_SIZE,format='Png',isCircular=false})
|
|
||||||
if err then return err end
|
|
||||||
local response,headers = http_request('GET', ROBLOX_THUMBNAIL_URL..'users/'.._TYPE..res, API_HEADER)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetGroups(USER_ID)
|
|
||||||
if not USER_ID then return 'empty id' end
|
|
||||||
local response,headers = http_request('GET',string.format(ROBLOX_GROUPS_ROLES_URL,USER_ID))
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
|
|
||||||
function API:GetSensWithParams(ARGUMENTS)
|
|
||||||
local hasarg = false
|
|
||||||
for _,val in next,ARGUMENTS do
|
|
||||||
if val then
|
|
||||||
hasarg=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ARGUMENTS.format='json'
|
|
||||||
local err,res = parseToURLArgs(ARGUMENTS)
|
|
||||||
if err then return err end
|
|
||||||
local response,headers=http_request('GET',ROBLOX_SENS_DB..(hasarg and 'get' or 'get/all')..res)
|
|
||||||
return response,headers
|
|
||||||
end
|
|
||||||
|
|
||||||
return API
|
|
@ -1,6 +1,7 @@
|
|||||||
local Discordia = require('discordia')
|
local Discordia = require('discordia')
|
||||||
local json = require('json')
|
local json = require('json')
|
||||||
local http_request = require('../Modules/http.lua')
|
local HttpRequest = require('../Modules/HttpRequest.lua')
|
||||||
|
local Request = HttpRequest.Request
|
||||||
local SubCommandHandler = require('../Modules/SubCommandHandler.lua')
|
local SubCommandHandler = require('../Modules/SubCommandHandler.lua')
|
||||||
Discordia.extensions()
|
Discordia.extensions()
|
||||||
|
|
||||||
@ -12,8 +13,10 @@ local MinecraftSubCommandHandler = SubCommandHandler.new()
|
|||||||
|
|
||||||
local MinecraftMainCommand = SlashCommandTools.slashCommand('minecraft', 'Minecraft server related commands')
|
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 MinecraftStatusSubCommand = SlashCommandTools.subCommand('status',
|
||||||
local MinecraftSetIpSubCommand = SlashCommandTools.subCommand('setip', 'Set the preferred Minecraft server IP address for this server')
|
'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')
|
local MinecraftSetIpOptions = SlashCommandTools.string('ip', 'The IP address of the server')
|
||||||
MinecraftSetIpOptions:setRequired(true)
|
MinecraftSetIpOptions:setRequired(true)
|
||||||
@ -54,17 +57,20 @@ MinecraftSubCommandHandler:AddSubCommand(MinecraftStatusSubCommand.name, functio
|
|||||||
end
|
end
|
||||||
|
|
||||||
local ServerIPStr = ServerMinecraftData.IP .. ':' .. ServerMinecraftData.PORT
|
local ServerIPStr = ServerMinecraftData.IP .. ':' .. ServerMinecraftData.PORT
|
||||||
local Response, Headers = http_request('GET', ('https://api.mcsrvstat.us/3/%s'):format(ServerIPStr))
|
local Headers, Body = Request("GET", ('https://api.mcsrvstat.us/3/%s'):format(ServerIPStr), nil,
|
||||||
|
{ ["User-Agent"] = "tommy-bot/1.0 Main-Release" })
|
||||||
local IsOnline = Response.online
|
if not Headers.code == 200 then
|
||||||
|
return error("Something went wrong")
|
||||||
|
end
|
||||||
|
local IsOnline = Body.online
|
||||||
local EmbedData
|
local EmbedData
|
||||||
if IsOnline then
|
if IsOnline then
|
||||||
local MaxPlayers = Response.players.max
|
local MaxPlayers = Body.players.max
|
||||||
local OnlinePlayers = Response.players.online
|
local OnlinePlayers = Body.players.online
|
||||||
local AnonymousPlayers = OnlinePlayers
|
local AnonymousPlayers = OnlinePlayers
|
||||||
local Players = {}
|
local Players = {}
|
||||||
if OnlinePlayers > 0 then
|
if OnlinePlayers > 0 then
|
||||||
for PlayerIndex, PlayerData in next, Response.players.list do
|
for PlayerIndex, PlayerData in next, Body.players.list do
|
||||||
table.insert(Players, PlayerData.name)
|
table.insert(Players, PlayerData.name)
|
||||||
AnonymousPlayers = AnonymousPlayers - 1
|
AnonymousPlayers = AnonymousPlayers - 1
|
||||||
end
|
end
|
||||||
@ -78,7 +84,7 @@ MinecraftSubCommandHandler:AddSubCommand(MinecraftStatusSubCommand.name, functio
|
|||||||
end
|
end
|
||||||
EmbedData = {
|
EmbedData = {
|
||||||
title = 'Server Status for ' .. ServerIPStr,
|
title = 'Server Status for ' .. ServerIPStr,
|
||||||
description = Response.motd.clean[1]..' ('..Response.version..')',
|
description = Body.motd.clean[1] .. ' (' .. Body.version .. ')',
|
||||||
fields = {
|
fields = {
|
||||||
{ name = 'Players', value = OnlinePlayers .. '/' .. MaxPlayers, inline = true },
|
{ name = 'Players', value = OnlinePlayers .. '/' .. MaxPlayers, inline = true },
|
||||||
{ name = 'List of players', value = table.concat(Players, '\n'), inline = true }
|
{ name = 'List of players', value = table.concat(Players, '\n'), inline = true }
|
||||||
|
@ -4,7 +4,7 @@ local Discordia = require('discordia')
|
|||||||
local Date = Discordia.Date
|
local Date = Discordia.Date
|
||||||
Discordia.extensions()
|
Discordia.extensions()
|
||||||
|
|
||||||
local API = require('../Modules/strafes_net.lua')
|
local StrafesNET = require('../Modules/StrafesNET.lua')
|
||||||
|
|
||||||
local UserCommand = SlashCommandTools.slashCommand('user', 'Looks up specified user on Roblox')
|
local UserCommand = SlashCommandTools.slashCommand('user', 'Looks up specified user on Roblox')
|
||||||
|
|
||||||
@ -58,7 +58,6 @@ local IDToDate = { --Terrible ranges but it's all we have
|
|||||||
{ 232802028144, FromYMD("2024-04-08") },
|
{ 232802028144, FromYMD("2024-04-08") },
|
||||||
{ 234886704167, FromYMD("2024-06-28") },
|
{ 234886704167, FromYMD("2024-06-28") },
|
||||||
{ 241580400713, FromYMD("2025-02-16") },
|
{ 241580400713, FromYMD("2025-02-16") },
|
||||||
{244356127782, FromYMD("2025-05-18")},
|
|
||||||
}
|
}
|
||||||
--We assume linear interpolation since anything more complex I can't process
|
--We assume linear interpolation since anything more complex I can't process
|
||||||
local function linterp(i1, i2, m)
|
local function linterp(i1, i2, m)
|
||||||
@ -95,16 +94,16 @@ local function Callback(Interaction, Command, Args)
|
|||||||
local user_id = Args.user_id
|
local user_id = Args.user_id
|
||||||
local member = Args.member
|
local member = Args.member
|
||||||
if username then
|
if username then
|
||||||
user_info = API:GetRobloxInfoFromUsername(username)
|
_, user_info = StrafesNET.GetRobloxInfoFromUsername(username)
|
||||||
elseif user_id then
|
elseif user_id then
|
||||||
user_info = API:GetRobloxInfoFromUserId(user_id)
|
_, user_info = StrafesNET.GetRobloxInfoFromUserId(user_id)
|
||||||
elseif member then
|
elseif member then
|
||||||
user_info = API:GetRobloxInfoFromDiscordId(member.id)
|
_, user_info = StrafesNET.GetRobloxInfoFromDiscordId(member.id)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local user = Interaction.member or Interaction.user
|
local user = Interaction.member or Interaction.user
|
||||||
if user then
|
if user then
|
||||||
user_info = API:GetRobloxInfoFromDiscordId(user.id)
|
_, user_info = StrafesNET.GetRobloxInfoFromDiscordId(user.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not user_info.id then
|
if not user_info.id then
|
||||||
@ -112,7 +111,6 @@ local function Callback(Interaction, Command, Args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local description = user_info.description == '' and 'This user has no description' or user_info.description
|
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 created = tostring(Date.fromISO(user_info.created):toSeconds())
|
||||||
local current = Date():toSeconds()
|
local current = Date():toSeconds()
|
||||||
local accountAge = round((current - created) / 86400)
|
local accountAge = round((current - created) / 86400)
|
||||||
@ -121,7 +119,8 @@ local function Callback(Interaction, Command, Args)
|
|||||||
local name = user_info.name
|
local name = user_info.name
|
||||||
local displayName = user_info.displayName
|
local displayName = user_info.displayName
|
||||||
|
|
||||||
local usernameHistory = API:GetUserUsernameHistory(id).data or {}
|
local usernameHistoryHeaders, usernameHistoryBody = StrafesNET.GetUserUsernameHistory(id)
|
||||||
|
local usernameHistory = usernameHistoryBody.data or {}
|
||||||
local usernameHistoryTable = {}
|
local usernameHistoryTable = {}
|
||||||
for index, usernameObj in next, usernameHistory do
|
for index, usernameObj in next, usernameHistory do
|
||||||
table.insert(usernameHistoryTable, usernameObj.name)
|
table.insert(usernameHistoryTable, usernameObj.name)
|
||||||
@ -135,7 +134,7 @@ local function Callback(Interaction, Command, Args)
|
|||||||
if onlineStatus_info.userPresenceType == 2 then LastLocation = "Ingame" end
|
if onlineStatus_info.userPresenceType == 2 then LastLocation = "Ingame" end
|
||||||
local LastOnline = 0 --Date.fromISO(onlineStatus_info.lastOnline):toSeconds()
|
local LastOnline = 0 --Date.fromISO(onlineStatus_info.lastOnline):toSeconds()
|
||||||
|
|
||||||
local verificationAssetId = API:GetVerificationItemID(id)
|
local verificationAssetId = StrafesNET.GetVerificationItemID(id)
|
||||||
local verificationDate = "Not verified"
|
local verificationDate = "Not verified"
|
||||||
if verificationAssetId.errors then
|
if verificationAssetId.errors then
|
||||||
verificationDate = "Failed to fetch"
|
verificationDate = "Failed to fetch"
|
||||||
@ -149,7 +148,7 @@ local function Callback(Interaction, Command, Args)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local badgeRequest = API:GetBadgesAwardedDates(id,Badges)
|
local _, badgeRequest = StrafesNET.GetBadgesAwardedDates(id, Badges)
|
||||||
local badgeData = badgeRequest.data
|
local badgeData = badgeRequest.data
|
||||||
|
|
||||||
-- local badgesDates = {}
|
-- local badgesDates = {}
|
||||||
@ -160,11 +159,11 @@ local function Callback(Interaction, Command, Args)
|
|||||||
local awardedDate = tonumber(Date.fromISO(badge.awardedDate):toSeconds())
|
local awardedDate = tonumber(Date.fromISO(badge.awardedDate):toSeconds())
|
||||||
if firstBadgeDate > awardedDate then
|
if firstBadgeDate > awardedDate then
|
||||||
firstBadge = badgeId
|
firstBadge = badgeId
|
||||||
firstBadgeDate=awardedDate
|
|
||||||
end
|
end
|
||||||
-- badgesDates[badgeId]=awardedDate
|
-- badgesDates[badgeId]=awardedDate
|
||||||
end
|
end
|
||||||
local userThumbnail = API:GetUserThumbnail(id).data[1]
|
local userThumbnailHeaders, userThumbnailBody = StrafesNET.GetUserThumbnail(id)
|
||||||
|
local userThumbnail = userThumbnailBody.data[1]
|
||||||
|
|
||||||
local embed = {
|
local embed = {
|
||||||
title = displayName .. ' (@' .. name .. ')',
|
title = displayName .. ' (@' .. name .. ')',
|
||||||
|
Reference in New Issue
Block a user