Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#96 - Initial work on the debugger #142

Merged
merged 9 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ body:
value: |
Thanks for taking the time to fill out this bug report! Before posting be sure that it's not a duplicate of any previous posted issues by using the search function.
Please note that we do not support outdated versions. Always use the latest stable release.
- type: dropdown
id: version
- type: input
id: bug-report-token
attributes:
label: Your fun-bots version
description: What version of fun-bots does this issue occur on? Please note that we do not support old versions. Select the correct version.
options:
- 2.2.0-RC (release candidates)
- 2.2.0 (stable release)
- 2.3.0-dev (development builds)
label: Bug report token
description: |
Generate a bug report using the `!bugreport` command and enter the token or URL here.
This is a **required** step to create the bug report, any bug report without this token will be closed.
When reporting multiple bugs, use the same bug report token as long as you've made no changes to the server or configuration. You can only create 3 bug reports every 24 hours.
placeholder: https://report.funbots.dev/7e1...
validations:
required: true
- type: textarea
Expand Down Expand Up @@ -57,6 +57,4 @@ body:
- label: I have read the [contribution guidelines on reporting bugs](https://github.com/Joe91/fun-bots/blob/master/.github/CONTRIBUTING.md#reporting-a-bug) and the [code of conduct](https://github.com/Joe91/fun-bots/blob/master/.github/CODE_OF_CONDUCT.md).
required: true
- label: I have tested and reproduced this bug without any other mods besides fun-bots.
required: false
- label: I have tested and reproduced this bug with the default fun-bots configuration file.
required: false
13 changes: 10 additions & 3 deletions ext/Server/Commands/Chat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local m_NodeCollection = require('__shared/NodeCollection')

local m_BotManager = require('BotManager')
local m_BotSpawner = require('BotSpawner')
local m_Debug = require('Debug/Debugger')

function ChatCommands:Execute(p_Parts, p_Player)
if p_Player == nil or Config.DisableChatCommands == true then
Expand Down Expand Up @@ -173,9 +174,6 @@ function ChatCommands:Execute(p_Parts, p_Player)

Config.BotAimWorsening = tonumber(p_Parts[2]) or 0.5
--self:_modifyWeapons(Config.BotAimWorsening) --causes lag. Instead restart round
if Debug.Server.COMMAND then
print('difficulty set to ' .. Config.BotAimWorsening .. '. Please restart round or level to take effect')
end
elseif p_Parts[1] == '!shootback' then
if PermissionManager:HasPermission(p_Player, 'ChatCommands.ShootBack') == false then
ChatManager:SendMessage('You have no permissions for this action (ChatCommands.ShootBack).', p_Player)
Expand Down Expand Up @@ -333,6 +331,15 @@ function ChatCommands:Execute(p_Parts, p_Player)

local s_TraceIndex = tonumber(p_Parts[2]) or 0
NetEvents:SendToLocal('ClientNodeEditor:SaveTrace', p_Player, s_TraceIndex)

-- Debug: Generate debug report
elseif p_Parts[1] == '!bugreport' then
if PermissionManager:HasPermission(p_Player, 'Debug.BugReport') == false then
ChatManager:SendMessage('You have no permissions for this action (Debug.BugReport).', p_Player)
return
end

Debugger:GenerateReport(p_Player)
end
end

Expand Down
5 changes: 4 additions & 1 deletion ext/Server/Constants/Permissions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,8 @@ Permissions = {
'UserInterface.WaypointEditor.TraceReset',

-- Settings
'UserInterface.Settings'
'UserInterface.Settings',

-- Debugger
'Debug.BugReport'
}
Empty file added ext/Server/Debug/BugReport.lua
Empty file.
133 changes: 133 additions & 0 deletions ext/Server/Debug/Debugger.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
class('Debugger')

-- Create a bug report using an in-game !bugreport command.
-- A bug report is required in order to create a new issue on the Github.
-- Abuse of the bug reporting system will lead into getting suspended from all fun-bots services, including support.
-- Do not change this without input from @Firjens (unless minor or text changes) to prevent unwanted behavior.
-- Author: @Firjen on 12/07/21 (finished on 20/08/21) for V2.3.0

-- The version used for API related things. The moment new features are required for debugging the REST API end-point will know that this is a newer or older version.
local DEBUG_VERSION = 1

-- The URL to the official reporting website.
local DEBUG_REPORT_URL = "https://report.funbots.dev"

-- Pre-check path (checks if a report can be made)
local DEBUG_ELIGIABLE_PATH = "/api/precheck"

-- Path to submit a bug report
local DEBUG_SUBMIT_PATH = "/api/submit"

-- Timestamp of the latest report created by anyone with permission. Uesd for reporting cooldown
local DEBUG_LAST_REPORT = 0

-- Cooldown between bug reports in milliseconds. You are limited to a certain reports per 24 hours, and it's useless to create a new report when no major changes were made.
local DEBUG_REPORT_COOLDOWN = 60*1000*3 -- 3 minutes cooldown

-- This function is solely run by someone with permissions running the in-game !bugreport command.
-- Param: p_Player - User who initiated the request
function Debugger:GenerateReport(p_Player)
-- Check if there is a current cooldown active, if so, return and tell the user.
if DEBUG_LAST_REPORT ~= nil and (DEBUG_LAST_REPORT - SharedUtils:GetTimeMS() > 0) then
ChatManager:Yell("A report was recently made, please wait " .. ReadableTimetamp((DEBUG_LAST_REPORT-SharedUtils:GetTimeMS()), TimeUnits.FIT, 1) .. " before creating a new report", 5.0, p_Player)
do return end
end

-- Set the current cooldown. There is no point in spamming it if the servers are down.
DEBUG_LAST_REPORT = SharedUtils:GetTimeMS() + DEBUG_REPORT_COOLDOWN

-- Check that the server GUID is correctly set.
if RCON:GetServerGuid() == nil then
ChatManager:Yell("Failed to create bug report. Server GUID is null", 5.0, p_Player)
print("[Debugger: Report] Failure to create a bug report. Server GUID is null.");
print("[Debugger: Report] This is not a fun-bots bug, please contact Venice Unleashed.");
do return end
end

-- Notify the user that we are creating a new bug report
print("[Debugger: Report] " .. p_Player.name .. " is creating a new bug report.");
ChatManager:Yell("Creating a new bug report...", 5.0, p_Player)

-- Contact the eligiable end point to see if we are allowed to even make a bug report. We may be rate limited? We may be suspended because we abused it?
-- No need to send the whole config to one end point as this can use precious server resources and networking.
local s_CheckURL = DEBUG_REPORT_URL .. DEBUG_ELIGIABLE_PATH .. "?uuid=" .. RCON:GetServerGuid():ToString("D");
Net:GetHTTPAsync(s_CheckURL, function(p_HttpResponse)
-- Check if the server has answered, even upon an error a JSON payload is returned with a message, if this isn't the case it's most likely the server that failed to contact it.
if p_HttpResponse == nil then
ChatManager:Yell("Failed to create bug report. Unable to contact report server.", 5.0, p_Player)
print("[Debugger: Report] Failure to precheck for a bug report. Unable to contact report server. Please check your internet connection and try again later.");
do return end
end

local s_Json = json.decode(p_HttpResponse.body)

-- Rate limiting, a limited amount of reports are allowed to be made within 24 hours.
if p_HttpResponse.status == 429 then
ChatManager:Yell("Too many bug reports created, try again in " .. ReadableTimetamp(s_Json.try_again, TimeUnits.FIT, 1), 5.0, p_Player)
print("[Debugger: Report] Failure to precheck for a bug report. Too many bug reports created, try again in " .. ReadableTimetamp(s_Json.try_again, TimeUnits.FIT, 0));
do return end
end

-- Other than rate limiting or OK means that the server has some kind of issue.
if p_HttpResponse.status ~= 200 then
ChatManager:Yell("Failed to create bug report. Returned HTTP code " .. p_HttpResponse.status, 5.0, p_Player)
print("[Debugger: Report] Failure to precheck for a bug report. Returned HTTP code " .. p_HttpResponse.status);
do return end
end

-- Report can be created as server returned error 200.
local s_SubmitURL = DEBUG_REPORT_URL .. DEBUG_SUBMIT_PATH .. "?uuid=" .. RCON:GetServerGuid():ToString("D");

-- This should not be modified as the server checks everything, parses it and validates it.
-- When something misses or gets added the server will reject the request.
local s_ReportData = {
debugversion = DEBUG_VERSION,
config = Config,
staticconfig = StaticConfig,
version = Config.Version.Tag,
author_name = p_Player.name,
author_guid = p_Player.guid,
map_id = SharedUtils:GetLevelName(),
gamemode_id = SharedUtils:GetCurrentGameMode()
}

-- Post the bug report information to the server
Net:PostHTTPAsync(s_SubmitURL, json.encode(s_ReportData), function(p_HttpResponse)
if p_HttpResponse == nil then
ChatManager:Yell("Failed to create bug report. Unable to contact report server.", 5.0, p_Player)
print("[Debugger: Report] Failure to post for a bug report. Unable to contact report server. Please check your internet connection and try again later.");
do return end
end

local s_Json = json.decode(p_HttpResponse.body)

-- 403 forbidden contains a message why it's forbidden. Show to user.
if p_HttpResponse.status == 403 then
ChatManager:Yell("Failed to create bug report. Server returned: " .. s_Json.message, 5.0, p_Player)
print("[Debugger: Report] Failure to post a bug report. Returned HTTP code " .. p_HttpResponse.status .. " with message: " .. s_Json.message);
do return end
end

-- If token fetch token and return token to user
if p_HttpResponse.status == 200 and s_Json.token ~= nil then
ChatManager:Yell("Success! Your report token is: " .. s_Json.token, 45.0, p_Player)
ChatManager:SendMessage("Bug report created: report.funbots.dev/" .. s_Json.token, p_Player)
print("[Debugger: Report] A new bug report is created and can be viewed on: report.funbots.dev/" .. s_Json.token);
do return end
end

ChatManager:Yell("Failed to create bug report. Returned HTTP code " .. p_HttpResponse.status, 5.0, p_Player)
print("[Debugger: Report] Failure to post a bug report. Returned HTTP code " .. p_HttpResponse.status .. " with message: " .. s_Json.message);
end)
end)
end

function Debugger:__init()
local s_start = SharedUtils:GetTimeMS()

print("Loaded debugger v2 in " .. ReadableTimetamp(os.time(os.date("!*t")) - s_start, TimeUnits.FIT, 1) .. " ms")

return true
end

return Debugger:__init()
1 change: 1 addition & 0 deletions ext/Server/__init__.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local m_SettingsManager = require('SettingsManager')
local m_BotManager = require('BotManager')
local m_BotSpawner = require('BotSpawner')
local m_WeaponList = require('__shared/WeaponList')
local m_Debugger = require('Debug/Debugger')
local m_ChatCommands = require('Commands/Chat')
local m_Console = require('Commands/Console')
local m_RCONCommands = require('Commands/RCON')
Expand Down
61 changes: 61 additions & 0 deletions ext/Shared/Utils/Timestamp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,65 @@ function ParseOffset(p_String)
end

return s_Timestamp + s_Offset
end

-- Enums for different time units used to convert milliseconds into a readable format to the clients.
-- Author: Firjen (19/08/21)
TimeUnits = {
FIT = 99,
DAYS = 4,
HOURS = 3,
MINUTES = 2,
SECONDS = 1,
}

-- Trim a large number to a smaller number with specified degree (numbers behind the comma)
-- Param: degree - Total numbers
-- Param: integer - number to trim
-- Author: Firjen (19/08/21)
-- Return: String [Double-like] (eg. 2.1, 1.6, 0.5)
function Trim(degree, integer)
return string.format("%.1f",integer)
end

-- Convert to a readable format (eg. 5 Minutes, 12 Seconds, etc.)
-- Author: Firjen (19/08/21)
-- Return: String (Eg. Permanent, 12 Seconds, 5 Minutes)
function ReadableTimetamp(p_Time, p_TimeUnit, p_Trim)
-- When time is equal to 0 it's now
if p_Time == 0 then
return "Now"
end

-- Anything less than 0 (eg. time is -1), it's considered permanent
if p_Time < 0 then
return "Permanent"
end

-- If fit pick the best timeunit
if p_TimeUnit == TimeUnits.FIT then
if p_Time < 60000 then
p_TimeUnit = TimeUnits.SECONDS
elseif p_Time < 3600000 then
p_TimeUnit = TimeUnits.MINUTES
elseif p_Time < 86400000 then
p_TimeUnit = TimeUnits.HOURS
else
p_TimeUnit = TimeUnits.DAYS
end
end


if p_TimeUnit == TimeUnits.DAYS then
return Trim(p_Trim, p_Time / 8.64E7) .. " Days"
elseif p_TimeUnit == TimeUnits.HOURS then
return Trim(p_Trim, p_Time / 3600000) .. " Hours"
elseif p_TimeUnit == TimeUnits.MINUTES then
return Trim(p_Trim, p_Time / 60000.) .. " Minutes"
elseif p_TimeUnit == TimeUnits.SECONDS then
return Trim(p_Trim, p_Time / 1000) .. " Seconds"

else
return Trim(p_Trim, p_Time) .. " Milliseconds"
end
end