974 lines
29 KiB
Lua
974 lines
29 KiB
Lua
if (!SH_REPORTS.ActiveReports) then
|
|
SH_REPORTS.ActiveReports = {}
|
|
SH_REPORTS.UniqueID = 0
|
|
SH_REPORTS.InsertSQL = "INSERT IGNORE INTO"
|
|
end
|
|
|
|
if (SH_REPORTS.UseWorkshop) then
|
|
-- resource.AddWorkshop("1141886968")
|
|
else
|
|
resource.AddFile("materials/shenesis/general/back.png")
|
|
resource.AddFile("materials/shenesis/general/close.png")
|
|
resource.AddFile("materials/shenesis/reports/add.png")
|
|
resource.AddFile("materials/shenesis/reports/stats.png")
|
|
resource.AddFile("materials/shenesis/reports/star.png")
|
|
resource.AddFile("resource/fonts/circular.ttf")
|
|
resource.AddFile("resource/fonts/circular_bold.ttf")
|
|
end
|
|
|
|
function SH_REPORTS:DatabaseConnected()
|
|
if (self.DatabaseMode == "mysqloo") then
|
|
self:Query("SHOW TABLES LIKE 'sh_reports_performance'", function(q, ok, data)
|
|
if (!ok) or (data and table.Count(data) > 0) then
|
|
self:PostDatabaseConnected()
|
|
return
|
|
end
|
|
|
|
self:Query([[
|
|
CREATE TABLE `sh_reports_performance` (
|
|
`steamid` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
|
|
`claimed` int(10) unsigned DEFAULT '0',
|
|
`closed` int(10) unsigned DEFAULT '0',
|
|
`timespent` int(10) unsigned DEFAULT '0',
|
|
`report_id` int(10) unsigned DEFAULT '0',
|
|
UNIQUE KEY `steamid_UNIQUE` (`steamid`,`report_id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
|
|
CREATE TABLE `sh_reports_performance_reports` (
|
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
|
`start_time` int(10) unsigned DEFAULT '0',
|
|
`end_time` int(10) unsigned DEFAULT '0',
|
|
PRIMARY KEY (`id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
]], function(q2, ok2, data2)
|
|
self:DBPrint("Creating sh_reports_performance and sh_reports_performance_reports: " .. tostring(ok2) .. " (" .. tostring(data2) /* 76561198398853149 */ .. ")")
|
|
self:PostDatabaseConnected()
|
|
end)
|
|
end)
|
|
|
|
self:Query("SHOW TABLES LIKE 'sh_reports_performance_ratings'", function(q, ok, data)
|
|
if (!ok) or (data and table.Count(data) > 0) then
|
|
return end
|
|
|
|
self:Query([[
|
|
CREATE TABLE `sh_reports_performance_ratings` (
|
|
`steamid` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
|
|
`total` int(10) unsigned DEFAULT '0',
|
|
`num` int(10) unsigned DEFAULT '0',
|
|
PRIMARY KEY (`steamid`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
]], function(q2, ok2, data2)
|
|
self:DBPrint("Creating sh_reports_performance_ratings: " .. tostring(ok2) .. " (" .. tostring(data2) /* 76561198398853124 */ .. ")")
|
|
end)
|
|
end)
|
|
|
|
self:Query("SHOW TABLES LIKE 'sh_reports_performance_history'", function(q, ok, data)
|
|
if (!ok) or (data and table.Count(data) > 0) then
|
|
return end
|
|
|
|
self:Query([[
|
|
CREATE TABLE `sh_reports_performance_history` (
|
|
`id` int(10) unsigned NOT NULL,
|
|
`reporter` varchar(64) NOT NULL,
|
|
`reported` varchar(64) NOT NULL,
|
|
`reason` varchar(256),
|
|
`comment` varchar(2048),
|
|
`waiting_time` int(10) unsigned DEFAULT '0',
|
|
`date` int(10) unsigned DEFAULT '0',
|
|
`admin` varchar(64) NOT NULL,
|
|
`rating` int(10) unsigned DEFAULT '0',
|
|
PRIMARY KEY (`id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
]], function(q2, ok2, data2)
|
|
self:DBPrint("Creating sh_reports_performance_history: " .. tostring(ok2) .. " (" .. tostring(data2) .. ")")
|
|
end)
|
|
end)
|
|
else
|
|
local function CreateTable(name, query)
|
|
if (!sql.TableExists(name)) then
|
|
sql.Query([[
|
|
CREATE TABLE `]] .. name .. [[` (]] .. query .. [[)
|
|
]])
|
|
|
|
self:DBPrint("Creating " .. name .. ": " .. tostring(sql.TableExists(name)))
|
|
end
|
|
end
|
|
|
|
CreateTable("sh_reports_performance", [[
|
|
`steamid` varchar(64) NOT NULL,
|
|
`claimed` int(10) DEFAULT '0',
|
|
`closed` int(10) DEFAULT '0',
|
|
`timespent` int(10) DEFAULT '0',
|
|
`report_id` int(10) DEFAULT '0',
|
|
UNIQUE(steamid, report_id) ON CONFLICT IGNORE
|
|
]])
|
|
|
|
CreateTable("sh_reports_performance_reports", [[
|
|
`id` int(10) NOT NULL PRIMARY KEY,
|
|
`start_time` int(10) DEFAULT '0',
|
|
`end_time` int(10) DEFAULT '0'
|
|
]])
|
|
|
|
CreateTable("sh_reports_performance_ratings", [[
|
|
`steamid` varchar(64) NOT NULL PRIMARY KEY,
|
|
`total` int(10) DEFAULT '0',
|
|
`num` int(10) DEFAULT '0'
|
|
]])
|
|
|
|
CreateTable("sh_reports_performance_history", [[
|
|
`id` int(10) NOT NULL PRIMARY KEY,
|
|
`reporter` varchar(64) NOT NULL,
|
|
`reported` varchar(64) NOT NULL,
|
|
`reason` varchar(256),
|
|
`comment` varchar(2048),
|
|
`waiting_time` int(10) DEFAULT '0',
|
|
`date` int(10) DEFAULT '0',
|
|
`admin` varchar(64) NOT NULL,
|
|
`rating` int(5) DEFAULT '0'
|
|
]])
|
|
|
|
self.InsertSQL = "INSERT OR IGNORE INTO"
|
|
self:PostDatabaseConnected()
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:PostDatabaseConnected()
|
|
self:BetterQuery("SELECT * FROM sh_reports_performance_reports WHERE {time} < end_time ORDER BY id DESC", {time = os.time()}, function(q, ok, data)
|
|
if (!ok) then
|
|
return end
|
|
|
|
if (data and #data > 0) then
|
|
local d = table.Copy(data[1])
|
|
d.id = tonumber(d.id)
|
|
d.start_time = tonumber(d.start_time)
|
|
d.end_time = tonumber(d.end_time)
|
|
|
|
self.CurrentPerfReport = d
|
|
self:DBPrint("Using performance report #" .. d.id .. ". It will last until " .. os.date(self.DateFormat, d.end_time) .. " 00:00.")
|
|
else
|
|
self:DBPrint("Creating new performance report as none were found.")
|
|
self:CreatePerformanceReport()
|
|
end
|
|
end)
|
|
|
|
if (self.StorageExpiryTime > 0) then
|
|
self:BetterQuery("DELETE FROM sh_reports_performance_history WHERE {time} > date", {time = os.time() - self.StorageExpiryTime})
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:CreatePerformanceReport()
|
|
local days = 1
|
|
if (self.PerformanceFrequency == "weekly") then
|
|
days = 7 - tonumber(os.date("%w")) + self.PerformanceWeekDay
|
|
elseif (self.PerformanceFrequency == "monthly") then
|
|
days = 31
|
|
end
|
|
local mthen = self:GetMidnight(days)
|
|
|
|
self:Query("SELECT id FROM sh_reports_performance_reports", function(q, ok, data)
|
|
if (!ok) then
|
|
return end
|
|
|
|
local d = {id = table.Count(data) + 1, start_time = os.time(), end_time = mthen}
|
|
self.CurrentPerfReport = d
|
|
|
|
self:BetterQuery([[
|
|
INSERT INTO sh_reports_performance_reports (id, start_time, end_time)
|
|
VALUES ({id}, {start_time}, {end_time})
|
|
]], d)
|
|
|
|
self:DBPrint("Created performance report #" .. d.id .. ". It will last until " .. os.date(self.DateFormat, mthen) .. " 00:00.")
|
|
end)
|
|
|
|
self.CachedPerfReports = nil
|
|
end
|
|
|
|
function SH_REPORTS:NewReport(ply, data)
|
|
if (self:IsAdmin(ply) and !self.StaffCanReport) then
|
|
self:Notify(ply, "cannot_report_as_admin", false)
|
|
return
|
|
end
|
|
|
|
if (data.reporter_id == data.reported_id) then
|
|
self:Notify(ply, "cannot_report_self", false)
|
|
return
|
|
end
|
|
|
|
local target = player.GetBySteamID64(data.reported_id)
|
|
if (IsValid(target) and self:IsAdmin(target) and !self.StaffCanBeReported) then
|
|
self:Notify(ply, "cannot_report_admin", false)
|
|
return
|
|
end
|
|
|
|
local sid = ply:SteamID64()
|
|
if (table.Count(self:GetAllReports(sid)) >= self.MaxReportsPerPlayer) then
|
|
self:Notify(ply, "report_limit_reached", false)
|
|
return
|
|
end
|
|
|
|
if (data.reported_id == "0" and !self.CanReportOther) then
|
|
return end
|
|
|
|
self.UniqueID = self.UniqueID + 1
|
|
data.id = self.UniqueID
|
|
self.ActiveReports[data.id] = table.Copy(data)
|
|
|
|
self:Notify(ply, "report_submitted", true)
|
|
self:Log(ply:Nick() .. " <" .. ply:SteamID() .. "> reported [#" .. data.id .. "] " .. data.reported_name .. " <" .. util.SteamIDFrom64(data.reported_id /* 76561198398853124 */) .. "> for " .. self.ReportReasons[data.reason_id])
|
|
|
|
easynet.Send(self:GetStaff(), "SH_REPORTS.ReportCreated", data)
|
|
end
|
|
|
|
function SH_REPORTS:PlayerSay(ply, str)
|
|
local text = str:Replace("!", "/"):lower():Trim()
|
|
|
|
if (self.AdminCommands[text]) then
|
|
self:ShowReports(ply)
|
|
return ""
|
|
end
|
|
|
|
if (self.ReportCommands[text]) then
|
|
if (!self:IsAdmin(ply) or self.StaffCanReport) then
|
|
easynet.Send(ply, "SH_REPORTS.QuickReport", {comment = "", lastkiller = ply.SH_LastKiller, lastarrester = ply.SH_LastArrester})
|
|
else
|
|
self:Notify(ply, "cannot_report_as_admin", false)
|
|
end
|
|
|
|
return ""
|
|
end
|
|
|
|
if (self.EnableQuickReport and !self:IsAdmin(ply) and text:StartWith("@")) then
|
|
easynet.Send(ply, "SH_REPORTS.QuickReport", {comment = str:sub(2), lastkiller = ply.SH_LastKiller, lastarrester = ply.SH_LastArrester})
|
|
return ""
|
|
end
|
|
|
|
if (text == "/reportstats") then
|
|
if (self:IsAdmin(ply)) then
|
|
self:BetterQuery("SELECT * FROM sh_reports_performance WHERE steamid = {steamid}", {steamid = ply:SteamID64()}, function(q, ok, data)
|
|
if (!ok or !IsValid(ply)) then
|
|
return end
|
|
|
|
local claimed = 0
|
|
local closed = 0
|
|
for _, d in pairs (data) do
|
|
claimed = claimed + tonumber(d.claimed)
|
|
closed = closed + tonumber(d.closed)
|
|
end
|
|
|
|
ply:ChatPrint("Reports claimed: " .. string.Comma(claimed) .. " | Reports closed: " .. string.Comma(closed))
|
|
end)
|
|
end
|
|
|
|
return ""
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:ShowReports(ply)
|
|
local tosend = {}
|
|
if (self:IsAdmin(ply)) then -- If admin, send all reports, if not only send own
|
|
tosend = self:GetAllReports()
|
|
else
|
|
tosend = self:GetAllReports(ply:SteamID64())
|
|
end
|
|
|
|
easynet.Send(ply, "SH_REPORTS.SendList", {
|
|
server_time = os.time(),
|
|
struct_reports = tosend,
|
|
})
|
|
end
|
|
|
|
local function SendPerfReports(ply, preps)
|
|
easynet.Send(ply, "SH_REPORTS.SendPerfReports", {
|
|
struct_perf_reports = preps
|
|
})
|
|
end
|
|
|
|
function SH_REPORTS:ShowPerformanceReports(ply)
|
|
if (!self.UsergroupsPerformance[ply:GetUserGroup()]) then
|
|
self:Notify(ply, "not_allowed_to_run_cmd", false)
|
|
return
|
|
end
|
|
|
|
if (self.CachedPerfReports) then
|
|
SendPerfReports(ply, self.CachedPerfReports)
|
|
else
|
|
self:BetterQuery("SELECT * FROM sh_reports_performance_reports", {time = os.time()}, function(q, ok, data)
|
|
if (!ok or !IsValid(ply)) then
|
|
return end
|
|
|
|
local d = {}
|
|
for k, v in pairs (data) do
|
|
d[tonumber(v.id)] = v
|
|
end
|
|
|
|
self.CachedPerfReports = d
|
|
if (IsValid(ply)) then
|
|
SendPerfReports(ply, d)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:RequestPerfReportStaff(ply, id)
|
|
if (!self.UsergroupsPerformance[ply:GetUserGroup()]) then
|
|
self:Notify(ply, "not_allowed_to_run_cmd", false)
|
|
return
|
|
end
|
|
|
|
self:BetterQuery("SELECT steamid, claimed, closed, timespent FROM sh_reports_performance WHERE report_id = {id}" /* 76561198398853149 */, {id = id}, function(q, ok, data)
|
|
if (!ok or !IsValid(ply)) then
|
|
return end
|
|
|
|
for k, v in pairs (data) do
|
|
v.claimed = tonumber(v.claimed) or 0
|
|
v.closed = tonumber(v.closed) or 0
|
|
v.timespent = tonumber(v.timespent) or 0
|
|
end
|
|
|
|
easynet.Send(ply, "SH_REPORTS.SendPerfReportStaff", {
|
|
id = id,
|
|
struct_perf_reports_staff = data
|
|
})
|
|
end)
|
|
end
|
|
|
|
function SH_REPORTS:RequestStaffRatings(ply)
|
|
if (!self.UsergroupsPerformance[ply:GetUserGroup()]) then
|
|
self:Notify(ply, "not_allowed_to_run_cmd", false)
|
|
return
|
|
end
|
|
|
|
self:BetterQuery("SELECT steamid, num, total FROM sh_reports_performance_ratings" /* 76561198398853124 */, {}, function(q, ok, data)
|
|
if (!ok or !IsValid(ply)) then
|
|
return end
|
|
|
|
easynet.Send(ply, "SH_REPORTS.SendRatings", {
|
|
struct_rating = data
|
|
})
|
|
end)
|
|
end
|
|
|
|
function SH_REPORTS:RequestReportHistory(ply)
|
|
if (!self.UsergroupsPerformance[ply:GetUserGroup()]) then
|
|
self:Notify(ply, "not_allowed_to_run_cmd", false)
|
|
return
|
|
end
|
|
|
|
self:BetterQuery("SELECT * FROM sh_reports_performance_history", {}, function(q, ok, data)
|
|
if (!ok or !IsValid(ply)) then
|
|
return end
|
|
|
|
-- Factorize the SteamID's to save on bytes
|
|
local t_steamids = {}
|
|
|
|
local t = {}
|
|
for _, dat in pairs (data) do
|
|
t[tonumber(dat.id)] = dat
|
|
|
|
t_steamids[dat.reporter] = true
|
|
t_steamids[dat.reported] = true
|
|
t_steamids[dat.admin] = true
|
|
end
|
|
|
|
local steamids = {}
|
|
for steamid in pairs (t_steamids) do
|
|
t_steamids[steamid] = table.insert(steamids, {steamid = steamid})
|
|
end
|
|
|
|
local t_list = {}
|
|
for id, dat in pairs (t) do
|
|
table.insert(t_list, {
|
|
report_id = tonumber(dat.id),
|
|
reporter_nid = t_steamids[dat.reporter],
|
|
reported_nid = t_steamids[dat.reported],
|
|
reason = dat.reason,
|
|
comment = dat.comment,
|
|
rating = dat.rating,
|
|
date = dat.date,
|
|
waiting_time = dat.waiting_time,
|
|
admin_nid = t_steamids[dat.admin],
|
|
})
|
|
end
|
|
|
|
easynet.Send(ply, "SH_REPORTS.SendHistoryList", {
|
|
struct_history_steamids = steamids,
|
|
struct_history_list = t_list,
|
|
})
|
|
end)
|
|
end
|
|
|
|
function SH_REPORTS:ClaimReport(admin, report)
|
|
local sid = admin:SteamID64()
|
|
for _, rep in pairs (self:GetAllReports()) do
|
|
if (rep.admin_id == sid) then
|
|
self:Notify(admin, "claimed_report_still_active", false)
|
|
return false
|
|
end
|
|
end
|
|
|
|
if (report.admin_id ~= "") then
|
|
return false
|
|
end
|
|
|
|
report.claim_time = os.time()
|
|
report.admin_id = sid
|
|
self:Notify(player.GetBySteamID64(report.reporter_id), "admin_claimed_your_report", true)
|
|
|
|
easynet.Send(admin, "SH_REPORTS.MinimizeReport", {report_id = report.id})
|
|
easynet.Send(self:GetStaff(), "SH_REPORTS.ReportClaimed", {report_id = report.id, admin_id = report.admin_id})
|
|
|
|
if (self.CurrentPerfReport) and (!report.is_admin or self.AdminReportsCount) then
|
|
self:BetterQuery([[
|
|
]] .. self.InsertSQL .. [[ sh_reports_performance (steamid, report_id)
|
|
VALUES ({steamid}, {report_id});
|
|
UPDATE sh_reports_performance SET claimed = claimed + 1
|
|
WHERE steamid = {steamid} AND report_id = {report_id}
|
|
]], {steamid = admin:SteamID64(), report_id = self.CurrentPerfReport.id})
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function SH_REPORTS:ClaimAndTeleport(admin, id, bring, bring_reported)
|
|
if (!self:IsAdmin(admin)) then
|
|
self:Notify(admin, "not_allowed_to_run_cmd", false)
|
|
return
|
|
end
|
|
|
|
local report = self:FindReport(id)
|
|
if (!report) then
|
|
self:Notify(admin, "report_non_existent", false)
|
|
return
|
|
end
|
|
|
|
if (self.ClaimNoTeleport) then
|
|
return end
|
|
|
|
local target = player.GetBySteamID64(report.reporter_id)
|
|
if (!IsValid(target)) then
|
|
return end
|
|
|
|
if (!self:ClaimReport(admin, report)) then
|
|
return end
|
|
|
|
admin.SH_PosBeforeReport = admin:GetPos()
|
|
target.SH_PosBeforeReport = target:GetPos()
|
|
|
|
if (self.UseULXCommands) then
|
|
-- Bad idea? ULX sucks anyways
|
|
if (bring) then
|
|
ulx.bring(admin, {target})
|
|
else
|
|
ulx.goto(admin, target)
|
|
end
|
|
|
|
if (bring_reported) then
|
|
local reported = player.GetBySteamID64(report.reported_id)
|
|
if (IsValid(reported)) then
|
|
reported.SH_PosBeforeReport = reported:GetPos()
|
|
|
|
if (bring) then
|
|
ulx.bring(admin, {reported})
|
|
else
|
|
ulx.send(admin, reported, target)
|
|
end
|
|
end
|
|
end
|
|
else
|
|
local a, b = admin, target
|
|
if (bring) then
|
|
a, b = target, admin
|
|
end
|
|
|
|
self:TeleportPlayer(a, b:GetPos())
|
|
|
|
if (bring_reported) then
|
|
local reported = player.GetBySteamID64(report.reported_id)
|
|
if (IsValid(reported)) then
|
|
reported.SH_PosBeforeReport = reported:GetPos()
|
|
|
|
self:TeleportPlayer(reported, b:GetPos())
|
|
end
|
|
end
|
|
end
|
|
|
|
self:Log(admin:Nick() .. " <" .. admin:SteamID() .. "> claimed " .. target:Nick() .. "'s <" .. target:SteamID() .. "> report [#" .. id .. "]")
|
|
end
|
|
|
|
function SH_REPORTS:ClaimAndCSit(admin, id)
|
|
if (!csitsystem) then
|
|
return end
|
|
|
|
if (!self:IsAdmin(admin)) then
|
|
self:Notify(admin, "not_allowed_to_run_cmd", false)
|
|
return
|
|
end
|
|
|
|
local report = self:FindReport(id)
|
|
if (!report) then
|
|
self:Notify(admin, "report_non_existent", false)
|
|
return
|
|
end
|
|
|
|
local target = player.GetBySteamID64(report.reporter_id)
|
|
if (!IsValid(target)) then
|
|
return end
|
|
|
|
if (!self:ClaimReport(admin, report)) then
|
|
return end
|
|
|
|
admin.SH_PosBeforeReport = admin:GetPos()
|
|
target.SH_PosBeforeReport = target:GetPos()
|
|
|
|
report.sit_id = csitsystem.HandOver(admin, target, player.GetBySteamID64(report.reported_id))
|
|
|
|
self:Log(admin:Nick() .. " <" .. admin:SteamID() .. "> claimed " .. target:Nick() .. "'s <" .. target:SteamID() .. "> report [#" .. id .. "] and started a sit")
|
|
-- self:CloseReport(admin, id)
|
|
end
|
|
|
|
function SH_REPORTS:CloseReport(ply, id)
|
|
local report = self:FindReport(id)
|
|
if (!report) then
|
|
self:Notify(ply, "report_non_existent", false)
|
|
return
|
|
end
|
|
|
|
local sid = ply:SteamID64()
|
|
if (self:IsAdmin(ply) and ((report.admin_id == "" and self.CanDeleteWhenUnclaimed) or report.admin_id == sid)) or (report.reporter_id == sid) then
|
|
self.ActiveReports[id] = nil
|
|
|
|
self:Notify(ply, "report_closed", true)
|
|
easynet.Send(self:GetStaff(), "SH_REPORTS.ReportClosed", {report_id = id})
|
|
|
|
local target = player.GetBySteamID64(report.reporter_id)
|
|
local admin = player.GetBySteamID64(report.admin_id)
|
|
if (IsValid(target)) then
|
|
if (report.reporter_id ~= sid) then
|
|
self:Notify(target, "your_report_was_closed", true)
|
|
elseif (report.admin_id ~= "") then
|
|
if (IsValid(admin) and admin ~= ply) then
|
|
self:Notify(admin, "reporter_closed_report", true)
|
|
end
|
|
end
|
|
|
|
easynet.Send(target, "SH_REPORTS.ReportClosed", {report_id = id})
|
|
end
|
|
|
|
if (!report.is_admin or self.AdminReportsCount) then
|
|
if (report.admin_id ~= "") then
|
|
local claim_time = os.time() - report.claim_time
|
|
|
|
if (self.CurrentPerfReport) then
|
|
self:BetterQuery([[
|
|
]] .. self.InsertSQL .. [[ sh_reports_performance (steamid, report_id, timespent)
|
|
VALUES ({steamid}, {report_id}, {timespent});
|
|
UPDATE sh_reports_performance SET closed = closed + 1, timespent = timespent + {timespent}
|
|
WHERE steamid = {steamid} AND report_id = {report_id}
|
|
]], {steamid = report.admin_id, report_id = self.CurrentPerfReport.id, timespent = claim_time})
|
|
end
|
|
|
|
if (sid == report.reporter_id) then
|
|
self:Log(ply:Nick() .. " <" .. ply:SteamID() .. "> closed their own report [#" .. id .. "]")
|
|
else
|
|
if (IsValid(target) and self.AskRating) then
|
|
if (!target.SH_ReportsCompleted) then
|
|
target.SH_ReportsCompleted = {}
|
|
end
|
|
target.SH_ReportsCompleted[id] = ply:SteamID64()
|
|
|
|
easynet.Send(target, "SH_REPORTS.PromptRating", {report_id = id, admin_name = ply:Nick()})
|
|
end
|
|
|
|
self:Log(ply:Nick() .. " <" .. ply:SteamID() .. "> closed the report [#" .. id .. "] from " .. report.reporter_name .. "<" .. util.SteamIDFrom64(report.reporter_id) .. ">")
|
|
end
|
|
elseif (self:IsAdmin(ply)) then
|
|
if (self.CurrentPerfReport) then
|
|
self:BetterQuery([[
|
|
]] .. self.InsertSQL .. [[ sh_reports_performance (steamid, report_id)
|
|
VALUES ({steamid}, {report_id});
|
|
UPDATE sh_reports_performance SET closed = closed + 1
|
|
WHERE steamid = {steamid} AND report_id = {report_id}
|
|
]], {steamid = sid, report_id = self.CurrentPerfReport.id})
|
|
end
|
|
|
|
if (sid == report.reporter_id) then
|
|
self:Log(ply:Nick() .. " <" .. ply:SteamID() .. "> closed their own UNCLAIMED report [#" .. id .. "]")
|
|
else
|
|
self:Log(ply:Nick() .. " <" .. ply:SteamID() .. "> closed the UNCLAIMED report [#" .. id .. "] from " .. report.reporter_name .. "<" .. util.SteamIDFrom64(report.reporter_id) .. ">")
|
|
end
|
|
end
|
|
end
|
|
|
|
if (report.admin_id ~= "") then
|
|
if (report.sit_id) then
|
|
csitsystem.EndSit(report.sit_id)
|
|
end
|
|
|
|
if (self.TeleportPlayersBack) then
|
|
if (IsValid(target)) then
|
|
self:ReturnPlayer(target)
|
|
end
|
|
|
|
local admin = player.GetBySteamID64(report.admin_id)
|
|
if (IsValid(admin)) then
|
|
self:ReturnPlayer(admin)
|
|
end
|
|
|
|
local reported = player.GetBySteamID64(report.reported_id)
|
|
if (IsValid(reported)) then
|
|
self:ReturnPlayer(reported)
|
|
end
|
|
end
|
|
|
|
if (self.StoreCompletedReports ~= "none") then
|
|
self:BetterQuery([[
|
|
]] .. self.InsertSQL .. [[ sh_reports_performance_history (id, reporter, reported, reason, comment, waiting_time, date, admin)
|
|
VALUES ({id}, {reporter}, {reported}, {reason}, {comment}, {waiting_time}, {date}, {admin});
|
|
]], {id = id, reporter = report.reporter_id, reported = report.reported_id, reason = self.ReportReasons[report.reason_id], comment = report.comment, waiting_time = os.time() - report.time, date = os.time(), admin = report.admin_id})
|
|
end
|
|
end
|
|
else
|
|
self:Notify(ply, "not_allowed_to_run_cmd", false)
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:RateAdmin(ply, report_id, rating)
|
|
if (!ply.SH_ReportsCompleted or !ply.SH_ReportsCompleted[report_id]) then
|
|
self:Notify(ply, "report_non_existent", false)
|
|
return
|
|
end
|
|
|
|
local admin_id = ply.SH_ReportsCompleted[report_id]
|
|
rating = math.Clamp(rating, 1, 5)
|
|
|
|
self:BetterQuery([[
|
|
]] .. self.InsertSQL .. [[ sh_reports_performance_ratings (steamid, total, num)
|
|
VALUES ({steamid}, 0, 0);
|
|
UPDATE sh_reports_performance_ratings SET total = total + {rating}, num = num + 1
|
|
WHERE steamid = {steamid}
|
|
]], {steamid = admin_id, rating = rating})
|
|
|
|
if (self.StoreCompletedReports ~= "none") then
|
|
self:BetterQuery([[
|
|
UPDATE sh_reports_performance_history SET rating = {rating}
|
|
WHERE id = {id}
|
|
]], {id = report_id, rating = rating})
|
|
end
|
|
|
|
if (self.NotifyRating) then
|
|
local admin = player.GetBySteamID64(admin_id)
|
|
if (IsValid(admin)) then
|
|
local rstr = ""
|
|
for i = 1, 5 do
|
|
rstr = rstr .. (rating >= i and "★" or "☆")
|
|
end
|
|
|
|
self:Notify(admin, "rate_notification\t" .. ply:Nick() .. "\t" .. rstr, rating >= 3)
|
|
end
|
|
end
|
|
|
|
ply.SH_ReportsCompleted[report_id] = nil
|
|
self:Notify(ply, "rate_thanks", true)
|
|
end
|
|
|
|
function SH_REPORTS:PlayerReady(ply)
|
|
if (self.NotifyAdminsOnConnect and self:IsAdmin(ply)) then
|
|
local num = 0
|
|
local pending = {}
|
|
for id, report in pairs (self:GetAllReports()) do
|
|
if (report.admin_id == "") then
|
|
num = num + 1
|
|
table.insert(pending, report)
|
|
end
|
|
end
|
|
|
|
if (num > 0) then
|
|
easynet.Send(ply, "SH_REPORTS.ReportsPending", {num = num, struct_reports = pending})
|
|
end
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:PlayerDisconnected(ply)
|
|
local sid = ply:SteamID64()
|
|
for id, report in pairs (self:GetAllReports()) do
|
|
if (report.reporter_id == sid) then
|
|
self.ActiveReports[id] = nil
|
|
easynet.Send(self:GetStaff(), "SH_REPORTS.ReportClosed", {report_id = id})
|
|
|
|
local admin = player.GetBySteamID64(report.admin_id)
|
|
if (IsValid(admin)) then
|
|
self:Notify(admin, "reporter_closed_report", false)
|
|
end
|
|
elseif (self:IsAdmin(ply) and report.admin_id == sid) then
|
|
report.admin_id = ""
|
|
easynet.Send(self:GetStaff(), "SH_REPORTS.AdminLeft", {report_id = id})
|
|
|
|
local reporter = player.GetBySteamID64(report.reporter_id)
|
|
if (IsValid(reporter)) then
|
|
easynet.Send(reporter, "SH_REPORTS.AdminLeft", {report_id = id})
|
|
self:Notify(reporter, "admin_has_disconnected", false)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:ReturnPlayer(ply)
|
|
if (!ply.SH_PosBeforeReport) then
|
|
return end
|
|
|
|
ply:SetPos(ply.SH_PosBeforeReport)
|
|
ply.SH_PosBeforeReport = nil
|
|
end
|
|
|
|
function SH_REPORTS:MidnightCheck()
|
|
local perf = self.CurrentPerfReport
|
|
if (!perf) then
|
|
return end
|
|
|
|
if (os.time() >= perf.end_time) then
|
|
self:DBPrint("Current performance report #" .. perf.id .. " expired, creating new one..")
|
|
self:CreatePerformanceReport()
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:Notify(ply, msg, good)
|
|
easynet.Send(ply, "SH_REPORTS.Notify", {msg = msg, positive = good})
|
|
end
|
|
|
|
function SH_REPORTS:GetStaff(ply)
|
|
local t = {}
|
|
for _, v in ipairs (player.GetAll()) do
|
|
if (self:IsAdmin(v)) then
|
|
table.insert(t, v)
|
|
end
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
local function CheckObstruction(ply, pos)
|
|
local t = {
|
|
start = pos,
|
|
endpos = pos + Vector(0, 0, 72),
|
|
mins = Vector(-16, -16, 0),
|
|
maxs = Vector(16, 16, 4),
|
|
filter = ply
|
|
}
|
|
|
|
return bit.band(util.PointContents(pos), CONTENTS_SOLID) > 0 or util.TraceHull(t).Hit
|
|
end
|
|
|
|
local coords = {
|
|
Vector(48, 0, 0),
|
|
Vector(-48, 0, 0),
|
|
Vector(0, 48, 0),
|
|
Vector(0, -48, 0),
|
|
Vector(48, 48, 0),
|
|
Vector(-48, 48, 0),
|
|
Vector(48, -48, 0),
|
|
Vector(-48, -48, 0),
|
|
}
|
|
|
|
function SH_REPORTS:TeleportPlayer(ply, pos, exact)
|
|
if (!exact) then
|
|
if (CheckObstruction(ply, pos)) then
|
|
for _, c in ipairs (coords) do
|
|
if (!util.TraceLine({start = pos, endpos = pos + c, filter = ents.GetAll()}).Hit and !CheckObstruction(ply, pos + c /* 76561198398853124 */)) then
|
|
pos = pos + c
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
ply.SH_PositionBeforeTeleport = ply:GetPos()
|
|
ply:SetPos(pos)
|
|
end
|
|
|
|
function SH_REPORTS:FindReport(id)
|
|
return self.ActiveReports[id]
|
|
end
|
|
|
|
function SH_REPORTS:GetAllReports(author)
|
|
local t = {}
|
|
for id, report in pairs (self.ActiveReports) do
|
|
if (author and report.reporter_id ~= author) then
|
|
continue end
|
|
|
|
t[id] = report
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
function SH_REPORTS:Log(s)
|
|
if (!self.UseServerLog) then
|
|
return end
|
|
|
|
ServerLog(s .. "\n")
|
|
end
|
|
|
|
local function GetPerformanceReport(date, preps)
|
|
for id, ps in pairs (preps) do
|
|
if (date >= ps[1] and date <= ps[2]) then
|
|
return id
|
|
end
|
|
end
|
|
end
|
|
|
|
function SH_REPORTS:RebuildPerformance()
|
|
local preps = {}
|
|
self:BetterQuery("SELECT * FROM sh_reports_performance_reports", {}, function(q, ok, data)
|
|
for k, v in pairs (data) do
|
|
preps[tonumber(v.id)] = {tonumber(v.start_time), tonumber(v.end_time)}
|
|
end
|
|
|
|
self:BetterQuery("SELECT * FROM sh_reports_performance_history", {}, function(q, ok, data)
|
|
local staffreps = {}
|
|
for _, rep in SortedPairsByMemberValue (data, "date") do
|
|
local admin = tostring(rep.admin)
|
|
staffreps[admin] = staffreps[admin] or {}
|
|
|
|
table.insert(staffreps[admin], rep)
|
|
end
|
|
|
|
local staffpreps = {}
|
|
for sid, reps in pairs (staffreps) do
|
|
staffpreps[sid] = {}
|
|
|
|
for _, rep in pairs (reps) do
|
|
local prepid = GetPerformanceReport(tonumber(rep.date), preps)
|
|
staffpreps[sid][prepid] = staffpreps[sid][prepid] or {}
|
|
table.insert(staffpreps[sid][prepid], rep)
|
|
end
|
|
end
|
|
|
|
for sid, preps in pairs (staffpreps) do
|
|
for prepid, reps in pairs (preps) do
|
|
local claimed, closed, timespent = 0, 0, 0
|
|
for _, rep in pairs (reps) do
|
|
claimed = claimed + 1
|
|
closed = closed + 1
|
|
timespent = timespent + tonumber(rep.waiting_time)
|
|
end
|
|
|
|
self:BetterQuery("SELECT * FROM sh_reports_performance WHERE steamid = {steamid} AND report_id = {prepid}", {steamid = sid, prepid = prepid}, function(q, ok, data)
|
|
if (data and data[1]) then
|
|
self:BetterQuery("UPDATE sh_reports_performance SET claimed = {claimed}, closed = {closed}, timespent = {timespent} WHERE steamid = {steamid} AND report_id = {prepid}", {claimed = claimed, closed = closed, timespent = timespent, steamid = sid, prepid = prepid})
|
|
else
|
|
self:BetterQuery("INSERT INTO sh_reports_performance (steamid, claimed, closed, timespent, report_id) VALUES ({steamid}, {claimed}, {closed}, {timespent}, {prepid})", {claimed = claimed, closed = closed, timespent = timespent, steamid = sid, prepid = prepid})
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
end)
|
|
end)
|
|
end
|
|
|
|
hook.Add("PlayerDisconnected", "SH_REPORTS.PlayerDisconnected", function(ply)
|
|
SH_REPORTS:PlayerDisconnected(ply)
|
|
end)
|
|
|
|
hook.Add("PlayerSay", "SH_REPORTS.PlayerSay", function(ply, str)
|
|
local r = SH_REPORTS:PlayerSay(ply, str)
|
|
if (r) then
|
|
return r
|
|
end
|
|
end)
|
|
|
|
hook.Add("DoPlayerDeath", "SH_REPORTS.DoPlayerDeath", function(ply, atk, dmginfo)
|
|
if (IsValid(atk) and atk:IsPlayer() and atk ~= ply) then
|
|
ply.SH_LastKiller = atk
|
|
end
|
|
end)
|
|
|
|
hook.Add("playerArrested", "SH_REPORTS.playerArrested", function(ply, time, arrester)
|
|
if (IsValid(arrester) and arrester:IsPlayer() and arrester ~= ply) then
|
|
ply.SH_LastArrester = arrester
|
|
end
|
|
end)
|
|
|
|
hook.Add("PlayerButtonDown", "SH_REPORTS.PlayerButtonDown", function(ply, btn)
|
|
if (!IsFirstTimePredicted()) then
|
|
return end
|
|
|
|
if (btn == SH_REPORTS.ReportKey) then
|
|
if (!SH_REPORTS:IsAdmin(ply) or SH_REPORTS.StaffCanReport) then
|
|
easynet.Send(ply, "SH_REPORTS.QuickReport", {comment = "", lastkiller = ply.SH_LastKiller, lastarrester = ply.SH_LastArrester})
|
|
else
|
|
SH_REPORTS:Notify(ply, "cannot_report_as_admin", false)
|
|
end
|
|
elseif (btn == SH_REPORTS.ReportsKey) then
|
|
SH_REPORTS:ShowReports(ply)
|
|
end
|
|
end)
|
|
|
|
timer.Create("SH_REPORTS.MidnightCheck", 1, 0, function()
|
|
SH_REPORTS:MidnightCheck()
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.NewReport", function(data, ply)
|
|
local report = data
|
|
data.reporter_name = ply:Nick()
|
|
data.reporter_id = ply:SteamID64()
|
|
data.time = os.time()
|
|
data.admin_id = ""
|
|
data.comment = data.comment:sub(1, SH_REPORTS.MaxCommentLength)
|
|
data.is_admin = SH_REPORTS:IsAdmin(ply)
|
|
|
|
SH_REPORTS:NewReport(ply, data)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.Claim", function(data, ply)
|
|
if (!SH_REPORTS:IsAdmin(ply)) then
|
|
SH_REPORTS:Notify(ply, "not_allowed_to_run_cmd", false)
|
|
return
|
|
end
|
|
|
|
local report = SH_REPORTS:FindReport(data.id)
|
|
if (!report) then
|
|
SH_REPORTS:Notify(ply, "report_non_existent", false)
|
|
return
|
|
end
|
|
|
|
SH_REPORTS:ClaimReport(ply, report)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.ClaimAndTeleport", function(data, ply)
|
|
SH_REPORTS:ClaimAndTeleport(ply, data.id, data.bring, data.bring_reported)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.ClaimAndCSit", function(data, ply)
|
|
SH_REPORTS:ClaimAndCSit(ply, data.id)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.CloseReport", function(data, ply)
|
|
SH_REPORTS:CloseReport(ply, data.id)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.RequestPerfReports", function(data, ply)
|
|
SH_REPORTS:ShowPerformanceReports(ply)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.RequestPerfReportStaff", function(data, ply)
|
|
SH_REPORTS:RequestPerfReportStaff(ply, data.id)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.PlayerReady", function(data, ply)
|
|
SH_REPORTS:PlayerReady(ply)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.RateAdmin", function(data, ply)
|
|
SH_REPORTS:RateAdmin(ply, data.report_id, data.rating)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.RequestStaffRatings", function(data, ply)
|
|
SH_REPORTS:RequestStaffRatings(ply)
|
|
end)
|
|
|
|
easynet.Callback("SH_REPORTS.RequestReportHistory", function(data, ply)
|
|
SH_REPORTS:RequestReportHistory(ply)
|
|
end)
|
|
|
|
-- vk.com/urbanichka
|