mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
174
addons/vyhub-gmod/lua/autorun/vyhub_load.lua
Normal file
174
addons/vyhub-gmod/lua/autorun/vyhub_load.lua
Normal file
@@ -0,0 +1,174 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local f = string.format
|
||||
|
||||
VyHub = VyHub or {}
|
||||
VyHub.Config = VyHub.Config or {}
|
||||
VyHub.Lib = VyHub.Lib or {}
|
||||
VyHub.ready = false
|
||||
|
||||
local vyhub_root = "vyhub"
|
||||
|
||||
local color_warn = Color(211, 120, 0)
|
||||
local color_err = Color(255, 0, 0)
|
||||
local color_green = Color(0, 255, 0)
|
||||
|
||||
function VyHub:msg(message, type)
|
||||
type = type or "neutral"
|
||||
|
||||
// Remove color tags
|
||||
message = string.gsub(message, "<([%l]+)>([^<]+)</%1>", "%2")
|
||||
|
||||
if type == "success" then
|
||||
MsgC("[VyHub] ", color_green, message .. "\n")
|
||||
elseif type == "error" then
|
||||
MsgC("[VyHub] [ERROR] ", color_err, message .. "\n")
|
||||
elseif type == "neutral" then
|
||||
MsgC("[VyHub] ", color_white, message .. "\n")
|
||||
elseif type == "warning" then
|
||||
MsgC("[VyHub] [WARN] ", color_warn, message .. "\n")
|
||||
elseif type == "debug" and VyHub.Config.debug then
|
||||
MsgC("[VyHub] [Debug] ", color_white, message .. "\n")
|
||||
end
|
||||
end
|
||||
|
||||
VyHub:msg("Initializing...")
|
||||
|
||||
if SERVER then
|
||||
addon_incomplete = false
|
||||
|
||||
if file.Exists( vyhub_root .. '/lang/en.json', "LUA") then
|
||||
if file.Exists( vyhub_root .. '/config/sv_config.lua', "LUA") then
|
||||
hook.Run("vyhub_loading_start")
|
||||
|
||||
-- libs
|
||||
VyHub:msg("Loading lib files...")
|
||||
local files = file.Find( vyhub_root .."/lib/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
AddCSLuaFile( vyhub_root .. "/lib/" .. file )
|
||||
include( vyhub_root .. "/lib/" .. file )
|
||||
end
|
||||
|
||||
-- Shared Config
|
||||
include( vyhub_root .. '/config/sh_config.lua' )
|
||||
AddCSLuaFile( vyhub_root .. "/config/sh_config.lua" )
|
||||
|
||||
-- Language
|
||||
VyHub:msg('Loading ' .. VyHub.Config.lang .. ' language...')
|
||||
include( vyhub_root .. '/shared/sh_lang.lua' )
|
||||
|
||||
-- Config Files
|
||||
VyHub:msg("Loading config files...")
|
||||
include( vyhub_root .. '/config/sv_config.lua' )
|
||||
|
||||
-- Shared Files
|
||||
VyHub:msg("Loading shared files...")
|
||||
local files = file.Find( vyhub_root .."/shared/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
AddCSLuaFile( vyhub_root .. "/shared/" .. file )
|
||||
include( vyhub_root .. "/shared/" .. file )
|
||||
end
|
||||
|
||||
-- Client Files
|
||||
VyHub:msg("Loading client files...")
|
||||
local files = file.Find( vyhub_root .."/client/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
AddCSLuaFile( vyhub_root .."/client/" .. file )
|
||||
end
|
||||
|
||||
-- Server Files
|
||||
VyHub:msg("Loading server files...")
|
||||
local files = file.Find( vyhub_root .. "/server/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
include( vyhub_root .. "/server/" .. file )
|
||||
end
|
||||
|
||||
game.ConsoleCommand("sv_hibernate_think 1\n")
|
||||
|
||||
file.CreateDir("vyhub")
|
||||
|
||||
VyHub.Config:load_cache_config()
|
||||
|
||||
timer.Simple(2, function()
|
||||
hook.Run("vyhub_loading_finish")
|
||||
end)
|
||||
|
||||
VyHub:msg("Finished loading!")
|
||||
else
|
||||
VyHub:msg("Could not find lua/vyhub/config/sv_config.lua. Please make sure it exists.", "error")
|
||||
end
|
||||
else
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("Could not find language files!!! Please make sure to download a correct vyhub-gmod release here: https://github.com/matbyte-com/vyhub-gmod/releases", "error")
|
||||
VyHub:msg("Cannot proceed with initialization.", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if CLIENT then
|
||||
if file.Exists( vyhub_root .. '/shared/sh_lang.lua', "LUA") then
|
||||
hook.Run("vyhub_loading_start")
|
||||
|
||||
-- libs
|
||||
VyHub:msg("Loading lib files...")
|
||||
local files = file.Find( vyhub_root .."/lib/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
include( vyhub_root .. "/lib/" .. file )
|
||||
end
|
||||
|
||||
-- Language
|
||||
VyHub:msg('Loading language...')
|
||||
include( vyhub_root .. '/shared/sh_lang.lua' )
|
||||
|
||||
-- Config Files
|
||||
VyHub:msg("Loading config files...")
|
||||
local files = file.Find( vyhub_root .."/config/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
if not string.StartWith(file, 'sv_') then
|
||||
include( vyhub_root .. "/config/" .. file )
|
||||
end
|
||||
end
|
||||
|
||||
-- Shared Files
|
||||
VyHub:msg("Loading shared files...")
|
||||
local files = file.Find( vyhub_root .."/shared/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
include( vyhub_root .. "/shared/" .. file )
|
||||
end
|
||||
|
||||
-- Client Files
|
||||
VyHub:msg("Loading client files...")
|
||||
local files = file.Find( vyhub_root .."/client/*.lua", "LUA" )
|
||||
for _, file in ipairs( files ) do
|
||||
include( vyhub_root .."/client/" .. file )
|
||||
end
|
||||
|
||||
timer.Simple(2, function()
|
||||
hook.Run("vyhub_loading_finish")
|
||||
end)
|
||||
|
||||
VyHub:msg("Finished loading!")
|
||||
else
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("VyHub not correctly loaded. Please check the server log.", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
VyHub:msg("!!!", "error")
|
||||
end
|
||||
end
|
||||
34
addons/vyhub-gmod/lua/vyhub/client/cl_chattag.lua
Normal file
34
addons/vyhub-gmod/lua/vyhub/client/cl_chattag.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
local color_red = Color(255, 0, 0)
|
||||
|
||||
if VyHub.Config.chat_tags and not DarkRP then
|
||||
hook.Add("OnPlayerChat", "vyhub_chattag_OnPlayerChat", function(ply, msg)
|
||||
if IsValid(ply) then
|
||||
local group = VyHub.Group:get(ply:GetUserGroup())
|
||||
|
||||
if group then
|
||||
local teamcolor = team.GetColor(ply:Team())
|
||||
local deadTag = ""
|
||||
|
||||
if not ply:Alive() then
|
||||
deadTag = f("*%s* ", VyHub.lang.other.dead)
|
||||
end
|
||||
|
||||
chat.AddText(VyHub.Util:hex2rgb(group.color), "[", group.name, "]", " ", color_red, deadTag, teamcolor, ply:Nick(), color_white, ": ", msg)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
532
addons/vyhub-gmod/lua/vyhub/client/cl_dashboard.lua
Normal file
532
addons/vyhub-gmod/lua/vyhub/client/cl_dashboard.lua
Normal file
@@ -0,0 +1,532 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
VyHub.Dashboard = VyHub.Dashboard or {}
|
||||
|
||||
VyHub.Dashboard.ui = VyHub.Dashboard.ui or nil
|
||||
|
||||
VyHub.Dashboard.html_ready = false
|
||||
VyHub.Dashboard.html_generated = VyHub.Dashboard.html_generated or false
|
||||
|
||||
local dashboard_html = dashboard_html or "Loading, please try again. If this does not help, please ask the server owner to check for errors in the server console. In most cases, vyhub-gmod has not been downloaded correctly and is missing files."
|
||||
|
||||
function VyHub.Dashboard:create_ui()
|
||||
VyHub.Dashboard.html_ready = false
|
||||
|
||||
local xsize = ScrW() - ScrW()/4
|
||||
local ysize = ScrH() - ScrH()/4
|
||||
local xpos = ScrW()/2 - xsize/2
|
||||
local ypos = ScrH()/2 - ysize/2
|
||||
local title = "VyHub Server-Dashboard"
|
||||
local box_color = Color(94, 0, 0, 255)
|
||||
|
||||
VyHub.Dashboard.ui = vgui.Create("DFrame")
|
||||
VyHub.Dashboard.ui:SetSize(xsize, ysize)
|
||||
VyHub.Dashboard.ui:SetPos(xpos, ypos)
|
||||
VyHub.Dashboard.ui:SetDraggable(true)
|
||||
VyHub.Dashboard.ui:SetTitle(title)
|
||||
VyHub.Dashboard.ui:SetDeleteOnClose(false)
|
||||
function VyHub.Dashboard.ui.Paint(self, w, h)
|
||||
surface.SetDrawColor(box_color)
|
||||
surface.DrawRect(0, 0, w, 24)
|
||||
end
|
||||
|
||||
VyHub.Dashboard.ui_html = vgui.Create("DHTML", VyHub.Dashboard.ui)
|
||||
VyHub.Dashboard.ui_html:SetSize(xsize, ysize - 24)
|
||||
VyHub.Dashboard.ui_html:SetPos(0, 24)
|
||||
VyHub.Dashboard.ui_html:SetHTML(dashboard_html)
|
||||
|
||||
function VyHub.Dashboard.ui_html:OnDocumentReady()
|
||||
MsgN("VyHub Dashboard: HTML Loaded")
|
||||
VyHub.Dashboard.html_ready = true
|
||||
VyHub.Dashboard.ui_html:RunJavascript('local_steamid64 = ' .. LocalPlayer():SteamID64())
|
||||
end
|
||||
|
||||
VyHub.Dashboard.ui_html:AddFunction("vyhub", "warning_toggle", function (warning_id)
|
||||
LocalPlayer():ConCommand(f("vh_warning_toggle %s", warning_id))
|
||||
end)
|
||||
VyHub.Dashboard.ui_html:AddFunction("vyhub", "warning_delete", function (warning_id)
|
||||
LocalPlayer():ConCommand(f("vh_warning_delete %s", warning_id))
|
||||
end)
|
||||
VyHub.Dashboard.ui_html:AddFunction("vyhub", "ban_set_status", function (ban_id, status)
|
||||
LocalPlayer():ConCommand(f("vh_ban_set_status %s %s", ban_id, status))
|
||||
end)
|
||||
VyHub.Dashboard.ui_html:AddFunction("vyhub", "warning_create", function (steamid, reason)
|
||||
LocalPlayer():ConCommand(f('vh_warn %s "%s"', steamid, VyHub.Util:escape_concommand_str(reason)))
|
||||
end)
|
||||
VyHub.Dashboard.ui_html:AddFunction("vyhub", "ban_create", function (steamid, minutes, reason)
|
||||
LocalPlayer():ConCommand(f('vh_ban %s "%s" "%s"', steamid, minutes, VyHub.Util:escape_concommand_str(reason)))
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Dashboard:load_html()
|
||||
VyHub.Dashboard.html_generated = true
|
||||
dashboard_html = [[
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.vyhub.net/assets/roboto-v30-latin/roboto-v30-latin.css">
|
||||
<link rel="stylesheet" href="http://cdn.vyhub.net/assets/font-awesome-4.7.0/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="http://cdn.vyhub.net/assets/bootswatch-darkly.min.css">
|
||||
|
||||
<style>
|
||||
::selection {
|
||||
background: #b5b5b5; /* WebKit/Blink Browsers */
|
||||
}
|
||||
|
||||
body{
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
font-family: Roboto !important;
|
||||
}
|
||||
|
||||
.vh-input {
|
||||
background-color: #303030;
|
||||
color: white;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.nav-pills .active {
|
||||
background-color: #303030;
|
||||
font-weight: bold;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.user-tab {
|
||||
padding: 3px 6px 3px 6px;
|
||||
border-radius: 8px;
|
||||
text-overflow: ellipsis;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
#user_name {
|
||||
width: 50%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="row" style="margin: 10px">
|
||||
<div class="col-xs-4 col-lg-3">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fa fa-search"></i></div>
|
||||
<input style="height: 40px;" id="user_search" type="text" class="form-control vh-input" onclick="$('#user_search').val(''); generate_user_list();" onkeyup="generate_user_list()" >
|
||||
</div>
|
||||
<br/>
|
||||
<ul class="nav nav-pills nav-stacked" id="user_list">
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-8 col-lg-9">
|
||||
<div id="user_content_empty">
|
||||
]] .. VyHub.lang.dashboard.select_user .. [[
|
||||
</div>
|
||||
<div class="tab-content" id="user_content" style="display: none;">
|
||||
<h3 style="margin: 5px 0px 0px 0;">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<span id="user_name">
|
||||
<span class="label label-default" style="background-color: #5E0000; border-radius: .25em 0 0 .25em;">
|
||||
<i class="fa fa-user"></i> <span id="user_content_name"></span>
|
||||
</span>
|
||||
<span class="label label-default" style="border-radius: 0 .25em .25em 0;">
|
||||
<span id="user_content_username"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<span id="user_memberships" class="pull-right">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h4><span class="label label-default"><i class="fa fa-exclamation-triangle"></i> ]] .. VyHub.lang.other.warnings .. [[</span></h3>
|
||||
|
||||
<div class="row perm-warning_edit">
|
||||
<div class="col-xs-10">
|
||||
<input id="user_warn" type="text" class="form-control vh-input" onclick="$('#user_warn').val('');" placeholder="]] .. VyHub.lang.other.reason .. [[" />
|
||||
</div>
|
||||
<div class="col-xs-2" style="padding-left: 0;">
|
||||
<button style="height: 30px;" onclick="create_warning()" class="btn btn-warning btn-xs btn-block"><i class="fa fa-exclamation-triangle"></i> ]] .. VyHub.lang.dashboard.action_warn .. [[</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<table class="table table-condensed table-hover">
|
||||
<tr>
|
||||
<th width="10px"></th>
|
||||
<th>]] .. VyHub.lang.other.reason .. [[</th>
|
||||
<th>]] .. VyHub.lang.other.admin .. [[</th>
|
||||
<th>]] .. VyHub.lang.other.date .. [[</th>
|
||||
<th class="text-right">]] .. VyHub.lang.other.actions .. [[</th>
|
||||
</tr>
|
||||
|
||||
<tbody id="user_content_warnings">
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<span class="label label-success"><i class="fa fa-check"></i> ]] .. VyHub.lang.other.active .. [[</span>
|
||||
<span class="label label-warning"><i class="fa fa-hourglass"></i> ]] .. VyHub.lang.other.inactive .. [[</span>
|
||||
<span class="label label-default"><i class="fa fa-times"></i> ]] .. VyHub.lang.other.disabled .. [[</span>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<h4><span class="label label-default"><i class="fa fa-gavel"></i> ]] .. VyHub.lang.other.bans .. [[</span></h3>
|
||||
|
||||
<div class="row perm-ban_edit">
|
||||
<div class="col-xs-8">
|
||||
<input id="user_ban_reason" type="text" class="form-control vh-input" onclick="$('#user_ban_reason').val('');" placeholder="]] .. VyHub.lang.other.reason .. [[" />
|
||||
</div>
|
||||
<div class="col-xs-2" style="padding-left: 0;">
|
||||
<input id="user_ban_minutes" type="text" class="form-control vh-input" onclick="$('#user_ban_minutes').val('');" placeholder="]] .. VyHub.lang.other.minutes .. [[" />
|
||||
</div>
|
||||
<div class="col-xs-2" style="padding-left: 0;">
|
||||
<button style="height: 30px;" onclick="create_ban()" class="btn btn-danger btn-xs btn-block"><i class="fa fa-gavel"></i> ]] .. VyHub.lang.dashboard.action_ban .. [[</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<table class="table table-condensed table-hover">
|
||||
<tr>
|
||||
<th width="10px"></th>
|
||||
<th>]] .. VyHub.lang.other.reason .. [[</th>
|
||||
<th>]] .. VyHub.lang.other.admin .. [[</th>
|
||||
<th>]] .. VyHub.lang.other.date .. [[</th>
|
||||
<th>]] .. VyHub.lang.other.minutes .. [[</th>
|
||||
<th class="text-right">]] .. VyHub.lang.other.actions .. [[</th>
|
||||
</tr>
|
||||
|
||||
<tbody id="user_content_bans">
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<span class="label label-success"><i class="fa fa-check"></i> ]] .. VyHub.lang.other.active .. [[</span>
|
||||
<span class="label label-info"><i class="fa fa-globe"></i> ]] .. VyHub.lang.other.active_global .. [[</span>
|
||||
<span class="label label-warning"><i class="fa fa-times"></i> ]] .. VyHub.lang.other.unbanned .. [[</span>
|
||||
<span class="label label-danger"><i class="fa fa-hourglass"></i> ]] .. VyHub.lang.other.inactive .. [[</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.min.js"></script>
|
||||
<script>
|
||||
var perms = null;
|
||||
var users = [];
|
||||
var users_by_id = {};
|
||||
var current_user = null;
|
||||
var local_steamid64 = null;
|
||||
|
||||
function escape(str) {
|
||||
return $("<div>").text(str).html();
|
||||
}
|
||||
|
||||
function format_date(iso_str) {
|
||||
return moment(iso_str).format('YYYY-MM-DD HH:mm');
|
||||
}
|
||||
|
||||
function load_data(new_data) {
|
||||
users = new_data;
|
||||
users_by_id = {};
|
||||
|
||||
new_data.forEach(function(user) {
|
||||
users_by_id[user.id] = user;
|
||||
});
|
||||
|
||||
generate_user_list()
|
||||
}
|
||||
|
||||
function load_perms(new_perms) {
|
||||
perms = new_perms;
|
||||
}
|
||||
|
||||
function enforce_perms() {
|
||||
if (perms == null) { return; }
|
||||
|
||||
Object.keys(perms).forEach(function(perm) {
|
||||
var has_perm = perms[perm];
|
||||
|
||||
if (has_perm) {
|
||||
$('.perm-' + perm).show();
|
||||
} else {
|
||||
$('.perm-' + perm).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function generate_user_list() {
|
||||
$('#user_list').html('');
|
||||
|
||||
var filter = null;
|
||||
|
||||
if ($('#user_search').val()) {
|
||||
filter = $('#user_search').val().toLowerCase();
|
||||
}
|
||||
|
||||
var ids = [];
|
||||
|
||||
var only_local_user = perms == null || (!perms.warning_show && !perms.ban_show);
|
||||
|
||||
users.forEach(function(user) {
|
||||
var activity = user.activities[0];
|
||||
|
||||
if (activity == null) { return; }
|
||||
if (only_local_user && user.identifier !== local_steamid64) { return; }
|
||||
|
||||
if (filter != null) {
|
||||
if (activity.extra.Nickname.toLowerCase().indexOf(filter) == -1 && user.username.toLowerCase().indexOf(filter) == -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var color = 'white';
|
||||
if (user.memberships.length > 0) {
|
||||
color = user.memberships[0].group.color;
|
||||
}
|
||||
|
||||
var warn_badge_color = ((user.warnings.length == 0) ? '#444' : "#f0ad4e");
|
||||
var ban_badge_color = ((user.bans.length == 0) ? '#444' : "#d9534f");
|
||||
|
||||
$('#user_list').append(' \
|
||||
<li class="user-tab" id="user_tab_' + user.id + '" onclick="generate_user_overview(\'' + user.id + '\')" style="cursor:pointer; color: ' + color + ';"> \
|
||||
' + escape(activity.extra.Nickname) + ' \
|
||||
<span class="badge pull-right" style="background-color: ' + ban_badge_color + ';">' + user.bans.length + ' <i class="fa fa-gavel"></i></span> \
|
||||
<span class="badge pull-right" style="background-color: ' + warn_badge_color + '; margin-left: 3px; margin-right: 3px;">' + user.warnings.length + ' <i class="fa fa-exclamation-triangle"></i></span> \
|
||||
</li> \
|
||||
');
|
||||
|
||||
ids.push(user.id);
|
||||
});
|
||||
|
||||
if (ids.length == 1) {
|
||||
generate_user_overview(ids[0]);
|
||||
} else if (ids.length == 0) {
|
||||
$('#user_content_empty').show();
|
||||
$('#user_content').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function generate_user_overview(user_id) {
|
||||
current_user = null;
|
||||
|
||||
$('#user_content_empty').hide();
|
||||
$('#user_content').hide();
|
||||
|
||||
var user = users_by_id[user_id];
|
||||
if (user == null) { return; }
|
||||
|
||||
var activity = user.activities[0];
|
||||
if (activity == null) { return; }
|
||||
|
||||
current_user = user;
|
||||
|
||||
$('#user_content_name').text(activity.extra.Nickname);
|
||||
$('#user_content_username').text(user.username);
|
||||
|
||||
if (activity.extra.Nickname === user.username) {
|
||||
$('#user_content_username').hide();
|
||||
} else {
|
||||
$('#user_content_username').show();
|
||||
}
|
||||
|
||||
$('.user-tab').removeClass("active");
|
||||
$('#user_tab_' + user_id).addClass("active");
|
||||
|
||||
$('#user_content_warnings').html('');
|
||||
user.warnings.forEach(function(warning) {
|
||||
var row_class = "success";
|
||||
|
||||
if (warning.disabled) {
|
||||
row_class = "active";
|
||||
} else if (!warning.active) {
|
||||
row_class = "warning";
|
||||
}
|
||||
|
||||
$('#user_content_warnings').append(' \
|
||||
<tr> \
|
||||
<td class="' + row_class + '"></td> \
|
||||
<td>' + escape(warning.reason) + '</td> \
|
||||
<td>' + escape(warning.creator.username) + '</td> \
|
||||
<td>' + format_date(warning.created_on) + '</td> \
|
||||
<td class="text-right"> \
|
||||
<button class="btn btn-default btn-xs perm-warning_edit" onclick="vyhub.warning_toggle(\'' + warning.id + '\')"><i class="fa fa-play"></i><i class="fa fa-pause"></i></button> \
|
||||
<button class="btn btn-default btn-xs perm-warning_delete" onclick="vyhub.warning_delete(\'' + warning.id + '\')"><i class="fa fa-trash"></i></button> \
|
||||
</td> \
|
||||
</tr> \
|
||||
');
|
||||
});
|
||||
|
||||
$('#user_content_bans').html('');
|
||||
user.bans.forEach(function(ban) {
|
||||
var minutes = '∞';
|
||||
|
||||
if (ban.length != null) {
|
||||
minutes = Math.round(ban.length/60);
|
||||
}
|
||||
|
||||
var row_class = "success";
|
||||
|
||||
if (ban.status == "UNBANNED") {
|
||||
row_class = "warning";
|
||||
} else if (!ban.active) {
|
||||
row_class = "danger";
|
||||
} else if (ban.serverbundle == null) {
|
||||
row_class = "info";
|
||||
}
|
||||
|
||||
var actions = "";
|
||||
|
||||
if (ban.status == "ACTIVE") {
|
||||
actions += '<button class="btn btn-default btn-xs perm-ban_edit" onclick="vyhub.ban_set_status(\'' + ban.id + '\', \'UNBANNED\')"><i class="fa fa-check"></i> ]] .. VyHub.lang.other.unban .. [[</button>';
|
||||
} else if (ban.status == "UNBANNED") {
|
||||
actions += '<button class="btn btn-default btn-xs perm-ban_edit" onclick="vyhub.ban_set_status(\'' + ban.id + '\', \'ACTIVE\')"><i class="fa fa-gavel"></i> ]] .. VyHub.lang.other.reban .. [[</button>';
|
||||
}
|
||||
|
||||
$('#user_content_bans').append(' \
|
||||
<tr> \
|
||||
<td class="' + row_class + '"></td> \
|
||||
<td>' + escape(ban.reason) + '</td> \
|
||||
<td>' + escape(ban.creator.username) + '</td> \
|
||||
<td>' + format_date(ban.created_on) + '</td> \
|
||||
<td>' + minutes + '</td> \
|
||||
<td class="text-right">' + actions + '</td> \
|
||||
</tr> \
|
||||
');
|
||||
});
|
||||
|
||||
$('#user_memberships').html('');
|
||||
|
||||
user.memberships.forEach(function(membership) {
|
||||
$('#user_memberships').append('<span class="label label-default" style="background-color: ' + membership.group.color + ';">' + membership.group.name + '</span>');
|
||||
});
|
||||
|
||||
$('#user_content').show();
|
||||
|
||||
enforce_perms();
|
||||
}
|
||||
|
||||
function reload_current_user() {
|
||||
if (current_user != null) {
|
||||
generate_user_overview(current_user.id);
|
||||
}
|
||||
}
|
||||
|
||||
function create_warning() {
|
||||
if (current_user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var reason = $('#user_warn').val();
|
||||
|
||||
vyhub.warning_create(current_user.identifier, reason);
|
||||
|
||||
$('#user_warn').val('');
|
||||
}
|
||||
|
||||
function create_ban() {
|
||||
if (current_user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var reason = $('#user_ban_reason').val();
|
||||
var minutes = $('#user_ban_minutes').val();
|
||||
|
||||
vyhub.ban_create(current_user.identifier, minutes, reason);
|
||||
|
||||
$('#user_ban_reason').val('');
|
||||
$('#user_ban_minutes').val('');
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
function VyHub.Dashboard:load_users(users_json)
|
||||
VyHub.Dashboard.ui_html:RunJavascript("load_data(" .. users_json .. ");")
|
||||
VyHub.Dashboard.ui_html:RunJavascript("reload_current_user();")
|
||||
end
|
||||
|
||||
function VyHub.Dashboard:load_perms(perms_json)
|
||||
VyHub.Dashboard.ui_html:RunJavascript("load_perms(" .. perms_json .. ");")
|
||||
end
|
||||
|
||||
concommand.Add("vh_dashboard", function ()
|
||||
if VyHub.Dashboard.ui == nil or not VyHub.Dashboard.ui:IsValid() then
|
||||
VyHub.Dashboard:create_ui()
|
||||
VyHub.Dashboard.ui:Show()
|
||||
VyHub.Dashboard.ui:MakePopup()
|
||||
else
|
||||
-- VyHub.Dashboard:create_ui()
|
||||
|
||||
-- if VyHub.Dashboard.ui != nil and VyHub.Dashboard.ui:IsValid() and VyHub.Dashboard.ui:IsVisible() then
|
||||
-- VyHub.Dashboard.ui:Hide()
|
||||
-- else
|
||||
VyHub.Dashboard.ui:Show()
|
||||
VyHub.Dashboard.ui:MakePopup()
|
||||
-- end
|
||||
end
|
||||
|
||||
net.Start("vyhub_dashboard")
|
||||
net.SendToServer()
|
||||
end)
|
||||
|
||||
|
||||
net.Receive("vyhub_dashboard", function()
|
||||
local data_length = net.ReadUInt(16)
|
||||
local data_raw = net.ReadData(data_length)
|
||||
local perms_json = net.ReadString()
|
||||
local users_json = util.Decompress(data_raw)
|
||||
|
||||
timer.Create("vyhub_dashboard_html_ready", 0.3, 20, function ()
|
||||
if not VyHub.Dashboard.html_ready then
|
||||
MsgN("VyHub Dashboard: Waiting for HTML to load.")
|
||||
return
|
||||
end
|
||||
|
||||
timer.Remove("vyhub_dashboard_html_ready")
|
||||
|
||||
VyHub.Dashboard:load_perms(perms_json)
|
||||
VyHub.Dashboard:load_users(users_json)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
net.Receive("vyhub_dashboard_reload", function()
|
||||
if VyHub.Dashboard.ui and VyHub.Dashboard.ui:IsVisible() then
|
||||
MsgN("Reloading dashboard data, because server told us.")
|
||||
net.Start("vyhub_dashboard")
|
||||
net.SendToServer()
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("vyhub_lang_loaded", "vyhub_dashboard_vyhub_lang_loaded", function ()
|
||||
VyHub.Dashboard:load_html()
|
||||
end)
|
||||
|
||||
if VyHub.Dashboard.html_generated then
|
||||
VyHub.Dashboard:load_html()
|
||||
end
|
||||
|
||||
30
addons/vyhub-gmod/lua/vyhub/client/cl_group.lua
Normal file
30
addons/vyhub-gmod/lua/vyhub/client/cl_group.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
VyHub.groups_mapped = VyHub.groups_mapped or nil
|
||||
|
||||
net.Receive("vyhub_group_data", function()
|
||||
local num = net.ReadUInt(8)
|
||||
local groups_mapped_new = {}
|
||||
|
||||
for i=1, num do
|
||||
-- Currently only the name and color of the group is transferred
|
||||
local name_game = net.ReadString()
|
||||
local name = net.ReadString()
|
||||
local color = net.ReadString()
|
||||
|
||||
groups_mapped_new[name_game] = {
|
||||
name = name,
|
||||
color = color,
|
||||
}
|
||||
end
|
||||
|
||||
VyHub.groups_mapped = groups_mapped_new
|
||||
end)
|
||||
27
addons/vyhub-gmod/lua/vyhub/client/cl_ply.lua
Normal file
27
addons/vyhub-gmod/lua/vyhub/client/cl_ply.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local meta_ply = FindMetaTable("Player")
|
||||
|
||||
VyHub.user_id = VyHub.user_id or nil
|
||||
|
||||
function meta_ply:VyHubID()
|
||||
if IsValid(self) then
|
||||
if self == LocalPlayer() then
|
||||
return VyHub.user_id
|
||||
else
|
||||
MsgN("ERROR: Cannot get VyHubID of other users on the client side.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
net.Receive("vyhub_user_id", function ()
|
||||
VyHub.user_id = net.ReadString()
|
||||
end)
|
||||
26
addons/vyhub-gmod/lua/vyhub/config/sh_config.lua
Normal file
26
addons/vyhub-gmod/lua/vyhub/config/sh_config.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
-- Language used. Currently only languages in the "lang" directory are supported.
|
||||
VyHub.Config.lang = "en"
|
||||
|
||||
-- Enable chat tags, not working together with DarkRP
|
||||
VyHub.Config.chat_tags = true
|
||||
|
||||
-- Date format to use (for example in ban message)
|
||||
-- See https://tieske.github.io/date/#dateObject.fmt
|
||||
VyHub.Config.date_format = "%Y-%m-%d %H:%M:%S %z"
|
||||
-- Time offset from UTC (+00:00)
|
||||
-- Uses the timezone of the GMOD server when set to nil
|
||||
-- Example: 2 for CEST, -5 for EST
|
||||
VyHub.Config.time_offset = nil
|
||||
|
||||
-- Debug mode. Enable to see all API requests and responses
|
||||
VyHub.Config.debug = false
|
||||
70
addons/vyhub-gmod/lua/vyhub/config/sv_config.lua
Normal file
70
addons/vyhub-gmod/lua/vyhub/config/sv_config.lua
Normal file
@@ -0,0 +1,70 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
-- VyHub Server Config
|
||||
-- BEWARE: Additional config values can be set in data/vyhub/config.json with the `vh_config <key> <value>` console command.
|
||||
-- The configuration in this file is overwritten by the configuration in data/vyhub/config.json
|
||||
|
||||
-- ONLY SET THE 3 FOLLOWING OPTIONS IF YOU KNOW WHAT YOU ARE DOING!
|
||||
-- PLEASE FOLLOW THE INSTALLATION INSTRUCTIONS HERE: https://docs.vyhub.net/latest/game/gmod/#installation
|
||||
VyHub.Config.api_url = "" -- https://api.vyhub.app/<name>/v1
|
||||
VyHub.Config.api_key = "" -- Admin -> Settings -> Server -> Setup
|
||||
VyHub.Config.server_id = "" -- Admin -> Settings -> Server -> Setup
|
||||
|
||||
-- Prevent script execution as reward
|
||||
-- Rewards that want to execute a script will not work if this is enabled.
|
||||
VyHub.Config.reward_disable_scripts = false
|
||||
-- Whitelsit for executed reward commands
|
||||
-- If this table has entries, only commands matching the given patterns are executed
|
||||
-- Patterns: https://wiki.facepunch.com/gmod/Patterns
|
||||
-- Example: { "^ulx adduser %l+ %l+$" } -> Allows a command like "ulx adduser username groupname"
|
||||
VyHub.Config.reward_command_whitelist = {}
|
||||
|
||||
-- Player groups are checked every X seconds
|
||||
VyHub.Config.player_refresh_time = 120
|
||||
-- Groups are refreshed every X seconds
|
||||
VyHub.Config.group_refresh_time = 300
|
||||
-- Every X seconds, an advert message is shown.
|
||||
VyHub.Config.advert_interval = 180
|
||||
|
||||
-- Printed before every advert line
|
||||
VyHub.Config.advert_prefix = "[★] "
|
||||
|
||||
-- Disable group sync
|
||||
VyHub.Config.group_disable_sync = false
|
||||
|
||||
-- Disable override of admin mod bans (ULX, SAM, ServerGuard, xAdmin, ...)
|
||||
VyHub.Config.ban_disable_sync = false
|
||||
-- Replace ULib ban list with VyHub bans
|
||||
VyHub.Config.replace_ulib_bans = false
|
||||
|
||||
-- Commands that open the shop page
|
||||
VyHub.Config.commands_shop = { '!shop' }
|
||||
-- Commands that open the bans page
|
||||
VyHub.Config.commands_bans = { '!bans' }
|
||||
-- Commands that open the warnings page
|
||||
VyHub.Config.commands_warnings = { '!warnings' }
|
||||
-- Commands that open the news page
|
||||
VyHub.Config.commands_news = { '!news' }
|
||||
-- Commands that open the profile page of a user (Usage: !user <user>)
|
||||
VyHub.Config.commands_profile = { '!user' }
|
||||
-- Commands to warn a user (Usage: !warn <user> <reason>)
|
||||
VyHub.Config.commands_warn = { '!warn' }
|
||||
-- Commands to open the dashboard
|
||||
VyHub.Config.commands_dashboard = { '!dashboard' }
|
||||
|
||||
-- Customize the ban message that banned players see when trying to connect
|
||||
VyHub.Config.ban_message = ">>> Ban Message <<<" .. "\n\n"
|
||||
.. VyHub.lang.other.reason .. ": %reason%" .. "\n"
|
||||
.. VyHub.lang.other.ban_date .. ": %ban_date%" .. "\n"
|
||||
.. VyHub.lang.other.unban_date .. ": %unban_date%" .. "\n"
|
||||
.. VyHub.lang.other.admin .. ": %admin%" .. "\n"
|
||||
.. VyHub.lang.other.id .. ": %id%" .. "\n\n"
|
||||
.. VyHub.lang.other.unban_url .. ": %unban_url%" .. "\n\n"
|
||||
1
addons/vyhub-gmod/lua/vyhub/lang/CONTRIBUTORS.b64
Normal file
1
addons/vyhub-gmod/lua/vyhub/lang/CONTRIBUTORS.b64
Normal file
@@ -0,0 +1 @@
|
||||
AA==
|
||||
201
addons/vyhub-gmod/lua/vyhub/lang/LICENSE
Normal file
201
addons/vyhub-gmod/lua/vyhub/lang/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [2022] [Matbyte UG]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
14
addons/vyhub-gmod/lua/vyhub/lang/README.md
Normal file
14
addons/vyhub-gmod/lua/vyhub/lang/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
[](http://translate.matbyte.com/engage/vyhub/)
|
||||
|
||||
# vyhub-lang
|
||||
Translations for VyHub GMOD
|
||||
|
||||
Matbyte Translation Tool (MTT): https://translate.matbyte.com/projects/vyhub/vyhub-lang/
|
||||
|
||||
## Contribute
|
||||
|
||||
1. Create a MTT account (see above)
|
||||
2. Contact us with your username and the language you wish to translate
|
||||
3. After your account has been unlocked, translate as much as you want
|
||||
4. Regularily check for new strings that need to be translated
|
||||
|
||||
63
addons/vyhub-gmod/lua/vyhub/lang/de.json
Normal file
63
addons/vyhub-gmod/lua/vyhub/lang/de.json
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"ply": {
|
||||
"no_permissions": "Du hast nicht die nötigen Berechtigungen dafür.",
|
||||
"banned_self": "Du wurdest vom Server gebannt",
|
||||
"group_changed": "Deine Gruppe wurde zu <green>%s</green> geändert.",
|
||||
"error_get": "Spieler konnte nicht gefunden werden. Bitte probiere es später erneut.",
|
||||
"banned": "Spieler <green>%s</green> wurde <red>%s gebannt</red>. Grund: <green>%s</green>",
|
||||
"welcome": "Willkommen auf dem Server, <green>%s</green>"
|
||||
},
|
||||
"warning": {
|
||||
"toggled": "Status der Verwarnung wurde geändert.",
|
||||
"cmd_help": "<red>Ungültiger Spieler!</red> Verwendung: <green>!warn <nick> <reason></green>",
|
||||
"create_error": "Fehler beim hinzufügen einer Verwarnung für <green>%s</green>: <red>%s</red>",
|
||||
"deleted": "Verwarnung gelöscht.",
|
||||
"received": "Du wurdest von <green>%s</green> verwarnt: <red>%s</red>",
|
||||
"toggled_self": "Der Status einer deiner Verwarnungen wurde geändert. Du kannst deiner Verwarnungen unter !dashboard sehen.",
|
||||
"user_warned": "<red>%s</red> wurde von <green>%s</green> verwarnt. Grund: <green>%s</green>",
|
||||
"deleted_self": "Eine deiner Verwarnungen wurde gelöscht. Du kannst deiner Verwarnungen unter !dashboard sehen."
|
||||
},
|
||||
"ban": {
|
||||
"status_changed": "Ban Status von %s erfolgreich auf %s gesetzt.",
|
||||
"user_banned": "<red>%s</red> wurde von <green>%s</green> für <red>%s</red> vom Server gebannt. Grund: <green>%s</green>"
|
||||
},
|
||||
"rslots": {
|
||||
"full": "Der Server ist voll",
|
||||
"full_no_slot": "Der Server ist voll und du hast keinen Zugriff auf einen reservierten Slot",
|
||||
"kick": "Ein Spieler mit einem reservierten Slot ist dem Server beigetreten und du wurdest gekickt um Platz zu schaffen"
|
||||
},
|
||||
"other": {
|
||||
"id": "ID",
|
||||
"reason": "Grund",
|
||||
"dead": "TOT",
|
||||
"ban_date": "Ban Datum",
|
||||
"unban_date": "Ban Ende",
|
||||
"admin": "Admin",
|
||||
"unknown": "Unbekannt",
|
||||
"minutes": "Minuten",
|
||||
"x_minutes": "%i Minuten",
|
||||
"permanently": "Permanent",
|
||||
"unban_url": "Entbannungs URL",
|
||||
"error_api": "Fehler bei der Kommunikation mit der API: %s",
|
||||
"never": "Nie",
|
||||
"active_global": "Aktiv (Global)",
|
||||
"unban": "Entbannen",
|
||||
"actions": "Aktionen",
|
||||
"active": "Aktiv",
|
||||
"inactive": "Inaktiv",
|
||||
"disabled": "Deaktiviert",
|
||||
"unbanned": "Entbannt",
|
||||
"reban": "Bannen",
|
||||
"warnings": "Verwarnungen",
|
||||
"date": "Datum",
|
||||
"warn": "Verwarnung",
|
||||
"ban": "Bann",
|
||||
"bans": "Banns",
|
||||
"welcome": "Willkommen"
|
||||
},
|
||||
"dashboard": {
|
||||
"select_user": "Bitte wähle einen Spieler aus.",
|
||||
"action_ban": "Bannen",
|
||||
"action_warn": "Verwarnen"
|
||||
}
|
||||
}
|
||||
63
addons/vyhub-gmod/lua/vyhub/lang/en.json
Normal file
63
addons/vyhub-gmod/lua/vyhub/lang/en.json
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"ply": {
|
||||
"banned": "Player <green>%s</green> has been <red>banned for %s</red>. Reason: <green>%s</green>",
|
||||
"no_permissions": "You don't have all required permissions.",
|
||||
"banned_self": "You are banned from this server",
|
||||
"group_changed": "Your group has been changed to <green>%s</green>.",
|
||||
"error_get": "Could find player. Please try again.",
|
||||
"welcome": "Welcome on the server, <green>%s</green>"
|
||||
},
|
||||
"warning": {
|
||||
"user_warned": "<red>%s</red> has been warned by <green>%s</green>. Reason: <green>%s</green>",
|
||||
"cmd_help": "<red>Invlid player!</red> Usage: <green>!warn <nick> <reason></green>",
|
||||
"toggled_self": "The status of one of your warnings has been changed. Check your warnings with !dashboard.",
|
||||
"create_error": "Error while adding warning for player <green>%s</green>: <red>%s</red>",
|
||||
"toggled": "Warning status changed.",
|
||||
"deleted": "Warning deleted.",
|
||||
"deleted_self": "One of your warnings has been deleted. Check your warnings with !dashboard.",
|
||||
"received": "You have received a warning by <green>%s</green>: <red>%s</red>"
|
||||
},
|
||||
"ban": {
|
||||
"status_changed": "Successfully set ban status of %s to %s.",
|
||||
"user_banned": "<red>%s</red> has been banned by <green>%s</green> for <red>%s</red>. Reason: <green>%s</green>"
|
||||
},
|
||||
"rslots": {
|
||||
"kick": "A player with a reserved slot connected to the server and you got kicked to free up space",
|
||||
"full": "The server is full",
|
||||
"full_no_slot": "The server is full and you do not have access to a reserved slot"
|
||||
},
|
||||
"dashboard": {
|
||||
"select_user": "Please select an user.",
|
||||
"action_ban": "Ban",
|
||||
"action_warn": "Warn"
|
||||
},
|
||||
"other": {
|
||||
"active": "Active",
|
||||
"active_global": "Active (Global)",
|
||||
"inactive": "Inactive",
|
||||
"disabled": "Disabled",
|
||||
"unbanned": "Unbanned",
|
||||
"id": "ID",
|
||||
"reason": "Reason",
|
||||
"dead": "DEAD",
|
||||
"ban_date": "Ban date",
|
||||
"unban_date": "Unban date",
|
||||
"unban": "Unban",
|
||||
"reban": "Reban",
|
||||
"admin": "Admin",
|
||||
"welcome": "Welcome",
|
||||
"actions": "Actions",
|
||||
"never": "Never",
|
||||
"warnings": "Warnings",
|
||||
"date": "Date",
|
||||
"ban": "Ban",
|
||||
"warn": "Warn",
|
||||
"bans": "Bans",
|
||||
"unknown": "Unknown",
|
||||
"minutes": "Minutes",
|
||||
"x_minutes": "%i Minutes",
|
||||
"permanently": "Permanently",
|
||||
"unban_url": "Unban URL",
|
||||
"error_api": "Error while communicating with the API: %s"
|
||||
}
|
||||
}
|
||||
63
addons/vyhub-gmod/lua/vyhub/lang/fr.json
Normal file
63
addons/vyhub-gmod/lua/vyhub/lang/fr.json
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"ply": {
|
||||
"banned": "Le joueur <green>%s</green> a été <red>banni pendant %s</red>. Raison : <green>%s</green>",
|
||||
"no_permissions": "Vous ne disposez pas de toutes les permissions requises.",
|
||||
"banned_self": "Vous êtes banni de ce serveur",
|
||||
"error_get": "Pourrait trouver un joueur. Veuillez réessayer.",
|
||||
"group_changed": "Votre groupe a été changé par <green>%s</green>.",
|
||||
"welcome": "Bienvenue sur le serveur, <green>%s</green>"
|
||||
},
|
||||
"warning": {
|
||||
"user_warned": "<red>%s</red> a été averti par <green>%s</green>. Raison : <green>%s</green>",
|
||||
"toggled_self": "L'état de l'un de vos avertissements a été modifié. Vérifiez vos avertissements avec !dashboard.",
|
||||
"create_error": "Erreur lors de l'ajout d'un avertissement pour le joueur <green>%s</green> : <red>%s</red>",
|
||||
"deleted": "Avertissement supprimé.",
|
||||
"deleted_self": "L'un de vos avertissements a été supprimé. Vérifiez vos avertissements avec !dashboard.",
|
||||
"toggled": "L'état d'avertissement a changé.",
|
||||
"cmd_help": "<red>Joueur invalide !</red> Utilisation : <green>!warn <joueur> <raison></green>",
|
||||
"received": "Vous avez reçu un avertissement de <green>%s</green> : <red>%s</red>"
|
||||
},
|
||||
"ban": {
|
||||
"status_changed": "Le statut de bannissement de %s a été défini avec succès sur %s.",
|
||||
"user_banned": "<red>%s</red> a été banni par <green>%s</green> pour <red>%s</red>. Raison : <green>%s</green>"
|
||||
},
|
||||
"rslots": {
|
||||
"full": "Le serveur est plein",
|
||||
"full_no_slot": "Le serveur est plein et vous n'avez pas accès à un créneau réservé",
|
||||
"kick": "Un joueur avec un emplacement réservé connecté au serveur et vous avez été expulsé pour libérer de l'espace"
|
||||
},
|
||||
"dashboard": {
|
||||
"select_user": "Veuillez sélectionner un utilisateur.",
|
||||
"action_warn": "Avertir",
|
||||
"action_ban": "Bannir"
|
||||
},
|
||||
"other": {
|
||||
"active": "Actif",
|
||||
"active_global": "Actif (Global)",
|
||||
"inactive": "Inactif",
|
||||
"disabled": "Désactivé",
|
||||
"unbanned": "Débannir",
|
||||
"id": "ID",
|
||||
"reason": "Raison",
|
||||
"dead": "Mort",
|
||||
"ban_date": "Date de bannissement",
|
||||
"unban": "Débannir",
|
||||
"unban_date": "Date de débannissement",
|
||||
"reban": "Rebannir",
|
||||
"admin": "Administrateur",
|
||||
"actions": "Actions",
|
||||
"never": "Jamais",
|
||||
"warnings": "Avertissements",
|
||||
"date": "Date",
|
||||
"ban": "Bannir",
|
||||
"warn": "Avertir",
|
||||
"bans": "Bannissements",
|
||||
"minutes": "Minutes",
|
||||
"unknown": "Inconnu",
|
||||
"x_minutes": "%i Minutes",
|
||||
"unban_url": "URL de débannissement",
|
||||
"permanently": "Permanent",
|
||||
"error_api": "Erreur lors de la communication avec l'API : %s",
|
||||
"welcome": "Bienvenue"
|
||||
}
|
||||
}
|
||||
766
addons/vyhub-gmod/lua/vyhub/lib/date.lua
Normal file
766
addons/vyhub-gmod/lua/vyhub/lib/date.lua
Normal file
@@ -0,0 +1,766 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
VyHub.Lib.date = VyHub.Lib.date or {}
|
||||
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Module for date and time calculations
|
||||
--
|
||||
-- Version 2.2
|
||||
-- Copyright (C) 2005-2006, by Jas Latrix (jastejada@yahoo.com)
|
||||
-- Copyright (C) 2013-2021, by Thijs Schreijer
|
||||
-- Licensed under MIT, http://opensource.org/licenses/MIT
|
||||
|
||||
-- https://github.com/Tieske/date
|
||||
|
||||
-- Changes by Matbyte: New function setbias
|
||||
|
||||
--[[ CONSTANTS ]]--
|
||||
local HOURPERDAY = 24
|
||||
local MINPERHOUR = 60
|
||||
local MINPERDAY = 1440 -- 24*60
|
||||
local SECPERMIN = 60
|
||||
local SECPERHOUR = 3600 -- 60*60
|
||||
local SECPERDAY = 86400 -- 24*60*60
|
||||
local TICKSPERSEC = 1000000
|
||||
local TICKSPERDAY = 86400000000
|
||||
local TICKSPERHOUR = 3600000000
|
||||
local TICKSPERMIN = 60000000
|
||||
local DAYNUM_MAX = 365242500 -- Sat Jan 01 1000000 00:00:00
|
||||
local DAYNUM_MIN = -365242500 -- Mon Jan 01 1000000 BCE 00:00:00
|
||||
local DAYNUM_DEF = 0 -- Mon Jan 01 0001 00:00:00
|
||||
local _;
|
||||
--[[ GLOBAL SETTINGS ]]--
|
||||
local centuryflip = 0 -- year >= centuryflip == 1900, < centuryflip == 2000
|
||||
--[[ LOCAL ARE FASTER ]]--
|
||||
local type = type
|
||||
local pairs = pairs
|
||||
local error = error
|
||||
local assert = assert
|
||||
local tonumber = tonumber
|
||||
local tostring = tostring
|
||||
local string = string
|
||||
local math = math
|
||||
local os = os
|
||||
local unpack = unpack or table.unpack
|
||||
local setmetatable = setmetatable
|
||||
local getmetatable = getmetatable
|
||||
--[[ EXTRA FUNCTIONS ]]--
|
||||
local fmt = string.format
|
||||
local lwr = string.lower
|
||||
local rep = string.rep
|
||||
local len = string.len -- luacheck: ignore
|
||||
local sub = string.sub
|
||||
local gsub = string.gsub
|
||||
local gmatch = string.gmatch or string.gfind
|
||||
local find = string.find
|
||||
local ostime = os.time
|
||||
local osdate = os.date
|
||||
local floor = math.floor
|
||||
local ceil = math.ceil
|
||||
local abs = math.abs
|
||||
-- removes the decimal part of a number
|
||||
local function fix(n) n = tonumber(n) return n and ((n > 0 and floor or ceil)(n)) end
|
||||
-- returns the modulo n % d;
|
||||
local function mod(n,d) return n - d*floor(n/d) end
|
||||
-- is `str` in string list `tbl`, `ml` is the minimun len
|
||||
local function inlist(str, tbl, ml, tn)
|
||||
local sl = len(str)
|
||||
if sl < (ml or 0) then return nil end
|
||||
str = lwr(str)
|
||||
for k, v in pairs(tbl) do
|
||||
if str == lwr(sub(v, 1, sl)) then
|
||||
if tn then tn[0] = k end
|
||||
return k
|
||||
end
|
||||
end
|
||||
end
|
||||
local function fnil() end
|
||||
--[[ DATE FUNCTIONS ]]--
|
||||
local DATE_EPOCH -- to be set later
|
||||
local sl_weekdays = {
|
||||
[0]="Sunday",[1]="Monday",[2]="Tuesday",[3]="Wednesday",[4]="Thursday",[5]="Friday",[6]="Saturday",
|
||||
[7]="Sun",[8]="Mon",[9]="Tue",[10]="Wed",[11]="Thu",[12]="Fri",[13]="Sat",
|
||||
}
|
||||
local sl_meridian = {[-1]="AM", [1]="PM"}
|
||||
local sl_months = {
|
||||
[00]="January", [01]="February", [02]="March",
|
||||
[03]="April", [04]="May", [05]="June",
|
||||
[06]="July", [07]="August", [08]="September",
|
||||
[09]="October", [10]="November", [11]="December",
|
||||
[12]="Jan", [13]="Feb", [14]="Mar",
|
||||
[15]="Apr", [16]="May", [17]="Jun",
|
||||
[18]="Jul", [19]="Aug", [20]="Sep",
|
||||
[21]="Oct", [22]="Nov", [23]="Dec",
|
||||
}
|
||||
-- added the '.2' to avoid collision, use `fix` to remove
|
||||
local sl_timezone = {
|
||||
[000]="utc", [0.2]="gmt",
|
||||
[300]="est", [240]="edt",
|
||||
[360]="cst", [300.2]="cdt",
|
||||
[420]="mst", [360.2]="mdt",
|
||||
[480]="pst", [420.2]="pdt",
|
||||
}
|
||||
-- set the day fraction resolution
|
||||
local function setticks(t)
|
||||
TICKSPERSEC = t;
|
||||
TICKSPERDAY = SECPERDAY*TICKSPERSEC
|
||||
TICKSPERHOUR= SECPERHOUR*TICKSPERSEC
|
||||
TICKSPERMIN = SECPERMIN*TICKSPERSEC
|
||||
end
|
||||
-- is year y leap year?
|
||||
local function isleapyear(y) -- y must be int!
|
||||
return (mod(y, 4) == 0 and (mod(y, 100) ~= 0 or mod(y, 400) == 0))
|
||||
end
|
||||
-- day since year 0
|
||||
local function dayfromyear(y) -- y must be int!
|
||||
return 365*y + floor(y/4) - floor(y/100) + floor(y/400)
|
||||
end
|
||||
-- day number from date, month is zero base
|
||||
local function makedaynum(y, m, d)
|
||||
local mm = mod(mod(m,12) + 10, 12)
|
||||
return dayfromyear(y + floor(m/12) - floor(mm/10)) + floor((mm*306 + 5)/10) + d - 307
|
||||
--local yy = y + floor(m/12) - floor(mm/10)
|
||||
--return dayfromyear(yy) + floor((mm*306 + 5)/10) + (d - 1)
|
||||
end
|
||||
-- date from day number, month is zero base
|
||||
local function breakdaynum(g)
|
||||
local g = g + 306
|
||||
local y = floor((10000*g + 14780)/3652425)
|
||||
local d = g - dayfromyear(y)
|
||||
if d < 0 then y = y - 1; d = g - dayfromyear(y) end
|
||||
local mi = floor((100*d + 52)/3060)
|
||||
return (floor((mi + 2)/12) + y), mod(mi + 2,12), (d - floor((mi*306 + 5)/10) + 1)
|
||||
end
|
||||
--[[ for floats or int32 Lua Number data type
|
||||
local function breakdaynum2(g)
|
||||
local g, n = g + 306;
|
||||
local n400 = floor(g/DI400Y);n = mod(g,DI400Y);
|
||||
local n100 = floor(n/DI100Y);n = mod(n,DI100Y);
|
||||
local n004 = floor(n/DI4Y); n = mod(n,DI4Y);
|
||||
local n001 = floor(n/365); n = mod(n,365);
|
||||
local y = (n400*400) + (n100*100) + (n004*4) + n001 - ((n001 == 4 or n100 == 4) and 1 or 0)
|
||||
local d = g - dayfromyear(y)
|
||||
local mi = floor((100*d + 52)/3060)
|
||||
return (floor((mi + 2)/12) + y), mod(mi + 2,12), (d - floor((mi*306 + 5)/10) + 1)
|
||||
end
|
||||
]]
|
||||
-- day fraction from time
|
||||
local function makedayfrc(h,r,s,t)
|
||||
return ((h*60 + r)*60 + s)*TICKSPERSEC + t
|
||||
end
|
||||
-- time from day fraction
|
||||
local function breakdayfrc(df)
|
||||
return
|
||||
mod(floor(df/TICKSPERHOUR),HOURPERDAY),
|
||||
mod(floor(df/TICKSPERMIN ),MINPERHOUR),
|
||||
mod(floor(df/TICKSPERSEC ),SECPERMIN),
|
||||
mod(df,TICKSPERSEC)
|
||||
end
|
||||
-- weekday sunday = 0, monday = 1 ...
|
||||
local function weekday(dn) return mod(dn + 1, 7) end
|
||||
-- yearday 0 based ...
|
||||
local function yearday(dn)
|
||||
return dn - dayfromyear((breakdaynum(dn))-1)
|
||||
end
|
||||
-- parse v as a month
|
||||
local function getmontharg(v)
|
||||
local m = tonumber(v);
|
||||
return (m and fix(m - 1)) or inlist(tostring(v) or "", sl_months, 2)
|
||||
end
|
||||
-- get daynum of isoweek one of year y
|
||||
local function isow1(y)
|
||||
local f = makedaynum(y, 0, 4) -- get the date for the 4-Jan of year `y`
|
||||
local d = weekday(f)
|
||||
d = d == 0 and 7 or d -- get the ISO day number, 1 == Monday, 7 == Sunday
|
||||
return f + (1 - d)
|
||||
end
|
||||
local function isowy(dn)
|
||||
local w1;
|
||||
local y = (breakdaynum(dn))
|
||||
if dn >= makedaynum(y, 11, 29) then
|
||||
w1 = isow1(y + 1);
|
||||
if dn < w1 then
|
||||
w1 = isow1(y);
|
||||
else
|
||||
y = y + 1;
|
||||
end
|
||||
else
|
||||
w1 = isow1(y);
|
||||
if dn < w1 then
|
||||
w1 = isow1(y-1)
|
||||
y = y - 1
|
||||
end
|
||||
end
|
||||
return floor((dn-w1)/7)+1, y
|
||||
end
|
||||
local function isoy(dn)
|
||||
local y = (breakdaynum(dn))
|
||||
return y + (((dn >= makedaynum(y, 11, 29)) and (dn >= isow1(y + 1))) and 1 or (dn < isow1(y) and -1 or 0))
|
||||
end
|
||||
local function makedaynum_isoywd(y,w,d)
|
||||
return isow1(y) + 7*w + d - 8 -- simplified: isow1(y) + ((w-1)*7) + (d-1)
|
||||
end
|
||||
--[[ THE DATE MODULE ]]--
|
||||
local fmtstr = "%x %X";
|
||||
--#if not DATE_OBJECT_AFX then
|
||||
local date = {}
|
||||
setmetatable(date, date)
|
||||
-- Version: VMMMRRRR; V-Major, M-Minor, R-Revision; e.g. 5.45.321 == 50450321
|
||||
do
|
||||
local major = 2
|
||||
local minor = 2
|
||||
local revision = 0
|
||||
date.version = major * 10000000 + minor * 10000 + revision
|
||||
end
|
||||
--#end -- not DATE_OBJECT_AFX
|
||||
--[[ THE DATE OBJECT ]]--
|
||||
local dobj = {}
|
||||
dobj.__index = dobj
|
||||
dobj.__metatable = dobj
|
||||
-- shout invalid arg
|
||||
local function date_error_arg() return error("invalid argument(s)",0) end
|
||||
-- create new date object
|
||||
local function date_new(dn, df)
|
||||
return setmetatable({daynum=dn, dayfrc=df}, dobj)
|
||||
end
|
||||
|
||||
--#if not NO_LOCAL_TIME_SUPPORT then
|
||||
-- magic year table
|
||||
local date_epoch, yt;
|
||||
local function getequivyear(y)
|
||||
assert(not yt)
|
||||
yt = {}
|
||||
local de = date_epoch:copy()
|
||||
local dw, dy
|
||||
for _ = 0, 3000 do
|
||||
de:setyear(de:getyear() + 1, 1, 1)
|
||||
dy = de:getyear()
|
||||
dw = de:getweekday() * (isleapyear(dy) and -1 or 1)
|
||||
if not yt[dw] then yt[dw] = dy end --print(de)
|
||||
if yt[1] and yt[2] and yt[3] and yt[4] and yt[5] and yt[6] and yt[7] and yt[-1] and yt[-2] and yt[-3] and yt[-4] and yt[-5] and yt[-6] and yt[-7] then
|
||||
getequivyear = function(y) return yt[ (weekday(makedaynum(y, 0, 1)) + 1) * (isleapyear(y) and -1 or 1) ] end
|
||||
return getequivyear(y)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- TimeValue from date and time
|
||||
local function totv(y,m,d,h,r,s)
|
||||
return (makedaynum(y, m, d) - DATE_EPOCH) * SECPERDAY + ((h*60 + r)*60 + s)
|
||||
end
|
||||
-- TimeValue from TimeTable
|
||||
local function tmtotv(tm)
|
||||
return tm and totv(tm.year, tm.month - 1, tm.day, tm.hour, tm.min, tm.sec)
|
||||
end
|
||||
-- Returns the bias in seconds of utc time daynum and dayfrc
|
||||
local function getbiasutc2(self)
|
||||
local y,m,d = breakdaynum(self.daynum)
|
||||
local h,r,s = breakdayfrc(self.dayfrc)
|
||||
local tvu = totv(y,m,d,h,r,s) -- get the utc TimeValue of date and time
|
||||
local tml = osdate("*t", tvu) -- get the local TimeTable of tvu
|
||||
if (not tml) or (tml.year > (y+1) or tml.year < (y-1)) then -- failed try the magic
|
||||
y = getequivyear(y)
|
||||
tvu = totv(y,m,d,h,r,s)
|
||||
tml = osdate("*t", tvu)
|
||||
end
|
||||
local tvl = tmtotv(tml)
|
||||
if tvu and tvl then
|
||||
return tvu - tvl, tvu, tvl
|
||||
else
|
||||
return error("failed to get bias from utc time")
|
||||
end
|
||||
end
|
||||
-- Returns the bias in seconds of local time daynum and dayfrc
|
||||
local function getbiasloc2(daynum, dayfrc)
|
||||
local tvu
|
||||
-- extract date and time
|
||||
local y,m,d = breakdaynum(daynum)
|
||||
local h,r,s = breakdayfrc(dayfrc)
|
||||
-- get equivalent TimeTable
|
||||
local tml = {year=y, month=m+1, day=d, hour=h, min=r, sec=s}
|
||||
-- get equivalent TimeValue
|
||||
local tvl = tmtotv(tml)
|
||||
|
||||
local function chkutc()
|
||||
tml.isdst = nil; local tvug = ostime(tml) if tvug and (tvl == tmtotv(osdate("*t", tvug))) then tvu = tvug return end
|
||||
tml.isdst = true; local tvud = ostime(tml) if tvud and (tvl == tmtotv(osdate("*t", tvud))) then tvu = tvud return end
|
||||
tvu = tvud or tvug
|
||||
end
|
||||
chkutc()
|
||||
if not tvu then
|
||||
tml.year = getequivyear(y)
|
||||
tvl = tmtotv(tml)
|
||||
chkutc()
|
||||
end
|
||||
return ((tvu and tvl) and (tvu - tvl)) or error("failed to get bias from local time"), tvu, tvl
|
||||
end
|
||||
--#end -- not NO_LOCAL_TIME_SUPPORT
|
||||
|
||||
--#if not DATE_OBJECT_AFX then
|
||||
-- the date parser
|
||||
local strwalker = {} -- ^Lua regular expression is not as powerful as Perl$
|
||||
strwalker.__index = strwalker
|
||||
local function newstrwalker(s)return setmetatable({s=s, i=1, e=1, c=len(s)}, strwalker) end
|
||||
function strwalker:aimchr() return "\n" .. self.s .. "\n" .. rep(".",self.e-1) .. "^" end
|
||||
function strwalker:finish() return self.i > self.c end
|
||||
function strwalker:back() self.i = self.e return self end
|
||||
function strwalker:restart() self.i, self.e = 1, 1 return self end
|
||||
function strwalker:match(s) return (find(self.s, s, self.i)) end
|
||||
function strwalker:__call(s, f)-- print("strwalker:__call "..s..self:aimchr())
|
||||
local is, ie; is, ie, self[1], self[2], self[3], self[4], self[5] = find(self.s, s, self.i)
|
||||
if is then self.e, self.i = self.i, 1+ie; if f then f(unpack(self)) end return self end
|
||||
end
|
||||
local function date_parse(str)
|
||||
local y,m,d, h,r,s, z, w,u, j, e, x,c, dn,df
|
||||
local sw = newstrwalker(gsub(gsub(str, "(%b())", ""),"^(%s*)","")) -- remove comment, trim leading space
|
||||
--local function error_out() print(y,m,d,h,r,s) end
|
||||
local function error_dup(q) --[[error_out()]] error("duplicate value: " .. (q or "") .. sw:aimchr()) end
|
||||
local function error_syn(q) --[[error_out()]] error("syntax error: " .. (q or "") .. sw:aimchr()) end
|
||||
local function error_inv(q) --[[error_out()]] error("invalid date: " .. (q or "") .. sw:aimchr()) end
|
||||
local function sety(q) y = y and error_dup() or tonumber(q); end
|
||||
local function setm(q) m = (m or w or j) and error_dup(m or w or j) or tonumber(q) end
|
||||
local function setd(q) d = d and error_dup() or tonumber(q) end
|
||||
local function seth(q) h = h and error_dup() or tonumber(q) end
|
||||
local function setr(q) r = r and error_dup() or tonumber(q) end
|
||||
local function sets(q) s = s and error_dup() or tonumber(q) end
|
||||
local function adds(q) s = s + tonumber(q) end
|
||||
local function setj(q) j = (m or w or j) and error_dup() or tonumber(q); end
|
||||
local function setz(q) z = (z ~= 0 and z) and error_dup() or q end
|
||||
local function setzn(zs,zn) zn = tonumber(zn); setz( ((zn<24) and (zn*60) or (mod(zn,100) + floor(zn/100) * 60))*( zs=='+' and -1 or 1) ) end
|
||||
local function setzc(zs,zh,zm) setz( ((tonumber(zh)*60) + tonumber(zm))*( zs=='+' and -1 or 1) ) end
|
||||
|
||||
if not (sw("^(%d%d%d%d)",sety) and (sw("^(%-?)(%d%d)%1(%d%d)",function(_,a,b) setm(tonumber(a)); setd(tonumber(b)) end) or sw("^(%-?)[Ww](%d%d)%1(%d?)",function(_,a,b) w, u = tonumber(a), tonumber(b or 1) end) or sw("^%-?(%d%d%d)",setj) or sw("^%-?(%d%d)",function(a) setm(a);setd(1) end))
|
||||
and ((sw("^%s*[Tt]?(%d%d):?",seth) and sw("^(%d%d):?",setr) and sw("^(%d%d)",sets) and sw("^(%.%d+)",adds))
|
||||
or sw:finish() or (sw"^%s*$" or sw"^%s*[Zz]%s*$" or sw("^%s-([%+%-])(%d%d):?(%d%d)%s*$",setzc) or sw("^%s*([%+%-])(%d%d)%s*$",setzn))
|
||||
) )
|
||||
then --print(y,m,d,h,r,s,z,w,u,j)
|
||||
sw:restart(); y,m,d,h,r,s,z,w,u,j = nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
|
||||
repeat -- print(sw:aimchr())
|
||||
if sw("^[tT:]?%s*(%d%d?):",seth) then --print("$Time")
|
||||
_ = sw("^%s*(%d%d?)",setr) and sw("^%s*:%s*(%d%d?)",sets) and sw("^(%.%d+)",adds)
|
||||
elseif sw("^(%d+)[/\\%s,-]?%s*") then --print("$Digits")
|
||||
x, c = tonumber(sw[1]), len(sw[1])
|
||||
if (x >= 70) or (m and d and (not y)) or (c > 3) then
|
||||
sety( x + ((x >= 100 or c>3) and 0 or x<centuryflip and 2000 or 1900) )
|
||||
else
|
||||
if m then setd(x) else m = x end
|
||||
end
|
||||
elseif sw("^(%a+)[/\\%s,-]?%s*") then --print("$Words")
|
||||
x = sw[1]
|
||||
if inlist(x, sl_months, 2, sw) then
|
||||
if m and (not d) and (not y) then d, m = m, false end
|
||||
setm(mod(sw[0],12)+1)
|
||||
elseif inlist(x, sl_timezone, 2, sw) then
|
||||
c = fix(sw[0]) -- ignore gmt and utc
|
||||
if c ~= 0 then setz(c, x) end
|
||||
elseif not inlist(x, sl_weekdays, 2, sw) then
|
||||
sw:back()
|
||||
-- am pm bce ad ce bc
|
||||
if sw("^([bB])%s*(%.?)%s*[Cc]%s*(%2)%s*[Ee]%s*(%2)%s*") or sw("^([bB])%s*(%.?)%s*[Cc]%s*(%2)%s*") then
|
||||
e = e and error_dup() or -1
|
||||
elseif sw("^([aA])%s*(%.?)%s*[Dd]%s*(%2)%s*") or sw("^([cC])%s*(%.?)%s*[Ee]%s*(%2)%s*") then
|
||||
e = e and error_dup() or 1
|
||||
elseif sw("^([PApa])%s*(%.?)%s*[Mm]?%s*(%2)%s*") then
|
||||
x = lwr(sw[1]) -- there should be hour and it must be correct
|
||||
if (not h) or (h > 12) or (h < 0) then return error_inv() end
|
||||
if x == 'a' and h == 12 then h = 0 end -- am
|
||||
if x == 'p' and h ~= 12 then h = h + 12 end -- pm
|
||||
else error_syn() end
|
||||
end
|
||||
elseif not(sw("^([+-])(%d%d?):(%d%d)",setzc) or sw("^([+-])(%d+)",setzn) or sw("^[Zz]%s*$")) then -- sw{"([+-])",{"(%d%d?):(%d%d)","(%d+)"}}
|
||||
error_syn("?")
|
||||
end
|
||||
sw("^%s*") until sw:finish()
|
||||
--else print("$Iso(Date|Time|Zone)")
|
||||
end
|
||||
-- if date is given, it must be complete year, month & day
|
||||
if (not y and not h) or ((m and not d) or (d and not m)) or ((m and w) or (m and j) or (j and w)) then return error_inv("!") end
|
||||
-- fix month
|
||||
if m then m = m - 1 end
|
||||
-- fix year if we are on BCE
|
||||
if e and e < 0 and y > 0 then y = 1 - y end
|
||||
-- create date object
|
||||
dn = (y and ((w and makedaynum_isoywd(y,w,u)) or (j and makedaynum(y, 0, j)) or makedaynum(y, m, d))) or DAYNUM_DEF
|
||||
df = makedayfrc(h or 0, r or 0, s or 0, 0) + ((z or 0)*TICKSPERMIN)
|
||||
--print("Zone",h,r,s,z,m,d,y,df)
|
||||
return date_new(dn, df) -- no need to :normalize();
|
||||
end
|
||||
local function date_fromtable(v)
|
||||
local y, m, d = fix(v.year), getmontharg(v.month), fix(v.day)
|
||||
local h, r, s, t = tonumber(v.hour), tonumber(v.min), tonumber(v.sec), tonumber(v.ticks)
|
||||
-- atleast there is time or complete date
|
||||
if (y or m or d) and (not(y and m and d)) then return error("incomplete table") end
|
||||
return (y or h or r or s or t) and date_new(y and makedaynum(y, m, d) or DAYNUM_DEF, makedayfrc(h or 0, r or 0, s or 0, t or 0))
|
||||
end
|
||||
local tmap = {
|
||||
['number'] = function(v) return date_epoch:copy():addseconds(v) end,
|
||||
['string'] = function(v) return date_parse(v) end,
|
||||
['boolean']= function(v) return date_fromtable(osdate(v and "!*t" or "*t")) end,
|
||||
['table'] = function(v) local ref = getmetatable(v) == dobj; return ref and v or date_fromtable(v), ref end
|
||||
}
|
||||
local function date_getdobj(v)
|
||||
local o, r = (tmap[type(v)] or fnil)(v);
|
||||
return (o and o:normalize() or error"invalid date time value"), r -- if r is true then o is a reference to a date obj
|
||||
end
|
||||
--#end -- not DATE_OBJECT_AFX
|
||||
local function date_from(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
||||
local y, m, d = fix(arg1), getmontharg(arg2), fix(arg3)
|
||||
local h, r, s, t = tonumber(arg4 or 0), tonumber(arg5 or 0), tonumber(arg6 or 0), tonumber(arg7 or 0)
|
||||
if y and m and d and h and r and s and t then
|
||||
return date_new(makedaynum(y, m, d), makedayfrc(h, r, s, t)):normalize()
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
|
||||
--[[ THE DATE OBJECT METHODS ]]--
|
||||
function dobj:normalize()
|
||||
local dn, df = fix(self.daynum), self.dayfrc
|
||||
self.daynum, self.dayfrc = dn + floor(df/TICKSPERDAY), mod(df, TICKSPERDAY)
|
||||
return (dn >= DAYNUM_MIN and dn <= DAYNUM_MAX) and self or error("date beyond imposed limits:"..self)
|
||||
end
|
||||
|
||||
function dobj:getdate() local y, m, d = breakdaynum(self.daynum) return y, m+1, d end
|
||||
function dobj:gettime() return breakdayfrc(self.dayfrc) end
|
||||
|
||||
function dobj:getclockhour() local h = self:gethours() return h>12 and mod(h,12) or (h==0 and 12 or h) end
|
||||
|
||||
function dobj:getyearday() return yearday(self.daynum) + 1 end
|
||||
function dobj:getweekday() return weekday(self.daynum) + 1 end -- in lua weekday is sunday = 1, monday = 2 ...
|
||||
|
||||
function dobj:getyear() local r,_,_ = breakdaynum(self.daynum) return r end
|
||||
function dobj:getmonth() local _,r,_ = breakdaynum(self.daynum) return r+1 end-- in lua month is 1 base
|
||||
function dobj:getday() local _,_,r = breakdaynum(self.daynum) return r end
|
||||
function dobj:gethours() return mod(floor(self.dayfrc/TICKSPERHOUR),HOURPERDAY) end
|
||||
function dobj:getminutes() return mod(floor(self.dayfrc/TICKSPERMIN), MINPERHOUR) end
|
||||
function dobj:getseconds() return mod(floor(self.dayfrc/TICKSPERSEC ),SECPERMIN) end
|
||||
function dobj:getfracsec() return mod(floor(self.dayfrc/TICKSPERSEC ),SECPERMIN)+(mod(self.dayfrc,TICKSPERSEC)/TICKSPERSEC) end
|
||||
function dobj:getticks(u) local x = mod(self.dayfrc,TICKSPERSEC) return u and ((x*u)/TICKSPERSEC) or x end
|
||||
|
||||
function dobj:getweeknumber(wdb)
|
||||
local wd, yd = weekday(self.daynum), yearday(self.daynum)
|
||||
if wdb then
|
||||
wdb = tonumber(wdb)
|
||||
if wdb then
|
||||
wd = mod(wd-(wdb-1),7)-- shift the week day base
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
return (yd < wd and 0) or (floor(yd/7) + ((mod(yd, 7)>=wd) and 1 or 0))
|
||||
end
|
||||
|
||||
function dobj:getisoweekday() return mod(weekday(self.daynum)-1,7)+1 end -- sunday = 7, monday = 1 ...
|
||||
function dobj:getisoweeknumber() return (isowy(self.daynum)) end
|
||||
function dobj:getisoyear() return isoy(self.daynum) end
|
||||
function dobj:getisodate()
|
||||
local w, y = isowy(self.daynum)
|
||||
return y, w, self:getisoweekday()
|
||||
end
|
||||
function dobj:setisoyear(y, w, d)
|
||||
local cy, cw, cd = self:getisodate()
|
||||
if y then cy = fix(tonumber(y))end
|
||||
if w then cw = fix(tonumber(w))end
|
||||
if d then cd = fix(tonumber(d))end
|
||||
if cy and cw and cd then
|
||||
self.daynum = makedaynum_isoywd(cy, cw, cd)
|
||||
return self:normalize()
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
|
||||
function dobj:setisoweekday(d) return self:setisoyear(nil, nil, d) end
|
||||
function dobj:setisoweeknumber(w,d) return self:setisoyear(nil, w, d) end
|
||||
|
||||
function dobj:setyear(y, m, d)
|
||||
local cy, cm, cd = breakdaynum(self.daynum)
|
||||
if y then cy = fix(tonumber(y))end
|
||||
if m then cm = getmontharg(m) end
|
||||
if d then cd = fix(tonumber(d))end
|
||||
if cy and cm and cd then
|
||||
self.daynum = makedaynum(cy, cm, cd)
|
||||
return self:normalize()
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
|
||||
function dobj:setmonth(m, d)return self:setyear(nil, m, d) end
|
||||
function dobj:setday(d) return self:setyear(nil, nil, d) end
|
||||
|
||||
function dobj:sethours(h, m, s, t)
|
||||
local ch,cm,cs,ck = breakdayfrc(self.dayfrc)
|
||||
ch, cm, cs, ck = tonumber(h or ch), tonumber(m or cm), tonumber(s or cs), tonumber(t or ck)
|
||||
if ch and cm and cs and ck then
|
||||
self.dayfrc = makedayfrc(ch, cm, cs, ck)
|
||||
return self:normalize()
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
|
||||
function dobj:setminutes(m,s,t) return self:sethours(nil, m, s, t) end
|
||||
function dobj:setseconds(s, t) return self:sethours(nil, nil, s, t) end
|
||||
function dobj:setticks(t) return self:sethours(nil, nil, nil, t) end
|
||||
|
||||
function dobj:spanticks() return (self.daynum*TICKSPERDAY + self.dayfrc) end
|
||||
function dobj:spanseconds() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERSEC end
|
||||
function dobj:spanminutes() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERMIN end
|
||||
function dobj:spanhours() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERHOUR end
|
||||
function dobj:spandays() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERDAY end
|
||||
|
||||
function dobj:addyears(y, m, d)
|
||||
local cy, cm, cd = breakdaynum(self.daynum)
|
||||
if y then y = fix(tonumber(y))else y = 0 end
|
||||
if m then m = fix(tonumber(m))else m = 0 end
|
||||
if d then d = fix(tonumber(d))else d = 0 end
|
||||
if y and m and d then
|
||||
self.daynum = makedaynum(cy+y, cm+m, cd+d)
|
||||
return self:normalize()
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
|
||||
function dobj:addmonths(m, d)
|
||||
return self:addyears(nil, m, d)
|
||||
end
|
||||
|
||||
local function dobj_adddayfrc(self,n,pt,pd)
|
||||
n = tonumber(n)
|
||||
if n then
|
||||
local x = floor(n/pd);
|
||||
self.daynum = self.daynum + x;
|
||||
self.dayfrc = self.dayfrc + (n-x*pd)*pt;
|
||||
return self:normalize()
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
function dobj:adddays(n) return dobj_adddayfrc(self,n,TICKSPERDAY,1) end
|
||||
function dobj:addhours(n) return dobj_adddayfrc(self,n,TICKSPERHOUR,HOURPERDAY) end
|
||||
function dobj:addminutes(n) return dobj_adddayfrc(self,n,TICKSPERMIN,MINPERDAY) end
|
||||
function dobj:addseconds(n) return dobj_adddayfrc(self,n,TICKSPERSEC,SECPERDAY) end
|
||||
function dobj:addticks(n) return dobj_adddayfrc(self,n,1,TICKSPERDAY) end
|
||||
local tvspec = {
|
||||
-- Abbreviated weekday name (Sun)
|
||||
['%a']=function(self) return sl_weekdays[weekday(self.daynum) + 7] end,
|
||||
-- Full weekday name (Sunday)
|
||||
['%A']=function(self) return sl_weekdays[weekday(self.daynum)] end,
|
||||
-- Abbreviated month name (Dec)
|
||||
['%b']=function(self) return sl_months[self:getmonth() - 1 + 12] end,
|
||||
-- Full month name (December)
|
||||
['%B']=function(self) return sl_months[self:getmonth() - 1] end,
|
||||
-- Year/100 (19, 20, 30)
|
||||
['%C']=function(self) return fmt("%.2d", fix(self:getyear()/100)) end,
|
||||
-- The day of the month as a number (range 1 - 31)
|
||||
['%d']=function(self) return fmt("%.2d", self:getday()) end,
|
||||
-- year for ISO 8601 week, from 00 (79)
|
||||
['%g']=function(self) return fmt("%.2d", mod(self:getisoyear() ,100)) end,
|
||||
-- year for ISO 8601 week, from 0000 (1979)
|
||||
['%G']=function(self) return fmt("%.4d", self:getisoyear()) end,
|
||||
-- same as %b
|
||||
['%h']=function(self) return self:fmt0("%b") end,
|
||||
-- hour of the 24-hour day, from 00 (06)
|
||||
['%H']=function(self) return fmt("%.2d", self:gethours()) end,
|
||||
-- The hour as a number using a 12-hour clock (01 - 12)
|
||||
['%I']=function(self) return fmt("%.2d", self:getclockhour()) end,
|
||||
-- The day of the year as a number (001 - 366)
|
||||
['%j']=function(self) return fmt("%.3d", self:getyearday()) end,
|
||||
-- Month of the year, from 01 to 12
|
||||
['%m']=function(self) return fmt("%.2d", self:getmonth()) end,
|
||||
-- Minutes after the hour 55
|
||||
['%M']=function(self) return fmt("%.2d", self:getminutes())end,
|
||||
-- AM/PM indicator (AM)
|
||||
['%p']=function(self) return sl_meridian[self:gethours() > 11 and 1 or -1] end, --AM/PM indicator (AM)
|
||||
-- The second as a number (59, 20 , 01)
|
||||
['%S']=function(self) return fmt("%.2d", self:getseconds()) end,
|
||||
-- ISO 8601 day of the week, to 7 for Sunday (7, 1)
|
||||
['%u']=function(self) return self:getisoweekday() end,
|
||||
-- Sunday week of the year, from 00 (48)
|
||||
['%U']=function(self) return fmt("%.2d", self:getweeknumber()) end,
|
||||
-- ISO 8601 week of the year, from 01 (48)
|
||||
['%V']=function(self) return fmt("%.2d", self:getisoweeknumber()) end,
|
||||
-- The day of the week as a decimal, Sunday being 0
|
||||
['%w']=function(self) return self:getweekday() - 1 end,
|
||||
-- Monday week of the year, from 00 (48)
|
||||
['%W']=function(self) return fmt("%.2d", self:getweeknumber(2)) end,
|
||||
-- The year as a number without a century (range 00 to 99)
|
||||
['%y']=function(self) return fmt("%.2d", mod(self:getyear() ,100)) end,
|
||||
-- Year with century (2000, 1914, 0325, 0001)
|
||||
['%Y']=function(self) return fmt("%.4d", self:getyear()) end,
|
||||
-- Time zone offset, the date object is assumed local time (+1000, -0230)
|
||||
['%z']=function(self) local b = -self:getbias(); local x = abs(b); return fmt("%s%.4d", b < 0 and "-" or "+", fix(x/60)*100 + floor(mod(x,60))) end,
|
||||
-- Time zone name, the date object is assumed local time
|
||||
['%Z']=function(self) return self:gettzname() end,
|
||||
-- Misc --
|
||||
-- Year, if year is in BCE, prints the BCE Year representation, otherwise result is similar to "%Y" (1 BCE, 40 BCE)
|
||||
['%\b']=function(self) local x = self:getyear() return fmt("%.4d%s", x>0 and x or (-x+1), x>0 and "" or " BCE") end,
|
||||
-- Seconds including fraction (59.998, 01.123)
|
||||
['%\f']=function(self) local x = self:getfracsec() return fmt("%s%.9f",x >= 10 and "" or "0", x) end,
|
||||
-- percent character %
|
||||
['%%']=function(self) return "%" end,
|
||||
-- Group Spec --
|
||||
-- 12-hour time, from 01:00:00 AM (06:55:15 AM); same as "%I:%M:%S %p"
|
||||
['%r']=function(self) return self:fmt0("%I:%M:%S %p") end,
|
||||
-- hour:minute, from 01:00 (06:55); same as "%I:%M"
|
||||
['%R']=function(self) return self:fmt0("%I:%M") end,
|
||||
-- 24-hour time, from 00:00:00 (06:55:15); same as "%H:%M:%S"
|
||||
['%T']=function(self) return self:fmt0("%H:%M:%S") end,
|
||||
-- month/day/year from 01/01/00 (12/02/79); same as "%m/%d/%y"
|
||||
['%D']=function(self) return self:fmt0("%m/%d/%y") end,
|
||||
-- year-month-day (1979-12-02); same as "%Y-%m-%d"
|
||||
['%F']=function(self) return self:fmt0("%Y-%m-%d") end,
|
||||
-- The preferred date and time representation; same as "%x %X"
|
||||
['%c']=function(self) return self:fmt0("%x %X") end,
|
||||
-- The preferred date representation, same as "%a %b %d %\b"
|
||||
['%x']=function(self) return self:fmt0("%a %b %d %\b") end,
|
||||
-- The preferred time representation, same as "%H:%M:%\f"
|
||||
['%X']=function(self) return self:fmt0("%H:%M:%\f") end,
|
||||
-- GroupSpec --
|
||||
-- Iso format, same as "%Y-%m-%dT%T"
|
||||
['${iso}'] = function(self) return self:fmt0("%Y-%m-%dT%T") end,
|
||||
-- http format, same as "%a, %d %b %Y %T GMT"
|
||||
['${http}'] = function(self) return self:fmt0("%a, %d %b %Y %T GMT") end,
|
||||
-- ctime format, same as "%a %b %d %T GMT %Y"
|
||||
['${ctime}'] = function(self) return self:fmt0("%a %b %d %T GMT %Y") end,
|
||||
-- RFC850 format, same as "%A, %d-%b-%y %T GMT"
|
||||
['${rfc850}'] = function(self) return self:fmt0("%A, %d-%b-%y %T GMT") end,
|
||||
-- RFC1123 format, same as "%a, %d %b %Y %T GMT"
|
||||
['${rfc1123}'] = function(self) return self:fmt0("%a, %d %b %Y %T GMT") end,
|
||||
-- asctime format, same as "%a %b %d %T %Y"
|
||||
['${asctime}'] = function(self) return self:fmt0("%a %b %d %T %Y") end,
|
||||
}
|
||||
function dobj:fmt0(str) return (gsub(str, "%%[%a%%\b\f]", function(x) local f = tvspec[x];return (f and f(self)) or x end)) end
|
||||
function dobj:fmt(str)
|
||||
str = str or self.fmtstr or fmtstr
|
||||
return self:fmt0((gmatch(str, "${%w+}")) and (gsub(str, "${%w+}", function(x)local f=tvspec[x];return (f and f(self)) or x end)) or str)
|
||||
end
|
||||
|
||||
function dobj.__lt(a, b) if (a.daynum == b.daynum) then return (a.dayfrc < b.dayfrc) else return (a.daynum < b.daynum) end end
|
||||
function dobj.__le(a, b) if (a.daynum == b.daynum) then return (a.dayfrc <= b.dayfrc) else return (a.daynum <= b.daynum) end end
|
||||
function dobj.__eq(a, b)return (a.daynum == b.daynum) and (a.dayfrc == b.dayfrc) end
|
||||
function dobj.__sub(a,b)
|
||||
local d1, d2 = date_getdobj(a), date_getdobj(b)
|
||||
local d0 = d1 and d2 and date_new(d1.daynum - d2.daynum, d1.dayfrc - d2.dayfrc)
|
||||
return d0 and d0:normalize()
|
||||
end
|
||||
function dobj.__add(a,b)
|
||||
local d1, d2 = date_getdobj(a), date_getdobj(b)
|
||||
local d0 = d1 and d2 and date_new(d1.daynum + d2.daynum, d1.dayfrc + d2.dayfrc)
|
||||
return d0 and d0:normalize()
|
||||
end
|
||||
function dobj.__concat(a, b) return tostring(a) .. tostring(b) end
|
||||
function dobj:__tostring() return self:fmt() end
|
||||
|
||||
function dobj:copy() return date_new(self.daynum, self.dayfrc) end
|
||||
|
||||
|
||||
function dobj:setbias(bias)
|
||||
self.bias = bias
|
||||
return self
|
||||
end
|
||||
|
||||
--[[ THE LOCAL DATE OBJECT METHODS ]]--
|
||||
function dobj:tolocal()
|
||||
local dn,df = self.daynum, self.dayfrc
|
||||
bias = self.bias or getbiasutc2(self)
|
||||
if bias != nil then
|
||||
-- utc = local + bias; local = utc - bias
|
||||
self.daynum = dn
|
||||
self.dayfrc = df - bias*TICKSPERSEC
|
||||
return self:normalize()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dobj:toutc()
|
||||
local dn,df = self.daynum, self.dayfrc
|
||||
local bias = self.bias or getbiasloc2(dn, df)
|
||||
if bias then
|
||||
-- utc = local + bias;
|
||||
self.daynum = dn
|
||||
self.dayfrc = df + bias*TICKSPERSEC
|
||||
return self:normalize()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dobj:getbias() return self.bias != nil and self.bias/SECPERMIN or (getbiasloc2(self.daynum, self.dayfrc))/SECPERMIN end
|
||||
|
||||
function dobj:gettzname()
|
||||
if self.bias != nil then return "" end
|
||||
|
||||
local _, tvu, _ = getbiasloc2(self.daynum, self.dayfrc)
|
||||
return tvu and osdate("%Z",tvu) or ""
|
||||
end
|
||||
|
||||
--#if not DATE_OBJECT_AFX then
|
||||
function date.time(h, r, s, t)
|
||||
h, r, s, t = tonumber(h or 0), tonumber(r or 0), tonumber(s or 0), tonumber(t or 0)
|
||||
if h and r and s and t then
|
||||
return date_new(DAYNUM_DEF, makedayfrc(h, r, s, t))
|
||||
else
|
||||
return date_error_arg()
|
||||
end
|
||||
end
|
||||
|
||||
function date:__call(arg1, ...)
|
||||
local arg_count = select("#", ...) + (arg1 == nil and 0 or 1)
|
||||
if arg_count > 1 then return (date_from(arg1, ...))
|
||||
elseif arg_count == 0 then return (date_getdobj(false))
|
||||
else local o, r = date_getdobj(arg1); return r and o:copy() or o end
|
||||
end
|
||||
|
||||
date.diff = dobj.__sub
|
||||
|
||||
function date.isleapyear(v)
|
||||
local y = fix(v);
|
||||
if not y then
|
||||
y = date_getdobj(v)
|
||||
y = y and y:getyear()
|
||||
end
|
||||
return isleapyear(y+0)
|
||||
end
|
||||
|
||||
function date.epoch() return date_epoch:copy() end
|
||||
|
||||
function date.isodate(y,w,d) return date_new(makedaynum_isoywd(y + 0, w and (w+0) or 1, d and (d+0) or 1), 0) end
|
||||
function date.setcenturyflip(y)
|
||||
if y ~= floor(y) or y < 0 or y > 100 then date_error_arg() end
|
||||
centuryflip = y
|
||||
end
|
||||
function date.getcenturyflip() return centuryflip end
|
||||
|
||||
-- Internal functions
|
||||
function date.fmt(str) if str then fmtstr = str end; return fmtstr end
|
||||
function date.daynummin(n) DAYNUM_MIN = (n and n < DAYNUM_MAX) and n or DAYNUM_MIN return n and DAYNUM_MIN or date_new(DAYNUM_MIN, 0):normalize()end
|
||||
function date.daynummax(n) DAYNUM_MAX = (n and n > DAYNUM_MIN) and n or DAYNUM_MAX return n and DAYNUM_MAX or date_new(DAYNUM_MAX, 0):normalize()end
|
||||
function date.ticks(t) if t then setticks(t) end return TICKSPERSEC end
|
||||
--#end -- not DATE_OBJECT_AFX
|
||||
|
||||
local tm = osdate("!*t", 0);
|
||||
if tm then
|
||||
date_epoch = date_new(makedaynum(tm.year, tm.month - 1, tm.day), makedayfrc(tm.hour, tm.min, tm.sec, 0))
|
||||
-- the distance from our epoch to os epoch in daynum
|
||||
DATE_EPOCH = date_epoch and date_epoch:spandays()
|
||||
else -- error will be raise only if called!
|
||||
date_epoch = setmetatable({},{__index = function() error("failed to get the epoch date") end})
|
||||
end
|
||||
|
||||
--#if not DATE_OBJECT_AFX then
|
||||
VyHub.Lib.date = date
|
||||
--#else
|
||||
--$return date_from
|
||||
--#end
|
||||
|
||||
399
addons/vyhub-gmod/lua/vyhub/lib/json.lua
Normal file
399
addons/vyhub-gmod/lua/vyhub/lib/json.lua
Normal file
@@ -0,0 +1,399 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
VyHub.Lib.json = VyHub.Lib.json or {}
|
||||
|
||||
--
|
||||
-- json.lua
|
||||
--
|
||||
-- Copyright (c) 2020 rxi
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in
|
||||
-- the Software without restriction, including without limitation the rights to
|
||||
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
-- of the Software, and to permit persons to whom the Software is furnished to do
|
||||
-- so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all
|
||||
-- copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
-- SOFTWARE.
|
||||
--
|
||||
|
||||
local json = { _version = "0.1.2" }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Encode
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local encode
|
||||
|
||||
local escape_char_map = {
|
||||
[ "\\" ] = "\\",
|
||||
[ "\"" ] = "\"",
|
||||
[ "\b" ] = "b",
|
||||
[ "\f" ] = "f",
|
||||
[ "\n" ] = "n",
|
||||
[ "\r" ] = "r",
|
||||
[ "\t" ] = "t",
|
||||
}
|
||||
|
||||
local escape_char_map_inv = { [ "/" ] = "/" }
|
||||
for k, v in pairs(escape_char_map) do
|
||||
escape_char_map_inv[v] = k
|
||||
end
|
||||
|
||||
|
||||
local function escape_char(c)
|
||||
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
|
||||
end
|
||||
|
||||
|
||||
local function encode_nil(val)
|
||||
return "null"
|
||||
end
|
||||
|
||||
|
||||
local function encode_table(val, stack)
|
||||
local res = {}
|
||||
stack = stack or {}
|
||||
|
||||
-- Circular reference?
|
||||
if stack[val] then error("circular reference") end
|
||||
|
||||
stack[val] = true
|
||||
|
||||
if rawget(val, 1) ~= nil or next(val) == nil then
|
||||
-- Treat as array -- check keys are valid and it is not sparse
|
||||
local n = 0
|
||||
for k in pairs(val) do
|
||||
if type(k) ~= "number" then
|
||||
error("invalid table: mixed or invalid key types")
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if n ~= #val then
|
||||
error("invalid table: sparse array")
|
||||
end
|
||||
-- Encode
|
||||
for i, v in ipairs(val) do
|
||||
table.insert(res, encode(v, stack))
|
||||
end
|
||||
stack[val] = nil
|
||||
return "[" .. table.concat(res, ",") .. "]"
|
||||
|
||||
else
|
||||
-- Treat as an object
|
||||
for k, v in pairs(val) do
|
||||
if type(k) ~= "string" then
|
||||
error("invalid table: mixed or invalid key types")
|
||||
end
|
||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
||||
end
|
||||
stack[val] = nil
|
||||
return "{" .. table.concat(res, ",") .. "}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function encode_string(val)
|
||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
||||
end
|
||||
|
||||
|
||||
local function encode_number(val)
|
||||
-- Check for NaN, -inf and inf
|
||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
||||
error("unexpected number value '" .. tostring(val) .. "'")
|
||||
end
|
||||
return string.format("%.14g", val)
|
||||
end
|
||||
|
||||
|
||||
local type_func_map = {
|
||||
[ "nil" ] = encode_nil,
|
||||
[ "table" ] = encode_table,
|
||||
[ "string" ] = encode_string,
|
||||
[ "number" ] = encode_number,
|
||||
[ "boolean" ] = tostring,
|
||||
}
|
||||
|
||||
|
||||
encode = function(val, stack)
|
||||
local t = type(val)
|
||||
local f = type_func_map[t]
|
||||
if f then
|
||||
return f(val, stack)
|
||||
end
|
||||
error("unexpected type '" .. t .. "'")
|
||||
end
|
||||
|
||||
|
||||
function json.encode(val)
|
||||
return ( encode(val) )
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Decode
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local parse
|
||||
|
||||
local function create_set(...)
|
||||
local res = {}
|
||||
for i = 1, select("#", ...) do
|
||||
res[ select(i, ...) ] = true
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
||||
local literals = create_set("true", "false", "null")
|
||||
|
||||
local literal_map = {
|
||||
[ "true" ] = true,
|
||||
[ "false" ] = false,
|
||||
[ "null" ] = nil,
|
||||
}
|
||||
|
||||
|
||||
local function next_char(str, idx, set, negate)
|
||||
for i = idx, #str do
|
||||
if set[str:sub(i, i)] ~= negate then
|
||||
return i
|
||||
end
|
||||
end
|
||||
return #str + 1
|
||||
end
|
||||
|
||||
|
||||
local function decode_error(str, idx, msg)
|
||||
local line_count = 1
|
||||
local col_count = 1
|
||||
for i = 1, idx - 1 do
|
||||
col_count = col_count + 1
|
||||
if str:sub(i, i) == "\n" then
|
||||
line_count = line_count + 1
|
||||
col_count = 1
|
||||
end
|
||||
end
|
||||
error( string.format("%s at line %d col %d", msg, line_count, col_count) )
|
||||
end
|
||||
|
||||
|
||||
local function codepoint_to_utf8(n)
|
||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
||||
local f = math.floor
|
||||
if n <= 0x7f then
|
||||
return string.char(n)
|
||||
elseif n <= 0x7ff then
|
||||
return string.char(f(n / 64) + 192, n % 64 + 128)
|
||||
elseif n <= 0xffff then
|
||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||
elseif n <= 0x10ffff then
|
||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
||||
f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||
end
|
||||
error( string.format("invalid unicode codepoint '%x'", n) )
|
||||
end
|
||||
|
||||
|
||||
local function parse_unicode_escape(s)
|
||||
local n1 = tonumber( s:sub(1, 4), 16 )
|
||||
local n2 = tonumber( s:sub(7, 10), 16 )
|
||||
-- Surrogate pair?
|
||||
if n2 then
|
||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
||||
else
|
||||
return codepoint_to_utf8(n1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function parse_string(str, i)
|
||||
local res = ""
|
||||
local j = i + 1
|
||||
local k = j
|
||||
|
||||
while j <= #str do
|
||||
local x = str:byte(j)
|
||||
|
||||
if x < 32 then
|
||||
decode_error(str, j, "control character in string")
|
||||
|
||||
elseif x == 92 then -- `\`: Escape
|
||||
res = res .. str:sub(k, j - 1)
|
||||
j = j + 1
|
||||
local c = str:sub(j, j)
|
||||
if c == "u" then
|
||||
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
|
||||
or str:match("^%x%x%x%x", j + 1)
|
||||
or decode_error(str, j - 1, "invalid unicode escape in string")
|
||||
res = res .. parse_unicode_escape(hex)
|
||||
j = j + #hex
|
||||
else
|
||||
if not escape_chars[c] then
|
||||
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
|
||||
end
|
||||
res = res .. escape_char_map_inv[c]
|
||||
end
|
||||
k = j + 1
|
||||
|
||||
elseif x == 34 then -- `"`: End of string
|
||||
res = res .. str:sub(k, j - 1)
|
||||
return res, j + 1
|
||||
end
|
||||
|
||||
j = j + 1
|
||||
end
|
||||
|
||||
decode_error(str, i, "expected closing quote for string")
|
||||
end
|
||||
|
||||
|
||||
local function parse_number(str, i)
|
||||
local x = next_char(str, i, delim_chars)
|
||||
local s = str:sub(i, x - 1)
|
||||
local n = tonumber(s)
|
||||
if not n then
|
||||
decode_error(str, i, "invalid number '" .. s .. "'")
|
||||
end
|
||||
return n, x
|
||||
end
|
||||
|
||||
|
||||
local function parse_literal(str, i)
|
||||
local x = next_char(str, i, delim_chars)
|
||||
local word = str:sub(i, x - 1)
|
||||
if not literals[word] then
|
||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
||||
end
|
||||
return literal_map[word], x
|
||||
end
|
||||
|
||||
|
||||
local function parse_array(str, i)
|
||||
local res = {}
|
||||
local n = 1
|
||||
i = i + 1
|
||||
while 1 do
|
||||
local x
|
||||
i = next_char(str, i, space_chars, true)
|
||||
-- Empty / end of array?
|
||||
if str:sub(i, i) == "]" then
|
||||
i = i + 1
|
||||
break
|
||||
end
|
||||
-- Read token
|
||||
x, i = parse(str, i)
|
||||
res[n] = x
|
||||
n = n + 1
|
||||
-- Next token
|
||||
i = next_char(str, i, space_chars, true)
|
||||
local chr = str:sub(i, i)
|
||||
i = i + 1
|
||||
if chr == "]" then break end
|
||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
||||
end
|
||||
return res, i
|
||||
end
|
||||
|
||||
|
||||
local function parse_object(str, i)
|
||||
local res = {}
|
||||
i = i + 1
|
||||
while 1 do
|
||||
local key, val
|
||||
i = next_char(str, i, space_chars, true)
|
||||
-- Empty / end of object?
|
||||
if str:sub(i, i) == "}" then
|
||||
i = i + 1
|
||||
break
|
||||
end
|
||||
-- Read key
|
||||
if str:sub(i, i) ~= '"' then
|
||||
decode_error(str, i, "expected string for key")
|
||||
end
|
||||
key, i = parse(str, i)
|
||||
-- Read ':' delimiter
|
||||
i = next_char(str, i, space_chars, true)
|
||||
if str:sub(i, i) ~= ":" then
|
||||
decode_error(str, i, "expected ':' after key")
|
||||
end
|
||||
i = next_char(str, i + 1, space_chars, true)
|
||||
-- Read value
|
||||
val, i = parse(str, i)
|
||||
-- Set
|
||||
res[key] = val
|
||||
-- Next token
|
||||
i = next_char(str, i, space_chars, true)
|
||||
local chr = str:sub(i, i)
|
||||
i = i + 1
|
||||
if chr == "}" then break end
|
||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
||||
end
|
||||
return res, i
|
||||
end
|
||||
|
||||
|
||||
local char_func_map = {
|
||||
[ '"' ] = parse_string,
|
||||
[ "0" ] = parse_number,
|
||||
[ "1" ] = parse_number,
|
||||
[ "2" ] = parse_number,
|
||||
[ "3" ] = parse_number,
|
||||
[ "4" ] = parse_number,
|
||||
[ "5" ] = parse_number,
|
||||
[ "6" ] = parse_number,
|
||||
[ "7" ] = parse_number,
|
||||
[ "8" ] = parse_number,
|
||||
[ "9" ] = parse_number,
|
||||
[ "-" ] = parse_number,
|
||||
[ "t" ] = parse_literal,
|
||||
[ "f" ] = parse_literal,
|
||||
[ "n" ] = parse_literal,
|
||||
[ "[" ] = parse_array,
|
||||
[ "{" ] = parse_object,
|
||||
}
|
||||
|
||||
|
||||
parse = function(str, idx)
|
||||
local chr = str:sub(idx, idx)
|
||||
local f = char_func_map[chr]
|
||||
if f then
|
||||
return f(str, idx)
|
||||
end
|
||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
||||
end
|
||||
|
||||
|
||||
function json.decode(str)
|
||||
if type(str) ~= "string" then
|
||||
error("expected argument of type string, got " .. type(str))
|
||||
end
|
||||
local res, idx = parse(str, next_char(str, 1, space_chars, true))
|
||||
idx = next_char(str, idx, space_chars, true)
|
||||
if idx <= #str then
|
||||
decode_error(str, idx, "trailing garbage")
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
VyHub.Lib.json = json
|
||||
57
addons/vyhub-gmod/lua/vyhub/server/sv_advert.lua
Normal file
57
addons/vyhub-gmod/lua/vyhub/server/sv_advert.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
VyHub.Advert = VyHub.Advert or {}
|
||||
VyHub.adverts = VyHub.adverts or {}
|
||||
|
||||
local current_advert = 0
|
||||
|
||||
function VyHub.Advert:refresh()
|
||||
VyHub.API:get("/advert/", nil, { active = "true", serverbundle_id = VyHub.server.serverbundle.id }, function(code, result)
|
||||
VyHub.adverts = result
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Advert:show(advert)
|
||||
if advert then
|
||||
local lines = string.Explode('\n', advert.content)
|
||||
local color = VyHub.Util:hex2rgb(advert.color)
|
||||
|
||||
local prefix = VyHub.Config.advert_prefix
|
||||
|
||||
for _, line in ipairs(lines) do
|
||||
VyHub.Util:print_chat_all(line, prefix, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Advert:next()
|
||||
current_advert = current_advert + 1;
|
||||
|
||||
local advert = VyHub.adverts[current_advert];
|
||||
|
||||
if advert then
|
||||
VyHub.Advert:show(advert)
|
||||
else
|
||||
current_advert = 0
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_advert_vyhub_ready", function ()
|
||||
VyHub.Advert:refresh()
|
||||
|
||||
timer.Create("vyhub_advert_next", VyHub.Config.advert_interval, 0, function()
|
||||
VyHub.Advert:next()
|
||||
end)
|
||||
|
||||
timer.Create("vyhub_advert_refresh", 300, 0, function ()
|
||||
VyHub.Advert:refresh()
|
||||
end)
|
||||
end)
|
||||
170
addons/vyhub-gmod/lua/vyhub/server/sv_api.lua
Normal file
170
addons/vyhub-gmod/lua/vyhub/server/sv_api.lua
Normal file
@@ -0,0 +1,170 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
VyHub.API = VyHub.API or {}
|
||||
|
||||
local content_type = "application/json; charset=utf-8"
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
function VyHub.API:request(method, url, path_params, query, headers, request_body, type, success, failed, no_error_for)
|
||||
no_error_for = no_error_for or {}
|
||||
|
||||
if path_params != nil then
|
||||
url = f(url, unpack(path_params))
|
||||
end
|
||||
|
||||
if istable(request_body) then
|
||||
request_body = json.encode(request_body)
|
||||
end
|
||||
|
||||
success_func = function(code, body, headers)
|
||||
local result = body
|
||||
|
||||
if headers["Content-Type"] and headers["Content-Type"] == 'application/json' then
|
||||
result = json.decode(body)
|
||||
end
|
||||
|
||||
if code >= 200 and code < 300 then
|
||||
VyHub:msg(f("HTTP %s %s (%s): %s", method, url, json.encode(query), code), "debug")
|
||||
|
||||
if success != nil then
|
||||
-- VyHub:msg(f("Response: %s", body), "debug")
|
||||
|
||||
success(code, result, headers)
|
||||
end
|
||||
else
|
||||
if not table.HasValue(no_error_for, code) then
|
||||
local err_msg = f("HTTP %s %s: %s", method, url, code)
|
||||
|
||||
if query then
|
||||
err_msg = err_msg .. f("\nQuery: %s", json.encode(query))
|
||||
end
|
||||
if request_body then
|
||||
err_msg = err_msg .. f("\nBody: %s", request_body)
|
||||
end
|
||||
|
||||
VyHub:msg(err_msg, "error")
|
||||
|
||||
if code < 500 and string.find( body:lower(), "html>" ) == nil then
|
||||
VyHub:msg(f("Response: %s", body), "error")
|
||||
end
|
||||
end
|
||||
|
||||
if failed != nil then
|
||||
local err_text = json.encode(result)
|
||||
|
||||
if istable(result) and result.detail != nil and result.detail.msg != nil then
|
||||
err_text = f("%s (%s)", result.detail.msg, result.detail.code)
|
||||
end
|
||||
|
||||
failed(code, result, headers, err_text)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
failed_func = function(reason)
|
||||
local err_msg = f("HTTP %s %s: %s", method, url, code)
|
||||
|
||||
if query then
|
||||
err_msg = err_msg .. f("\nQuery: %s", json.encode(query))
|
||||
end
|
||||
if request_body then
|
||||
err_msg = err_msg .. f("\nBody: %s", request_body)
|
||||
end
|
||||
|
||||
VyHub:msg(err_msg, "error")
|
||||
|
||||
if failed != nil then
|
||||
failed(0, reason, {})
|
||||
end
|
||||
end
|
||||
|
||||
HTTP({
|
||||
method = method,
|
||||
url = url,
|
||||
parameters = query,
|
||||
headers = headers,
|
||||
body = request_body,
|
||||
type = type,
|
||||
success = success_func,
|
||||
failed = failed_func,
|
||||
})
|
||||
end
|
||||
|
||||
function VyHub.API:get(endpoint, path_params, query, success, failed, no_error_for)
|
||||
local url = f("%s%s", VyHub.API.url, endpoint)
|
||||
|
||||
VyHub.API:request("GET", url, path_params, query, self.headers, nil, content_type, success, failed, no_error_for)
|
||||
end
|
||||
|
||||
function VyHub.API:delete(endpoint, path_params, success, failed)
|
||||
local url = f("%s%s", VyHub.API.url, endpoint)
|
||||
|
||||
self:request("DELETE", url, path_params, nil, self.headers, nil, content_type, success, failed)
|
||||
end
|
||||
|
||||
function VyHub.API:post(endpoint, path_params, body, success, failed, query)
|
||||
local url = f("%s%s", VyHub.API.url, endpoint)
|
||||
|
||||
self:request("POST", url, path_params, query, self.headers, body, content_type, success, failed)
|
||||
end
|
||||
|
||||
function VyHub.API:patch(endpoint, path_params, body, success, failed)
|
||||
local url = f("%s%s", VyHub.API.url, endpoint)
|
||||
|
||||
self:request("PATCH", url, path_params, nil, self.headers, body, content_type, success, failed)
|
||||
end
|
||||
|
||||
function VyHub.API:put(endpoint, path_params, body, success, failed)
|
||||
local url = f("%s%s", VyHub.API.url, endpoint)
|
||||
|
||||
self:request("PUT", url, path_params, nil, self.headers, body, content_type, success, failed)
|
||||
end
|
||||
|
||||
hook.Add("vyhub_loading_finish", "vyhub_api_vyhub_loading_finish", function()
|
||||
if VyHub.Util:invalid_str({VyHub.Config.api_url, VyHub.Config.api_key, VyHub.Config.server_id}) then
|
||||
VyHub:msg("API URL, Server ID or API Key not set! Please follow the manual.", "error")
|
||||
|
||||
timer.Simple(60, function ()
|
||||
hook.Run("vyhub_loading_finish")
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.API.url = VyHub.Config.api_url
|
||||
VyHub.API.headers = {
|
||||
Authorization = f("Bearer %s", VyHub.Config.api_key)
|
||||
}
|
||||
|
||||
if string.EndsWith(VyHub.API.url, "/") then
|
||||
VyHub.API.url = string.sub(VyHub.API.url, 1, -2)
|
||||
end
|
||||
|
||||
VyHub:msg(f("API URL is %s", VyHub.API.url))
|
||||
|
||||
VyHub.API:get("/openapi.json", nil, nil, function(code, result, headers)
|
||||
VyHub:msg(f("Connection to API %s version %s successful!", result.info.title, result.info.version), "success")
|
||||
|
||||
hook.Run("vyhub_api_ready")
|
||||
end, function()
|
||||
VyHub:msg("Connection to API failed! Trying to use cache.", "error")
|
||||
|
||||
hook.Run("vyhub_api_failed")
|
||||
end)
|
||||
end)
|
||||
|
||||
concommand.Add("vh_reinit", function (ply)
|
||||
if not VyHub.Util:is_server(ply) then return end
|
||||
|
||||
hook.Run("vyhub_loading_finish")
|
||||
end)
|
||||
1018
addons/vyhub-gmod/lua/vyhub/server/sv_ban.lua
Normal file
1018
addons/vyhub-gmod/lua/vyhub/server/sv_ban.lua
Normal file
File diff suppressed because it is too large
Load Diff
58
addons/vyhub-gmod/lua/vyhub/server/sv_cache.lua
Normal file
58
addons/vyhub-gmod/lua/vyhub/server/sv_cache.lua
Normal file
@@ -0,0 +1,58 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
VyHub.Cache = VyHub.Cache or {}
|
||||
|
||||
function VyHub.Cache:save(key, value)
|
||||
local data = {
|
||||
timestamp = os.time(),
|
||||
data = value
|
||||
}
|
||||
|
||||
local filename = f("vyhub/%s.json", key)
|
||||
local json = json.encode(data)
|
||||
|
||||
VyHub:msg("Write " .. filename .. ": " .. json, "debuga")
|
||||
|
||||
file.Write(filename, json)
|
||||
end
|
||||
|
||||
function VyHub.Cache:get(key, max_age)
|
||||
local path = f("vyhub/%s.json", key)
|
||||
|
||||
if not file.Exists(path, "data") then
|
||||
return nil
|
||||
end
|
||||
|
||||
local data_str = file.Read(path, "data")
|
||||
|
||||
if not string.Trim(data_str) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local success, data = pcall(json.decode, data_str)
|
||||
|
||||
if not success then
|
||||
return nil
|
||||
end
|
||||
|
||||
if istable(data) and data.timestamp and data.data then
|
||||
if max_age != nil and os.time() - data.timestamp > max_age then
|
||||
return nil
|
||||
end
|
||||
|
||||
return data.data
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
75
addons/vyhub-gmod/lua/vyhub/server/sv_commands.lua
Normal file
75
addons/vyhub-gmod/lua/vyhub/server/sv_commands.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_commands_vyhub_ready", function ()
|
||||
VyHub:get_frontend_url(function (url)
|
||||
-- !shop
|
||||
local function open_shop(ply, args)
|
||||
if IsValid(ply) then
|
||||
VyHub.Util:open_url(ply, f('%s/shop', url))
|
||||
end
|
||||
end
|
||||
|
||||
for _, cmd in ipairs(VyHub.Config.commands_shop) do
|
||||
VyHub.Util:register_chat_command(cmd, open_shop)
|
||||
end
|
||||
|
||||
-- !bans
|
||||
local function open_bans(ply, args)
|
||||
if IsValid(ply) then
|
||||
VyHub.Util:open_url(ply, f('%s/bans', url))
|
||||
end
|
||||
end
|
||||
|
||||
for _, cmd in ipairs(VyHub.Config.commands_bans) do
|
||||
VyHub.Util:register_chat_command(cmd, open_bans)
|
||||
end
|
||||
|
||||
-- !warnings
|
||||
local function open_warnings(ply, args)
|
||||
if IsValid(ply) then
|
||||
VyHub.Util:open_url(ply, f('%s/warnings', url))
|
||||
end
|
||||
end
|
||||
|
||||
for _, cmd in ipairs(VyHub.Config.commands_warnings) do
|
||||
VyHub.Util:register_chat_command(cmd, open_warnings)
|
||||
end
|
||||
|
||||
-- !news
|
||||
local function open_news(ply, args)
|
||||
if IsValid(ply) then
|
||||
VyHub.Util:open_url(ply, f('%s/', url))
|
||||
end
|
||||
end
|
||||
|
||||
for _, cmd in ipairs(VyHub.Config.commands_news) do
|
||||
VyHub.Util:register_chat_command(cmd, open_news)
|
||||
end
|
||||
|
||||
-- !user
|
||||
local function open_profile(ply, args)
|
||||
if IsValid(ply) and args[1] then
|
||||
other_ply = VyHub.Util:get_player_by_nick(args[1])
|
||||
|
||||
if IsValid(other_ply) then
|
||||
VyHub.Util:open_url(ply, f('%s/profile/steam/%s', url, other_ply:SteamID64()))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, cmd in ipairs(VyHub.Config.commands_profile) do
|
||||
VyHub.Util:register_chat_command(cmd, open_profile)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
88
addons/vyhub-gmod/lua/vyhub/server/sv_config.lua
Normal file
88
addons/vyhub-gmod/lua/vyhub/server/sv_config.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
function VyHub.Config:load_cache_config()
|
||||
local ccfg = VyHub.Cache:get("config")
|
||||
|
||||
if ccfg != nil and #table.GetKeys(ccfg) > 0 then
|
||||
VyHub.Config = table.Merge(VyHub.Config, ccfg)
|
||||
VyHub:msg(f("Loaded cache config values: %s", table.concat(table.GetKeys(ccfg), ', ')))
|
||||
end
|
||||
end
|
||||
|
||||
concommand.Add("vh_setup", function (ply, _, args)
|
||||
if not VyHub.Util:is_server(ply) then return end
|
||||
|
||||
if not args[1] or not args[2] or not args[3] then return end
|
||||
|
||||
local ccfg = VyHub.Cache:get("config")
|
||||
|
||||
if not istable(ccfg) then
|
||||
ccfg = {}
|
||||
end
|
||||
|
||||
ccfg["api_key"] = args[1]
|
||||
ccfg["api_url"] = args[2]
|
||||
ccfg["server_id"] = args[3]
|
||||
|
||||
VyHub.Cache:save("config", ccfg)
|
||||
|
||||
for key, value in pairs(ccfg) do
|
||||
VyHub.Config[key] = value
|
||||
end
|
||||
|
||||
VyHub:msg(f("Successfully set initial config, please wait up to one minute for VyHub to initialize (%s, %s, %s)", args[1], args[2], args[3]))
|
||||
end)
|
||||
|
||||
concommand.Add("vh_config", function (ply, _, args)
|
||||
if not VyHub.Util:is_server(ply) then return end
|
||||
|
||||
local ccfg = VyHub.Cache:get("config")
|
||||
|
||||
if not args[1] or not args[2] then
|
||||
if istable(ccfg) then
|
||||
VyHub:msg("Additional config options:")
|
||||
PrintTable(ccfg)
|
||||
else
|
||||
VyHub:msg("No additional config options set.")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local key = args[1]
|
||||
local value = args[2]
|
||||
|
||||
if not istable(ccfg) then
|
||||
ccfg = {}
|
||||
end
|
||||
|
||||
if value == "false" then
|
||||
value = false
|
||||
elseif value == "true" then
|
||||
value = true
|
||||
end
|
||||
|
||||
ccfg[key] = value
|
||||
VyHub.Cache:save("config", ccfg)
|
||||
|
||||
VyHub.Config[key] = value
|
||||
|
||||
VyHub:msg(f("Successfully set config value %s.", key))
|
||||
end)
|
||||
|
||||
concommand.Add("vh_config_reset", function (ply)
|
||||
if not VyHub.Util:is_server(ply) then return end
|
||||
|
||||
VyHub.Cache:save("config", {})
|
||||
|
||||
VyHub:msg(f("Successfully cleared additional config.", key))
|
||||
end)
|
||||
95
addons/vyhub-gmod/lua/vyhub/server/sv_dashboard.lua
Normal file
95
addons/vyhub-gmod/lua/vyhub/server/sv_dashboard.lua
Normal file
@@ -0,0 +1,95 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
VyHub.Dashboard = VyHub.Dashboard or {}
|
||||
VyHub.Dashboard.last_update = VyHub.Dashboard.last_update or {}
|
||||
VyHub.Dashboard.data = VyHub.Dashboard.data or {}
|
||||
|
||||
util.AddNetworkString("vyhub_dashboard")
|
||||
util.AddNetworkString("vyhub_dashboard_reload")
|
||||
|
||||
function VyHub.Dashboard:reset()
|
||||
VyHub.Dashboard.data = {}
|
||||
VyHub.Dashboard.last_update = {}
|
||||
net.Start("vyhub_dashboard_reload")
|
||||
net.Broadcast()
|
||||
end
|
||||
|
||||
function VyHub.Dashboard:fetch_data(user_id, callback)
|
||||
VyHub.API:get("/server/%s/user-activity?morph_user_id=%s", {VyHub.server.id, user_id}, nil, function(code, result)
|
||||
callback(result)
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Dashboard:get_data(steamid64, callback)
|
||||
if VyHub.Dashboard.data[steamid64] == nil or VyHub.Dashboard.last_update[steamid64] == nil or os.time() - VyHub.Dashboard.last_update[steamid64] > 30 then
|
||||
VyHub.Player:get(steamid64, function (user)
|
||||
if user then
|
||||
VyHub.Dashboard:fetch_data(user.id, function (data)
|
||||
VyHub.Dashboard.data[steamid64] = data
|
||||
VyHub.Dashboard.last_update[steamid64] = os.time()
|
||||
|
||||
callback(VyHub.Dashboard.data[steamid64])
|
||||
end)
|
||||
end
|
||||
end)
|
||||
else
|
||||
callback(VyHub.Dashboard.data[steamid64])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function VyHub.Dashboard:get_permissions(ply)
|
||||
return {
|
||||
warning_show = VyHub.Player:check_property(ply, 'warning_show'),
|
||||
warning_edit = VyHub.Player:check_property(ply, 'warning_edit'),
|
||||
warning_delete = VyHub.Player:check_property(ply, 'warning_delete'),
|
||||
ban_show = VyHub.Player:check_property(ply, 'ban_show'),
|
||||
ban_edit = VyHub.Player:check_property(ply, 'ban_edit'),
|
||||
}
|
||||
end
|
||||
|
||||
net.Receive("vyhub_dashboard", function(_, ply)
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
VyHub.Dashboard:get_data(ply:SteamID64(), function (users)
|
||||
local users_json = json.encode(users)
|
||||
local users_json_compressed = util.Compress(users_json)
|
||||
local users_json_compressed_len = #users_json_compressed
|
||||
local perms = VyHub.Dashboard:get_permissions(ply)
|
||||
local perms_json = json.encode(perms)
|
||||
|
||||
net.Start("vyhub_dashboard")
|
||||
net.WriteUInt(users_json_compressed_len, 16)
|
||||
net.WriteData(users_json_compressed, users_json_compressed_len)
|
||||
net.WriteString(perms_json)
|
||||
net.Send(ply)
|
||||
end)
|
||||
end)
|
||||
|
||||
local function open_dashboard(ply, args)
|
||||
if ply and IsValid(ply) then
|
||||
ply:ConCommand("vh_dashboard")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_dashboard_vyhub_ready", function ()
|
||||
for _, cmd in ipairs(VyHub.Config.commands_dashboard) do
|
||||
VyHub.Util:register_chat_command(cmd, open_dashboard)
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("vyhub_dashboard_data_changed", "vyhub_dahboard_vyhub_dashboard_data_changed", function ()
|
||||
VyHub.Dashboard:reset()
|
||||
end)
|
||||
375
addons/vyhub-gmod/lua/vyhub/server/sv_group.lua
Normal file
375
addons/vyhub-gmod/lua/vyhub/server/sv_group.lua
Normal file
@@ -0,0 +1,375 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
VyHub.Group = VyHub.Group or {}
|
||||
|
||||
VyHub.groups = VyHub.groups or nil
|
||||
VyHub.groups_mapped = VyHub.groups_mapped or nil
|
||||
VyHub.Group.group_changes = VyHub.Group.group_changes or {} -- dict(steamid64, groupname) of the last in-game group change (VyHub -> GMOD). Used to prevent loop.
|
||||
|
||||
util.AddNetworkString("vyhub_group_data")
|
||||
|
||||
local meta_ply = FindMetaTable("Player")
|
||||
|
||||
function VyHub.Group:refresh()
|
||||
VyHub.API:get("/group/", nil, nil, function(code, result)
|
||||
if result != VyHub.groups then
|
||||
VyHub.groups = result
|
||||
|
||||
VyHub:msg(f("Found groups: %s", json.encode(result)), "debug")
|
||||
|
||||
VyHub.groups_mapped = {}
|
||||
|
||||
for _, group in ipairs(VyHub.groups) do
|
||||
for _, mapping in ipairs(group.mappings) do
|
||||
if mapping.serverbundle_id == nil or mapping.serverbundle_id == VyHub.server.serverbundle.id then
|
||||
VyHub.groups_mapped[mapping.name] = group
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
VyHub.Group:send_groups()
|
||||
end
|
||||
end, function (code, reason)
|
||||
VyHub:msg("Could not refresh groups.", "error")
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Group:send_groups(ply)
|
||||
if not VyHub.groups_mapped then return end
|
||||
|
||||
local groups_to_send = VyHub.groups_mapped
|
||||
|
||||
net.Start("vyhub_group_data")
|
||||
net.WriteUInt(table.Count(groups_to_send), 8)
|
||||
|
||||
for name_game, group in pairs(groups_to_send) do
|
||||
net.WriteString(name_game)
|
||||
net.WriteString(group.name)
|
||||
net.WriteString(group.color)
|
||||
end
|
||||
|
||||
if ply != nil and IsValid(ply) then
|
||||
net.Send(ply)
|
||||
else
|
||||
net.Broadcast()
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Group:set(steamid, groupname, seconds, processor_id, callback)
|
||||
if seconds != nil and seconds == 0 then
|
||||
seconds = nil
|
||||
end
|
||||
|
||||
if VyHub.groups_mapped == nil then
|
||||
VyHub:msg("Groups not initialized yet. Please try again later.", "error")
|
||||
if callback then
|
||||
callback(!VyHub.Config.strict_group_sync)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local group = VyHub.groups_mapped[groupname]
|
||||
|
||||
if group == nil then
|
||||
VyHub:msg(f("Could not find VyHub group with name %s", groupname), "debug")
|
||||
|
||||
if callback then
|
||||
callback(!VyHub.Config.strict_group_sync)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.Player:get(steamid, function (user)
|
||||
if user == nil then
|
||||
if callback then
|
||||
callback(false)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local end_date = nil
|
||||
|
||||
if seconds != nil then
|
||||
end_date = VyHub.Util:format_datetime(os.time() + seconds)
|
||||
end
|
||||
|
||||
local url = '/user/%s/membership'
|
||||
|
||||
if processor_id != nil then
|
||||
url = url .. '?morph_user_id=' .. processor_id
|
||||
end
|
||||
|
||||
local ply = player.GetBySteamID64(steamid)
|
||||
|
||||
VyHub.API:post(url, {user.id}, {
|
||||
begin = VyHub.Util.format_datetime(),
|
||||
["end"] = end_date,
|
||||
group_id = group.id,
|
||||
serverbundle_id = VyHub.server.serverbundle.id
|
||||
}, function (code, result)
|
||||
VyHub:msg(f("Added membership in group %s for user %s.", groupname, steamid), "success")
|
||||
|
||||
if IsValid(ply) then
|
||||
timer.Simple(5, function()
|
||||
VyHub.Player:refresh(ply)
|
||||
end)
|
||||
end
|
||||
|
||||
if callback then
|
||||
callback(true)
|
||||
end
|
||||
end, function (code, reason)
|
||||
VyHub:msg(f("Could not add membership in group %s for user %s.", groupname, steamid), "error")
|
||||
if callback then
|
||||
callback(false)
|
||||
end
|
||||
|
||||
if IsValid(ply) then
|
||||
timer.Simple(2, function()
|
||||
VyHub.Player:refresh(ply)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Group:remove(steamid, processor_id, callback)
|
||||
VyHub.Player:get(steamid, function (user)
|
||||
if user == nil then
|
||||
if callback then
|
||||
callback(false)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local url = f('/user/%%s/membership?serverbundle_id=%s', VyHub.server.serverbundle.id)
|
||||
|
||||
if processor_id != nil then
|
||||
url = url .. '&morph_user_id=' .. processor_id
|
||||
end
|
||||
|
||||
VyHub.API:delete(url, {user.id}, function (code, result)
|
||||
VyHub:msg(f("Removed %s from all groups.", steamid), "success")
|
||||
|
||||
local ply = player.GetBySteamID64(steamid)
|
||||
|
||||
if IsValid(ply) then
|
||||
VyHub.Player:refresh(ply)
|
||||
end
|
||||
|
||||
if callback then
|
||||
callback(true)
|
||||
end
|
||||
end, function (code, reason)
|
||||
VyHub:msg(f("Could not remove %s from all groups.", steamid), "error")
|
||||
|
||||
if callback then
|
||||
callback(false)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Group:override_admin_mods()
|
||||
if VyHub.Config.group_disable_sync then return end
|
||||
|
||||
local _setusergroup = meta_ply.SetUserGroup
|
||||
|
||||
if not ULib and not serverguard and not sam and not (xAdmin and xAdmin.Admin.RegisterBan) and not sAdmin then
|
||||
hook.Remove("PlayerInitialSpawn", "PlayerAuthSpawn")
|
||||
|
||||
meta_ply.SetUserGroup = function(ply, name, ignore_vh)
|
||||
if ply:GetUserGroup() == name then
|
||||
VyHub:msg(ply:SteamID64() .. " already in group " .. name .. ". Ignoring change...")
|
||||
return
|
||||
end
|
||||
|
||||
local steamid = ply:SteamID64()
|
||||
|
||||
if not ignore_vh and VyHub.Group.group_changes[steamid] != name then
|
||||
if VyHub.Group:set(steamid, name) or VyHub.Config.disable_group_check then
|
||||
_setusergroup(ply, name)
|
||||
end
|
||||
else
|
||||
_setusergroup(ply, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if xAdmin and xAdmin.Admin.RegisterBan then
|
||||
local xadmin_setgroup = xAdmin.SetGroup
|
||||
|
||||
xAdmin.SetGroup = function(ply, group, ignore_vh)
|
||||
local steamid32 = isstring(ply) and ply or ply:SteamID()
|
||||
local steamid64 = util.SteamIDTo64(steamid32)
|
||||
|
||||
if not ignore_vh then
|
||||
VyHub.Group:set(steamid64, group, nil, nil, function(success)
|
||||
if success then
|
||||
xadmin_setgroup( ply, group )
|
||||
end
|
||||
end)
|
||||
else
|
||||
xadmin_setgroup( ply, group )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if ULib then
|
||||
local ulx_adduser = ULib.ucl.addUser
|
||||
local ulx_removeuser = ULib.ucl.removeUser
|
||||
|
||||
ULib.ucl.addUser = function(steamid32, allow, deny, groupname, ignore_vh)
|
||||
if not ignore_vh then
|
||||
local steamid64 = util.SteamIDTo64(steamid32)
|
||||
VyHub.Group:set(steamid64, groupname, nil, nil, function(success)
|
||||
if success then
|
||||
ulx_adduser( steamid32, allow, deny, groupname )
|
||||
end
|
||||
end)
|
||||
else
|
||||
ulx_adduser( steamid32, allow, deny, groupname )
|
||||
end
|
||||
end
|
||||
|
||||
ULib.ucl.removeUser = function(id)
|
||||
local steamid64 = nil
|
||||
|
||||
if string.find(id, ":") then
|
||||
steamid64 = util.SteamIDTo64(id)
|
||||
else
|
||||
local ply = player.GetByUniqueID(id)
|
||||
|
||||
if IsValid(ply) then
|
||||
steamid64 = ply:SteamID64()
|
||||
end
|
||||
end
|
||||
|
||||
if steamid64 then
|
||||
VyHub.Group:remove(steamid64, nil, function (success)
|
||||
if success then
|
||||
ulx_removeuser( id )
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if serverguard then
|
||||
local servergaurd_setrank = serverguard.player["SetRank"]
|
||||
|
||||
function serverguard.player:SetRank(target, rank, length, ignore_vh)
|
||||
if not ignore_vh then
|
||||
if target then
|
||||
if type(target) == "Player" and IsValid(target) then
|
||||
VyHub.Group:set(target:SteamID64(), rank, nil, nil, function(success)
|
||||
if success then
|
||||
servergaurd_setrank(self, target, rank, length)
|
||||
end
|
||||
end)
|
||||
elseif type(target) == "string" and string.match(target, "STEAM_%d:%d:%d+") then
|
||||
local steamid = util.SteamIDTo64(target)
|
||||
|
||||
VyHub.Group:set(steamid, rank, nil, nil, function(success)
|
||||
if success then
|
||||
servergaurd_setrank(self, target, rank, length)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
else
|
||||
servergaurd_setrank(self, target, rank, length)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if sam then
|
||||
local sam_setrank = sam.player.set_rank
|
||||
|
||||
function sam.player.set_rank(ply, rank, length, ignore_vh)
|
||||
if not ignore_vh then
|
||||
if not sam.isnumber(length) or length < 0 then
|
||||
length = nil
|
||||
end
|
||||
|
||||
local seconds = nil
|
||||
|
||||
if length != nil then
|
||||
seconds = math.Round(length * 60, 0)
|
||||
end
|
||||
|
||||
VyHub.Group:set(ply:SteamID64(), rank, seconds, nil, function(success)
|
||||
if success then
|
||||
sam_setrank(ply, rank, length)
|
||||
end
|
||||
end)
|
||||
else
|
||||
sam_setrank(ply, rank, length)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if sAdmin then
|
||||
local sadmin_setrank = sAdmin.setRank
|
||||
|
||||
sAdmin.setRank = function(ply, rank, expire, noupdate, ignore_vh)
|
||||
rank = rank or "user"
|
||||
|
||||
if not ignore_vh and not noupdate then
|
||||
local seconds = nil
|
||||
|
||||
if isnumber(expire) and expire > 0 then
|
||||
seconds = math.max(expire, 0)
|
||||
end
|
||||
|
||||
VyHub.Group:set(ply:SteamID64(), rank, seconds, nil, function(success)
|
||||
if success then
|
||||
sadmin_setrank(ply, rank, nil, noupdate)
|
||||
end
|
||||
end)
|
||||
else
|
||||
sadmin_setrank(ply, rank, expire, noupdate)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_group_vyhub_ready", function ()
|
||||
VyHub.Group:refresh()
|
||||
|
||||
timer.Create("vyhub_group_refresh", VyHub.Config.group_refresh_time, 0, function ()
|
||||
VyHub.Group:refresh()
|
||||
end)
|
||||
|
||||
hook.Add("vyhub_ply_connected", "vyhub_group_vyhub_ply_connected", function(ply)
|
||||
VyHub.Group:send_groups(ply)
|
||||
end)
|
||||
|
||||
concommand.Add("vh_setgroup", function(ply, _, args)
|
||||
if VyHub.Util:is_server(ply) then
|
||||
local steamid = args[1]
|
||||
local group = args[2]
|
||||
local bundle = args[3]
|
||||
|
||||
if steamid and group then
|
||||
VyHub.Group:set(steamid, group)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
VyHub.Group:override_admin_mods()
|
||||
end)
|
||||
92
addons/vyhub-gmod/lua/vyhub/server/sv_main.lua
Normal file
92
addons/vyhub-gmod/lua/vyhub/server/sv_main.lua
Normal file
@@ -0,0 +1,92 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
VyHub.frontend_url = VyHub.frontend_url or nil
|
||||
|
||||
function VyHub:server_data_ready()
|
||||
VyHub:msg(f("I am server %s in bundle %s.", VyHub.server.name, VyHub.server.serverbundle.name))
|
||||
|
||||
VyHub.ready = true
|
||||
|
||||
hook.Run("vyhub_ready")
|
||||
end
|
||||
|
||||
function VyHub:get_frontend_url(callback)
|
||||
if VyHub.frontend_url != nil then
|
||||
if callback then
|
||||
callback(VyHub.frontend_url)
|
||||
end
|
||||
|
||||
return VyHub.frontend_url
|
||||
end
|
||||
|
||||
VyHub.API:get('/general/frontend-url', nil, nil, function (code, result)
|
||||
VyHub.frontend_url = result.frontend_url
|
||||
VyHub.Cache:save('frontend_url', VyHub.frontend_url)
|
||||
|
||||
if callback then
|
||||
callback(VyHub.frontend_url)
|
||||
end
|
||||
end, function ()
|
||||
local frontend_url = VyHub.Cache:get('frontend_url')
|
||||
|
||||
if frontend_url == nil then
|
||||
VyHub:msg("Could not get frontend_url!", "error")
|
||||
end
|
||||
|
||||
if callback then
|
||||
callback(frontend_url)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
hook.Add("vyhub_api_ready", "vyhub_main_vyhub_api_ready", function ()
|
||||
VyHub.API:get("/server/%s", { VyHub.Config.server_id }, nil, function(code, result)
|
||||
VyHub.server = result
|
||||
|
||||
VyHub:server_data_ready()
|
||||
|
||||
VyHub.Cache:save("server", VyHub.server)
|
||||
end, function (code, result)
|
||||
VyHub:msg(f("Could not find server with id %s", VyHub.Config.server_id), "error")
|
||||
|
||||
timer.Simple(60, function ()
|
||||
hook.Run("vyhub_loading_finish")
|
||||
end)
|
||||
end)
|
||||
|
||||
VyHub:get_frontend_url()
|
||||
end)
|
||||
|
||||
hook.Add("vyhub_api_failed", "vyhub_main_vyhub_api_failed", function ()
|
||||
local server = VyHub.Cache:get("server", 604800)
|
||||
|
||||
if server != nil then
|
||||
VyHub.server = server
|
||||
|
||||
VyHub:server_data_ready()
|
||||
else
|
||||
VyHub:msg("Could not find cached server data or cached data is too old. Please make sure that the server is able to reach the VyHub API.", "error")
|
||||
|
||||
timer.Simple(60, function ()
|
||||
hook.Run("vyhub_loading_finish")
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
timer.Create("vyhub_not_ready_msg", 30, 0, function ()
|
||||
if VyHub.ready then
|
||||
timer.Remove("vyhub_not_ready_msg")
|
||||
else
|
||||
VyHub.Util:print_chat_all("<green>VyHub</green> is not ready. Please check the server log/console for errors.")
|
||||
end
|
||||
end)
|
||||
350
addons/vyhub-gmod/lua/vyhub/server/sv_ply.lua
Normal file
350
addons/vyhub-gmod/lua/vyhub/server/sv_ply.lua
Normal file
@@ -0,0 +1,350 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
VyHub.Player = VyHub.Player or {}
|
||||
|
||||
VyHub.Player.connect_queue = VyHub.Player.connect_queue or {}
|
||||
VyHub.Player.table = VyHub.Player.table or {}
|
||||
|
||||
util.AddNetworkString("vyhub_user_id")
|
||||
|
||||
local meta_ply = FindMetaTable("Player")
|
||||
|
||||
function VyHub.Player:initialize(ply, retry)
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local steamid = ply:SteamID64()
|
||||
|
||||
VyHub:msg(f("Initializing user %s, %s", ply:Nick(), steamid))
|
||||
|
||||
VyHub.API:get("/user/%s", {steamid}, {type = "STEAM"}, function(code, result)
|
||||
VyHub:msg(f("Found existing user %s for steam id %s (%s).", result.id, steamid, ply:Nick()), "success")
|
||||
|
||||
VyHub.Player.table[steamid] = result
|
||||
|
||||
VyHub.Player:refresh(ply)
|
||||
|
||||
VyHub.Player:send_user_id(ply)
|
||||
|
||||
hook.Run("vyhub_ply_initialized", ply)
|
||||
|
||||
local ply_timer_name = "vyhub_player_" .. steamid
|
||||
|
||||
timer.Create(ply_timer_name, VyHub.Config.player_refresh_time, 0, function()
|
||||
if IsValid(ply) then
|
||||
VyHub.Player:refresh(ply)
|
||||
else
|
||||
timer.Remove(ply_timer_name)
|
||||
end
|
||||
end)
|
||||
end, function(code, reason)
|
||||
if code != 404 then
|
||||
VyHub:msg(f("Could not check if users %s exists. Retrying in a minute..", steamid), "error")
|
||||
|
||||
timer.Simple(60, function ()
|
||||
VyHub.Player:initialize(ply)
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if retry then
|
||||
VyHub:msg(f("Could not create user %s. Retrying in a minute..", steamid), "error")
|
||||
|
||||
timer.Simple(60, function()
|
||||
VyHub.Player:initialize(ply)
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.Player:create(steamid, function()
|
||||
VyHub.Player:initialize(ply, true)
|
||||
end, function ()
|
||||
VyHub.Player:initialize(ply, true)
|
||||
end)
|
||||
end, { 404 })
|
||||
end
|
||||
|
||||
function VyHub.Player:send_user_id(ply)
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
ply:VyHubID(function (user_id)
|
||||
net.Start("vyhub_user_id")
|
||||
net.WriteString(user_id)
|
||||
net.Send(ply)
|
||||
end)
|
||||
end
|
||||
|
||||
local creation_began = {}
|
||||
local creation_success = {}
|
||||
local creation_err = {}
|
||||
|
||||
function VyHub.Player:create(steamid, success, err)
|
||||
-- Creation can take longer. If multiple creation requests occur, merge them to one.
|
||||
if not istable(creation_success[steamid]) then creation_success[steamid] = {} end
|
||||
if not istable(creation_err[steamid]) then creation_err[steamid] = {} end
|
||||
|
||||
table.insert(creation_success[steamid], success)
|
||||
table.insert(creation_err[steamid], err)
|
||||
|
||||
if creation_began[steamid] and os.time() - creation_began[steamid] < 10 then
|
||||
VyHub:msg(f("Queued creation request for steamid %s", steamid), "debug")
|
||||
return
|
||||
end
|
||||
|
||||
VyHub:msg(f("No existing user found for steam id %s. Creating..", steamid))
|
||||
|
||||
creation_began[steamid] = os.time()
|
||||
|
||||
local function reset_queue()
|
||||
creation_began[steamid] = 0
|
||||
creation_success[steamid] = {}
|
||||
creation_err[steamid] = {}
|
||||
end
|
||||
|
||||
VyHub.API:post('/user/', nil, { identifier = steamid, type = 'STEAM' }, function()
|
||||
for _, success_callback in pairs(creation_success[steamid]) do
|
||||
if success_callback then
|
||||
success_callback()
|
||||
end
|
||||
end
|
||||
reset_queue()
|
||||
end, function()
|
||||
for _, err_callback in pairs(creation_err[steamid]) do
|
||||
if err_callback then
|
||||
err_callback()
|
||||
end
|
||||
end
|
||||
reset_queue()
|
||||
end)
|
||||
end
|
||||
|
||||
-- Return nil if steamid is nil or API error
|
||||
-- Return false if steamid is false or could not create user
|
||||
function VyHub.Player:get(steamid, callback, retry)
|
||||
if steamid == nil then
|
||||
callback(nil)
|
||||
return
|
||||
end
|
||||
|
||||
if steamid == false then
|
||||
callback(false)
|
||||
return
|
||||
end
|
||||
|
||||
if VyHub.Player.table[steamid] != nil then
|
||||
callback(VyHub.Player.table[steamid])
|
||||
else
|
||||
VyHub.API:get("/user/%s", {steamid}, {type = "STEAM"}, function(code, result)
|
||||
VyHub:msg(f("Received user %s for steam id %s.", result.id, steamid), "debug")
|
||||
|
||||
VyHub.Player.table[steamid] = result
|
||||
|
||||
callback(result)
|
||||
end, function(code)
|
||||
VyHub:msg(f("Could not receive user %s.", steamid), "error")
|
||||
|
||||
if code == 404 and retry == nil then
|
||||
VyHub.Player:create(steamid, function ()
|
||||
VyHub.Player:get(steamid, callback, true)
|
||||
end, function ()
|
||||
callback(false)
|
||||
end)
|
||||
else
|
||||
callback(nil)
|
||||
end
|
||||
end, {404})
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Player:change_game_group(ply, group)
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local steamid64 = ply:SteamID64()
|
||||
local nick = ply:Nick()
|
||||
|
||||
VyHub.Group.group_changes[steamid64] = group
|
||||
|
||||
if serverguard then
|
||||
serverguard.player:SetRank(ply, group, false, true)
|
||||
elseif ulx then
|
||||
ULib.ucl.addUser( ply:SteamID(), {}, {}, group, true )
|
||||
elseif sam then
|
||||
sam.player.set_rank(ply, group, 0, true)
|
||||
elseif xAdmin and xAdmin.Admin.RegisterBan then
|
||||
xAdmin.SetGroup(ply, group, true)
|
||||
elseif sAdmin then
|
||||
sAdmin.setRank(ply, group, 0, false, true)
|
||||
else
|
||||
ply:SetUserGroup(group, true)
|
||||
end
|
||||
|
||||
VyHub:msg("Added " .. nick .. " to group " .. group, "success")
|
||||
VyHub.Util:print_chat(ply, f(VyHub.lang.ply.group_changed, group))
|
||||
end
|
||||
|
||||
function VyHub.Player:check_group(ply, callback)
|
||||
if VyHub.Config.group_disable_sync then return end
|
||||
|
||||
if ply:VyHubID() == nil then
|
||||
VyHub:msg(f("Could not check groups for user %s, because no VyHub id is available.", ply:SteamID64()), "debug")
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.API:get("/user/%s/group", {ply:VyHubID()}, { serverbundle_id = VyHub.server.serverbundle_id }, function(code, result)
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local steamid64 = ply:SteamID64()
|
||||
local nick = ply:Nick()
|
||||
|
||||
local highest = nil
|
||||
|
||||
for _, group in ipairs(result) do
|
||||
if highest == nil or highest.permission_level < group.permission_level then
|
||||
highest = group
|
||||
end
|
||||
end
|
||||
|
||||
if highest == nil then
|
||||
VyHub:msg(f("Could not find any active group for %s (%s)", nick, steamid64), "debug")
|
||||
return
|
||||
end
|
||||
|
||||
local group = nil
|
||||
|
||||
for _, mapping in ipairs(highest.mappings) do
|
||||
if mapping.serverbundle_id == nil or mapping.serverbundle_id == VyHub.server.serverbundle.id then
|
||||
group = mapping.name
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if group == nil then
|
||||
VyHub:msg(f("Could not find group name mapping for group %s.", highest.name), "debug")
|
||||
return
|
||||
end
|
||||
|
||||
local delay = 0
|
||||
|
||||
if sAdmin then
|
||||
delay = 3
|
||||
end
|
||||
|
||||
timer.Simple(delay, function ()
|
||||
local curr_group = ply:GetUserGroup()
|
||||
|
||||
if curr_group != group then
|
||||
VyHub.Player:change_game_group(ply, group)
|
||||
end
|
||||
end)
|
||||
end, function()
|
||||
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Player:refresh(ply, callback)
|
||||
VyHub.Player:check_group(ply)
|
||||
end
|
||||
|
||||
function VyHub.Player:get_group(ply)
|
||||
if not IsValid(ply) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local group = VyHub.groups_mapped[ply:GetUserGroup()]
|
||||
|
||||
if group == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
return group
|
||||
end
|
||||
|
||||
function VyHub.Player:check_property(ply, property)
|
||||
if not IsValid(ply) then return false end
|
||||
|
||||
local group = VyHub.Player:get_group(ply)
|
||||
|
||||
if group != nil then
|
||||
local prop = group.properties[property]
|
||||
|
||||
if prop != nil and prop.granted then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local steamid64 = ply:SteamID64()
|
||||
|
||||
if VyHub.Player.table[steamid64] then
|
||||
return VyHub.Player.table[steamid64].admin
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function meta_ply:VyHubID(callback)
|
||||
if IsValid(self) then
|
||||
local user = VyHub.Player.table[self:SteamID64()]
|
||||
local id = nil
|
||||
|
||||
if user != nil then
|
||||
id = user.id
|
||||
end
|
||||
|
||||
if id == nil or id == "" then
|
||||
VyHub.Player:get(self:SteamID64(), function(user)
|
||||
if user then
|
||||
if callback then
|
||||
callback(user.id)
|
||||
end
|
||||
else
|
||||
if callback then
|
||||
callback(nil)
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
if callback then
|
||||
callback(id)
|
||||
end
|
||||
end
|
||||
|
||||
return id
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("vyhub_ply_connected", "vyhub_ply_vyhub_ply_connected", function(ply)
|
||||
VyHub.Player:initialize(ply)
|
||||
end)
|
||||
|
||||
hook.Add("PlayerInitialSpawn","vyhub_ply_PlayerInitialSpawn", function(ply)
|
||||
if IsValid(ply) and not ply:IsBot() then
|
||||
if VyHub.ready then
|
||||
hook.Run("vyhub_ply_connected", ply)
|
||||
else
|
||||
VyHub.Player.connect_queue[#VyHub.Player.connect_queue+1] = ply
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_ply_vyhub_ready", function ()
|
||||
timer.Simple(5, function()
|
||||
for _, ply in ipairs(VyHub.Player.connect_queue) do
|
||||
if IsValid(ply) then
|
||||
hook.Run("vyhub_ply_connected", ply)
|
||||
end
|
||||
end
|
||||
|
||||
VyHub.Player.connect_queue = {}
|
||||
end)
|
||||
end)
|
||||
266
addons/vyhub-gmod/lua/vyhub/server/sv_reward.lua
Normal file
266
addons/vyhub-gmod/lua/vyhub/server/sv_reward.lua
Normal file
@@ -0,0 +1,266 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
VyHub.Reward = VyHub.Reward or {}
|
||||
VyHub.Reward.executed_rewards_queue = VyHub.Reward.executed_rewards_queue or {}
|
||||
VyHub.Reward.executed_rewards = VyHub.Reward.executed_rewards or {}
|
||||
VyHub.rewards = VyHub.rewards or {}
|
||||
|
||||
local RewardEvent = {
|
||||
DIRECT = "DIRECT",
|
||||
CONNECT = "CONNECT",
|
||||
SPAWN = "SPAWN",
|
||||
DEATH = "DEATH",
|
||||
DISCONNECT = "DISCONNECT",
|
||||
DISABLE = "DISABLE",
|
||||
}
|
||||
|
||||
local RewardType = {
|
||||
COMMAND = "COMMAND",
|
||||
SCRIPT = "SCRIPT",
|
||||
CREDITS = "CREDITS",
|
||||
MEMBERSHIP = "MEMBERSHIP",
|
||||
}
|
||||
|
||||
function VyHub.Reward:refresh(callback, limit_players, err)
|
||||
local user_ids = ""
|
||||
local players = limit_players or player.GetHumans()
|
||||
|
||||
for _, ply in ipairs(players) do
|
||||
if IsValid(ply) then
|
||||
local id = ply:VyHubID()
|
||||
|
||||
if id and string.len(id) == 36 then
|
||||
local glue = '&'
|
||||
|
||||
if user_ids == "" then
|
||||
glue = '?'
|
||||
end
|
||||
|
||||
user_ids = user_ids .. glue .. 'user_id=' .. id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if user_ids == "" then
|
||||
VyHub.rewards = {}
|
||||
else
|
||||
local query = f("%s&active=true&serverbundle_id=%s&status=OPEN&for_server_id=%s&foreign_ids=true", user_ids, VyHub.server.serverbundle.id, VyHub.server.id)
|
||||
|
||||
VyHub.API:get('/packet/reward/applied/user' .. query, nil, nil,
|
||||
function(code, result)
|
||||
if limit_players == nil then
|
||||
VyHub.rewards = result
|
||||
VyHub:msg(f("Found %i users with open rewards.", table.Count(result)), "debug")
|
||||
else
|
||||
for steamid, arewards in pairs(result) do
|
||||
VyHub.rewards[steamid] = arewards
|
||||
end
|
||||
end
|
||||
|
||||
if callback then
|
||||
callback()
|
||||
end
|
||||
end, function (code, reason)
|
||||
if err then
|
||||
err()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Reward:set_executed(areward_id)
|
||||
VyHub.Reward.executed_rewards_queue[areward_id] = true
|
||||
table.insert(VyHub.Reward.executed_rewards, areward_id)
|
||||
|
||||
VyHub.Reward:save_executed()
|
||||
end
|
||||
|
||||
function VyHub.Reward:save_executed()
|
||||
VyHub.Cache:save("executed_rewards_queue", VyHub.Reward.executed_rewards_queue)
|
||||
end
|
||||
|
||||
function VyHub.Reward:send_executed()
|
||||
for areward_id, val in pairs(VyHub.Reward.executed_rewards_queue) do
|
||||
if val != nil then
|
||||
VyHub.API:patch('/packet/reward/applied/%s', { areward_id }, { executed_on = { VyHub.server.id } }, function (code, result)
|
||||
VyHub.Reward.executed_rewards_queue[areward_id] = nil
|
||||
VyHub.Reward:save_executed()
|
||||
end, function (code, reason)
|
||||
if code >= 400 and code < 500 then
|
||||
VyHub:msg(f("Could not mark reward %s as executed. Aborting.", areward_id), "error")
|
||||
VyHub.Reward.executed_rewards_queue[areward_id] = nil
|
||||
VyHub.Reward:save_executed()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Reward:exec_rewards(event, steamid)
|
||||
steamid = steamid or nil
|
||||
|
||||
local allowed_events = { event }
|
||||
|
||||
local rewards_by_player = VyHub.rewards
|
||||
|
||||
if steamid != nil then
|
||||
rewards_by_player = {}
|
||||
rewards_by_player[steamid] = VyHub.rewards[steamid]
|
||||
else
|
||||
if event != RewardEvent.DIRECT then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if event == RewardEvent.DIRECT then
|
||||
table.insert(allowed_events, RewardEvent.DISABLE)
|
||||
end
|
||||
|
||||
for steamid, arewards in pairs(rewards_by_player) do
|
||||
local ply = player.GetBySteamID64(steamid)
|
||||
|
||||
if not IsValid(ply) then
|
||||
VyHub:msg(f("Player %s not valid, skipping.", steamid), "debug")
|
||||
continue
|
||||
end
|
||||
|
||||
for _, areward in ipairs(arewards) do
|
||||
local se = true
|
||||
local reward = areward.reward
|
||||
|
||||
if not table.HasValue(allowed_events, reward.on_event) then
|
||||
continue
|
||||
end
|
||||
|
||||
if table.HasValue(VyHub.Reward.executed_rewards, areward.id) then
|
||||
VyHub:msg(f("Skipped reward %s, because it already has been executed.", areward.id), "debug")
|
||||
continue
|
||||
end
|
||||
|
||||
local data = reward.data
|
||||
|
||||
if reward.type == RewardType.COMMAND then
|
||||
if data.command != nil then
|
||||
local cmd = VyHub.Reward:do_string_replacements(data.command, ply, areward)
|
||||
|
||||
if VyHub.Config.reward_command_whitelist and #VyHub.Config.reward_command_whitelist > 0 then
|
||||
local matched = false
|
||||
|
||||
for _, cmd_pattern in ipairs(VyHub.Config.reward_command_whitelist) do
|
||||
if string.match(cmd, cmd_pattern) != nil then
|
||||
matched = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not matched then
|
||||
VyHub:msg(f("Failed to execute reward '%s': Command '%s' does not match a command on the whitelist.", reward.name, cmd), "error")
|
||||
continue
|
||||
end
|
||||
end
|
||||
|
||||
game.ConsoleCommand(cmd.. "\n")
|
||||
end
|
||||
elseif reward.type == RewardType.SCRIPT then
|
||||
if VyHub.Config.reward_disable_scripts then
|
||||
VyHub:msg(f("Failed to execute reward '%s': Scripts are not allowed on this server. You can enable scripts in sv_config.lua or by entering 'vh_config reward_disable_scripts false' in the server console.", reward.name), "error")
|
||||
continue
|
||||
end
|
||||
|
||||
local lua_str = data.script
|
||||
|
||||
if lua_str != nil then
|
||||
lua_str = VyHub.Reward:do_string_replacements(lua_str, ply, areward)
|
||||
|
||||
RunString("local PLAYER = player.GetBySteamID64(\"" .. steamid .. "\") " .. lua_str, "vyhub_reward_script")
|
||||
end
|
||||
else
|
||||
VyHub:msg(f("No implementation for reward type %s", reward.type) "warning")
|
||||
end
|
||||
|
||||
VyHub:msg(f("Executed reward %s for user %s (%s): %s", reward.type, ply:Nick(), ply:SteamID64(), json.encode(data)))
|
||||
|
||||
if se and reward.once then
|
||||
VyHub.Reward:set_executed(areward.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
VyHub.Reward:send_executed()
|
||||
end
|
||||
|
||||
function VyHub.Reward:do_string_replacements(inp_str, ply, areward)
|
||||
local purchase_amount = "-"
|
||||
|
||||
if areward.applied_packet.purchase != nil then
|
||||
purchase_amount = areward.applied_packet.purchase.amount_text
|
||||
end
|
||||
|
||||
local replacements = {
|
||||
["user_id"] = ply:VyHubID(),
|
||||
["nick"] = ply:Nick(),
|
||||
["steamid64"] = ply:SteamID64(),
|
||||
["steamid32"] = ply:SteamID(),
|
||||
["uniqueid"] = ply:UniqueID(),
|
||||
["applied_packet_id"] = areward.applied_packet_id,
|
||||
["packet_title"] = areward.applied_packet.packet.title,
|
||||
["purchase_amount"] = purchase_amount,
|
||||
}
|
||||
|
||||
for k, v in pairs(replacements) do
|
||||
inp_str = string.Replace(tostring(inp_str), "%" .. tostring(k) .. "%", tostring(v))
|
||||
end
|
||||
|
||||
return inp_str
|
||||
end
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_reward_vyhub_ready", function ()
|
||||
VyHub.Reward.executed_rewards_queue = VyHub.Cache:get("executed_rewards_queue") or {}
|
||||
|
||||
VyHub.Reward:refresh(function ()
|
||||
VyHub.Reward:exec_rewards(RewardEvent.DIRECT)
|
||||
end)
|
||||
|
||||
timer.Create("vyhub_reward_refresh", 60, 0, function ()
|
||||
VyHub.Reward:refresh(function ()
|
||||
VyHub.Reward:exec_rewards(RewardEvent.DIRECT)
|
||||
end)
|
||||
end)
|
||||
|
||||
hook.Add("vyhub_ply_initialized", "vyhub_reward_vyhub_ply_initialized", function(ply)
|
||||
local function exec_ply_rewards()
|
||||
VyHub.Reward:exec_rewards(RewardEvent.CONNECT, tostring(ply:SteamID64()))
|
||||
hook.Run("vyhub_reward_post_connect", ply)
|
||||
end
|
||||
|
||||
VyHub.Reward:refresh(exec_ply_rewards, { ply }, exec_ply_rewards)
|
||||
end)
|
||||
|
||||
hook.Add("PlayerSpawn", "vyhub_reward_PlayerSpawn", function(ply)
|
||||
if ply:Alive() then
|
||||
VyHub.Reward:exec_rewards(RewardEvent.SPAWN, tostring(ply:SteamID64()))
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("PostPlayerDeath", "vyhub_reward_PostPlayerDeath", function(ply)
|
||||
VyHub.Reward:exec_rewards(RewardEvent.DEATH, tostring(ply:SteamID64()))
|
||||
end)
|
||||
|
||||
-- Does not work
|
||||
hook.Add("PlayerDisconnect", "vyhub_reward_PlayerDisconnect", function(ply)
|
||||
if IsValid(ply) then
|
||||
VyHub.Reward:exec_rewards(RewardEvent.Disconnect, tostring(ply:SteamID64()))
|
||||
end
|
||||
end)
|
||||
end)
|
||||
157
addons/vyhub-gmod/lua/vyhub/server/sv_server.lua
Normal file
157
addons/vyhub-gmod/lua/vyhub/server/sv_server.lua
Normal file
@@ -0,0 +1,157 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
VyHub.Server = VyHub.Server or {}
|
||||
|
||||
VyHub.Server.extra_defaults = {
|
||||
res_slots = 0,
|
||||
res_slots_keep_free = false,
|
||||
res_slots_hide = false,
|
||||
}
|
||||
|
||||
VyHub.Server.reserved_slot_plys = VyHub.Server.reserved_slot_plys or {}
|
||||
|
||||
function VyHub.Server:get_extra(key)
|
||||
if VyHub.server.extra != nil and VyHub.server.extra[key] != nil then
|
||||
return VyHub.server.extra[key]
|
||||
end
|
||||
|
||||
return VyHub.Server.extra_defaults[key]
|
||||
end
|
||||
|
||||
function VyHub.Server:update_status()
|
||||
local user_activities = {}
|
||||
|
||||
for _, ply in ipairs(player.GetHumans()) do
|
||||
local id = ply:VyHubID()
|
||||
|
||||
if id and string.len(id) == 36 then
|
||||
local tt = string.FormattedTime( ply:TimeConnected() )
|
||||
|
||||
table.insert(user_activities, { user_id = id, extra = {
|
||||
Score = ply:Frags(),
|
||||
Deaths = ply:Deaths(),
|
||||
Nickname = ply:Nick(),
|
||||
Playtime = f('%02d:%02d:%02d', tt.h, tt.m, tt.s),
|
||||
Ping = f('%i ms', ply:Ping()),
|
||||
}})
|
||||
end
|
||||
end
|
||||
|
||||
local data = {
|
||||
users_max = VyHub.Server.max_slots_visible,
|
||||
users_current = #player.GetAll(),
|
||||
map = game.GetMap(),
|
||||
is_alive = true,
|
||||
user_activities = user_activities,
|
||||
}
|
||||
|
||||
VyHub:msg(f("Updating status: %s", json.encode(data)), "debug")
|
||||
|
||||
VyHub.API:patch(
|
||||
'/server/%s',
|
||||
{VyHub.server.id},
|
||||
data,
|
||||
function ()
|
||||
hook.Run("vyhub_dashboard_data_changed")
|
||||
end,
|
||||
function ()
|
||||
VyHub:msg("Could not update server status.", "error")
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function VyHub.Server:update_max_slots()
|
||||
RunConsoleCommand("sv_visiblemaxplayers", VyHub.Server.max_slots_visible)
|
||||
end
|
||||
|
||||
function VyHub.Server:init_slots()
|
||||
VyHub.Server.max_slots = game.MaxPlayers() - VyHub.Server:get_extra("res_slots")
|
||||
VyHub.Server.max_slots_visible = VyHub.Server.max_slots
|
||||
|
||||
if VyHub.Server:get_extra("res_slots_hide") then
|
||||
VyHub.Server:update_max_slots()
|
||||
|
||||
hook.Add("PlayerDisconnected", "vyhub_server_PlayerDisconnected", function(ply)
|
||||
timer.Create("vyhub_slots", 0.5, 20, function()
|
||||
if not IsValid(ply) then
|
||||
timer.Remove("vyhub_slots")
|
||||
VyHub.Server:update_max_slots()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
else
|
||||
VyHub.Server.max_slots_visible = game.MaxPlayers()
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Server:can_use_rslot(ply)
|
||||
if not IsValid(ply) or ply:IsBot() then
|
||||
return false
|
||||
end
|
||||
|
||||
if table.HasValue(VyHub.Server.reserved_slot_plys, ply:SteamID64()) then
|
||||
return true
|
||||
end
|
||||
|
||||
local group = VyHub.Player:get_group(ply)
|
||||
|
||||
if group != nil then
|
||||
if group.properties.reserved_slot_use != nil then
|
||||
return group.properties.reserved_slot_use.granted
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function VyHub.Server:handle_ply_connect(ply)
|
||||
if IsValid(ply) then
|
||||
if #player.GetHumans() > VyHub.Server.max_slots then
|
||||
if VyHub.Server:can_use_rslot(ply) then
|
||||
if VyHub.Server:get_extra("res_slots_keep_free") then
|
||||
local tokick = nil
|
||||
|
||||
for _, v in ipairs(player.GetHumans()) do
|
||||
if v:SteamID64() != ply:SteamID64() and not VyHub.Server:can_use_rslot(v) then
|
||||
if tokick == nil or (IsValid(tokick) and v:TimeConnected() < tokick:TimeConnected()) then
|
||||
tokick = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if tokick and IsValid(tokick) then
|
||||
tokick:Kick(VyHub.lang.rslots.kick)
|
||||
else
|
||||
ply:Kick(VyHub.lang.rslots.full)
|
||||
end
|
||||
end
|
||||
else
|
||||
ply:Kick(VyHub.lang.rslots.full_no_slot)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_server_vyhub_ready", function ()
|
||||
VyHub.Server:init_slots()
|
||||
VyHub.Server:update_status()
|
||||
|
||||
timer.Create("vyhub_status_update", 60, 0, function ()
|
||||
VyHub.Server:update_status()
|
||||
end)
|
||||
|
||||
hook.Add("vyhub_reward_post_connect", "vyhub_server_vyhub_reward_post_connect", function (ply)
|
||||
VyHub.Server:handle_ply_connect(ply)
|
||||
end)
|
||||
end)
|
||||
143
addons/vyhub-gmod/lua/vyhub/server/sv_statistic.lua
Normal file
143
addons/vyhub-gmod/lua/vyhub/server/sv_statistic.lua
Normal file
@@ -0,0 +1,143 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
VyHub.Statistic = VyHub.Statistic or {}
|
||||
VyHub.Statistic.playtime = VyHub.Statistic.playtime or {}
|
||||
VyHub.Statistic.attr_def = VyHub.Statistic.attr_def or nil
|
||||
|
||||
function VyHub.Statistic:save_playtime()
|
||||
VyHub:msg(f("Saved playtime statistics: %s", json.encode(VyHub.Statistic.playtime)), "debug")
|
||||
|
||||
VyHub.Cache:save("playtime", VyHub.Statistic.playtime)
|
||||
end
|
||||
|
||||
function VyHub.Statistic:add_one_minute()
|
||||
for _, ply in ipairs(player.GetHumans()) do
|
||||
local steamid = ply:SteamID64()
|
||||
ply:VyHubID(function (user_id)
|
||||
if user_id == nil or string.len(user_id) < 10 then
|
||||
VyHub:msg(f("Could not add playtime for user %s", steamid))
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.Statistic.playtime[user_id] = VyHub.Statistic.playtime[user_id] or 0
|
||||
VyHub.Statistic.playtime[user_id] = VyHub.Statistic.playtime[user_id] + 60
|
||||
end)
|
||||
end
|
||||
|
||||
VyHub.Statistic:save_playtime()
|
||||
end
|
||||
|
||||
function VyHub.Statistic:send_playtime()
|
||||
VyHub.Statistic:get_or_create_attr_definition(function (attr_def)
|
||||
if attr_def == nil then
|
||||
VyHub:msg("Could not send playtime statistics to API.", "warning")
|
||||
return
|
||||
end
|
||||
|
||||
local user_ids = table.GetKeys(VyHub.Statistic.playtime)
|
||||
|
||||
timer.Create("vyhub_send_stats", 0.3, table.Count(user_ids), function ()
|
||||
local i = table.Count(user_ids)
|
||||
local user_id = user_ids[i]
|
||||
|
||||
if user_id != nil then
|
||||
local seconds = VyHub.Statistic.playtime[user_id]
|
||||
table.remove(user_ids, i)
|
||||
|
||||
if seconds != nil and seconds > 0 then
|
||||
local hours = math.Round(seconds / 60 / 60, 2)
|
||||
|
||||
if hours > 0 then
|
||||
if string.len(user_id) < 10 then
|
||||
VyHub.Statistic.playtime[user_id] = nil
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.API:post("/user/attribute/", nil, {
|
||||
definition_id = attr_def.id,
|
||||
user_id = user_id,
|
||||
serverbundle_id = VyHub.server.serverbundle.id,
|
||||
value = tostring(hours),
|
||||
}, function (code, result)
|
||||
VyHub.Statistic.playtime[user_id] = nil
|
||||
VyHub.Statistic:save_playtime()
|
||||
end, function (code, reason)
|
||||
if code == 404 then
|
||||
VyHub.Statistic.playtime[user_id] = nil
|
||||
VyHub.Statistic:save_playtime()
|
||||
end
|
||||
|
||||
VyHub:msg(f("Could not send %s seconds playtime of %s to API.", seconds, user_id), "warning")
|
||||
end)
|
||||
end
|
||||
else
|
||||
VyHub.Statistic.playtime[user_id] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Statistic:get_or_create_attr_definition(callback)
|
||||
local function cb_wrapper(attr_def)
|
||||
VyHub.Statistic.attr_def = attr_def
|
||||
|
||||
callback(attr_def)
|
||||
end
|
||||
|
||||
if VyHub.Statistic.attr_def != nil then
|
||||
callback(VyHub.Statistic.attr_def)
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.API:get("/user/attribute/definition/%s", { "playtime" }, nil, function (code, result)
|
||||
VyHub.Cache:save("playtime_attr_def", result)
|
||||
cb_wrapper(result)
|
||||
end, function (code, reason)
|
||||
if code != 404 then
|
||||
local attr_def = VyHub.Cache:get("playtime_attr_def")
|
||||
|
||||
cb_wrapper(attr_def)
|
||||
else
|
||||
VyHub.API:post("/user/attribute/definition/", nil, {
|
||||
name = "playtime",
|
||||
title = "Play Time",
|
||||
unit = "Hours",
|
||||
type = "ACCUMULATED",
|
||||
accumulation_interval = "day",
|
||||
unspecific = "true",
|
||||
}, function (code, result)
|
||||
VyHub.Cache:save("playtime_attr_def", result)
|
||||
cb_wrapper(result)
|
||||
end, function (code, reason)
|
||||
cb_wrapper(nil)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_statistic_vyhub_ready", function ()
|
||||
VyHub.Statistic.playtime = VyHub.Cache:get("playtime") or {}
|
||||
|
||||
VyHub.Statistic:send_playtime()
|
||||
|
||||
timer.Create("vyhub_statistic_playtime_tick", 60, 0, function ()
|
||||
VyHub.Statistic:add_one_minute()
|
||||
end)
|
||||
|
||||
timer.Create("vyhub_statistic_send_playtime", 3600, 0, function ()
|
||||
VyHub.Statistic:send_playtime()
|
||||
end)
|
||||
end)
|
||||
183
addons/vyhub-gmod/lua/vyhub/server/sv_warning.lua
Normal file
183
addons/vyhub-gmod/lua/vyhub/server/sv_warning.lua
Normal file
@@ -0,0 +1,183 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
|
||||
VyHub.Warning = VyHub.Warning or {}
|
||||
|
||||
function VyHub.Warning:create(steamid, reason, processor_steamid)
|
||||
processor_steamid = processor_steamid or nil
|
||||
|
||||
VyHub.Player:get(steamid, function (user)
|
||||
if user == nil then
|
||||
VyHub.Util:print_chat_steamid(processor_steamid, f("<red>Cannot find VyHub user with SteamID %s.</red>", steamid))
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.Player:get(processor_steamid, function (processor)
|
||||
if processor_steamid != nil and processor == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local url = '/warning/'
|
||||
|
||||
if processor != nil then
|
||||
url = url .. f('?morph_user_id=%s', processor.id)
|
||||
end
|
||||
|
||||
VyHub.API:post(url, nil, {
|
||||
reason = reason,
|
||||
serverbundle_id = VyHub.server.serverbundle.id,
|
||||
user_id = user.id
|
||||
}, function (code, result)
|
||||
VyHub.Ban:refresh()
|
||||
VyHub:msg(f("Added warning for player %s: %s", user.username, reason))
|
||||
VyHub.Util:print_chat_all(f(VyHub.lang.warning.user_warned, user.username, processor.username, reason))
|
||||
VyHub.Util:print_chat_steamid(steamid, f(VyHub.lang.warning.received, processor.username, reason))
|
||||
VyHub.Util:play_sound_steamid(steamid, "https://cdn.vyhub.net/sound/negativebeep.wav")
|
||||
hook.Run("vyhub_dashboard_data_changed")
|
||||
end, function (code, err_reason, _, err_text)
|
||||
VyHub:msg(f("Error while adding warning for player %s: %s", user.username, err_text), "error")
|
||||
VyHub.Util:print_chat_steamid(processor_steamid, f(VyHub.lang.warning.create_error, user.username, err_text))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
function VyHub.Warning:delete(warning_id, processor_steamid)
|
||||
processor_steamid = processor_steamid or nil
|
||||
|
||||
VyHub.Player:get(processor_steamid, function (processor)
|
||||
if not processor then return end
|
||||
|
||||
local url = '/warning/%s'
|
||||
|
||||
if processor != nil then
|
||||
url = url .. f('?morph_user_id=%s', processor.id)
|
||||
end
|
||||
|
||||
VyHub.API:delete(url, { warning_id }, function (code, result)
|
||||
VyHub:msg(f("%s deleted warning %s.", processor.username, warning_id))
|
||||
VyHub.Util:print_chat_steamid(processor_steamid, f(VyHub.lang.warning.deleted))
|
||||
VyHub.Util:print_chat_steamid(steamid, VyHub.lang.warning.deleted_self)
|
||||
hook.Run("vyhub_dashboard_data_changed")
|
||||
end, function (code, err_reason, _, err_text)
|
||||
VyHub:msg(f("Error while deleteing warning %s: %s", warning_id, err_text), "error")
|
||||
VyHub.Util:print_chat_steamid(processor_steamid, f(VyHub.lang.other.error_api, err_text))
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function VyHub.Warning:toggle(warning_id, processor_steamid)
|
||||
processor_steamid = processor_steamid or nil
|
||||
|
||||
VyHub.Player:get(processor_steamid, function (processor)
|
||||
if not processor then return end
|
||||
|
||||
local url = '/warning/%s/toggle'
|
||||
|
||||
if processor != nil then
|
||||
url = url .. f('?morph_user_id=%s', processor.id)
|
||||
end
|
||||
|
||||
VyHub.API:patch(url, { warning_id }, nil, function (code, result)
|
||||
VyHub:msg(f("%s toggled warning %s.", processor.username, warning_id))
|
||||
VyHub.Util:print_chat_steamid(processor_steamid, f(VyHub.lang.warning.toggled))
|
||||
VyHub.Util:print_chat_steamid(steamid, VyHub.lang.warning.toggled_self)
|
||||
hook.Run("vyhub_dashboard_data_changed")
|
||||
end, function (code, err_reason, _, err_text)
|
||||
VyHub:msg(f("Error while toggling status of warning %s: %s", warning_id, err_text), "error")
|
||||
VyHub.Util:print_chat_steamid(processor_steamid, f(VyHub.lang.other.error_api, err_text))
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
local function warn_command(ply, args)
|
||||
if not VyHub.Player:check_property(ply, "warning_edit") then
|
||||
VyHub.Util:print_chat(ply, VyHub.lang.ply.no_permissions)
|
||||
return
|
||||
end
|
||||
|
||||
if args[1] and args[2] then
|
||||
local reason = VyHub.Util:concat_args(args, 2)
|
||||
|
||||
local target = VyHub.Util:get_player_by_nick(args[1])
|
||||
|
||||
if target and IsValid(target) then
|
||||
local nickparts = string.Explode(' ', target:Nick())
|
||||
|
||||
if #nickparts > 1 then
|
||||
nickparts = VyHub.Util:concat_args(nickparts, 2) .. ' '
|
||||
reason = string.Replace(reason, nickparts, '')
|
||||
end
|
||||
|
||||
VyHub.Warning:create(target:SteamID64(), reason, ply:SteamID64())
|
||||
end
|
||||
end
|
||||
|
||||
if IsValid(ply) then
|
||||
VyHub.Util:print_chat(ply, VyHub.lang.warning.cmd_help)
|
||||
end
|
||||
|
||||
return false;
|
||||
end
|
||||
|
||||
hook.Add("vyhub_ready", "vyhub_warning_vyhub_ready", function ()
|
||||
concommand.Add("vh_warn", function(ply, _, args)
|
||||
if not args[1] or not args[2] then return end
|
||||
|
||||
if VyHub.Util:is_server(ply) then
|
||||
VyHub.Warning:create(args[1], args[2])
|
||||
elseif IsValid(ply) then
|
||||
if VyHub.Player:check_property(ply, "warning_edit") then
|
||||
VyHub.Warning:create(args[1], args[2], ply:SteamID64())
|
||||
else
|
||||
VyHub.Util:print_chat(ply, VyHub.lang.ply.no_permissions)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
concommand.Add("vh_warning_toggle", function(ply, _, args)
|
||||
if not args[1] then return end
|
||||
|
||||
local warning_id = args[1]
|
||||
|
||||
if VyHub.Util:is_server(ply) then
|
||||
VyHub.Warning:toggle(warning_id)
|
||||
elseif IsValid(ply) then
|
||||
if VyHub.Player:check_property(ply, "warning_edit") then
|
||||
VyHub.Warning:toggle(warning_id, ply:SteamID64())
|
||||
else
|
||||
VyHub.Util:print_chat(ply, VyHub.lang.ply.no_permissions)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
concommand.Add("vh_warning_delete", function(ply, _, args)
|
||||
if not args[1] then return end
|
||||
|
||||
local warning_id = args[1]
|
||||
|
||||
if VyHub.Util:is_server(ply) then
|
||||
VyHub.Warning:delete(warning_id)
|
||||
elseif IsValid(ply) then
|
||||
if VyHub.Player:check_property(ply, "warning_delete") then
|
||||
VyHub.Warning:delete(warning_id, ply:SteamID64())
|
||||
else
|
||||
VyHub.Util:print_chat(ply, VyHub.lang.ply.no_permissions)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
for _, cmd in ipairs(VyHub.Config.commands_warn) do
|
||||
VyHub.Util:register_chat_command(cmd, warn_command)
|
||||
end
|
||||
end)
|
||||
43
addons/vyhub-gmod/lua/vyhub/shared/sh_01_config.lua
Normal file
43
addons/vyhub-gmod/lua/vyhub/shared/sh_01_config.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
-- DEFAULTS
|
||||
VyHub.Config.date_format = VyHub.Config.date_format or "%Y-%m-%d %H:%M:%S %z"
|
||||
|
||||
if SERVER then
|
||||
VyHub.Config.advert_interval = VyHub.Config.advert_interval or 180
|
||||
VyHub.Config.advert_prefix = VyHub.Config.advert_prefix or "[★] "
|
||||
|
||||
-- Do not allow too small refresh intervals
|
||||
if VyHub.Config.player_refresh_time < 5 then
|
||||
VyHub.Config.player_refresh_time = 5
|
||||
end
|
||||
if VyHub.Config.group_refresh_time < 5 then
|
||||
VyHub.Config.group_refresh_time = 5
|
||||
end
|
||||
|
||||
VyHub.Config.ban_message = VyHub.Config.ban_message or ">>> Ban Message <<<" .. "\n\n"
|
||||
.. VyHub.lang.other.reason .. ": %reason%" .. "\n"
|
||||
.. VyHub.lang.other.ban_date .. ": %ban_date%" .. "\n"
|
||||
.. VyHub.lang.other.unban_date .. ": %unban_date%" .. "\n"
|
||||
.. VyHub.lang.other.admin .. ": %admin%" .. "\n"
|
||||
.. VyHub.lang.other.id .. ": %id%" .. "\n\n"
|
||||
.. VyHub.lang.other.unban_url .. ": %unban_url%" .. "\n\n"
|
||||
|
||||
VyHub.Config.commands_shop = VyHub.Config.commands_shop or { '!shop' }
|
||||
VyHub.Config.commands_bans = VyHub.Config.commands_bans or { '!bans' }
|
||||
VyHub.Config.commands_warnings = VyHub.Config.commands_warnings or { '!warnings' }
|
||||
VyHub.Config.commands_news = VyHub.Config.commands_news or { '!news' }
|
||||
VyHub.Config.commands_profile = VyHub.Config.commands_profile or { '!user' }
|
||||
VyHub.Config.commands_warn = VyHub.Config.commands_warn or { '!warn' }
|
||||
VyHub.Config.commands_dashboard = VyHub.Config.commands_dashboard or { '!dashboard' }
|
||||
|
||||
VyHub.Config.strict_group_sync = VyHub.Config.strict_group_sync or false
|
||||
end
|
||||
19
addons/vyhub-gmod/lua/vyhub/shared/sh_group.lua
Normal file
19
addons/vyhub-gmod/lua/vyhub/shared/sh_group.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
VyHub.Group = VyHub.Group or {}
|
||||
|
||||
function VyHub.Group:get(groupname)
|
||||
if VyHub.groups_mapped == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
return VyHub.groups_mapped[groupname]
|
||||
end
|
||||
110
addons/vyhub-gmod/lua/vyhub/shared/sh_lang.lua
Normal file
110
addons/vyhub-gmod/lua/vyhub/shared/sh_lang.lua
Normal file
@@ -0,0 +1,110 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local json = VyHub.Lib.json
|
||||
|
||||
VyHub.Lang = VyHub.Lang or {}
|
||||
VyHub.lang = VyHub.lang or nil
|
||||
|
||||
if SERVER then
|
||||
util.AddNetworkString("vyhub_lang")
|
||||
|
||||
VyHub.Lang.compressed = VyHub.Lang.compressed or nil
|
||||
|
||||
function VyHub.Lang:load()
|
||||
local f_en = file.Open("vyhub/lang/en.json", "r", "LUA")
|
||||
|
||||
if f_en == nil then
|
||||
VyHub:msg("Missing language file en.json!!! PLEASE MAKE SURE TO DOWNLOAD VYHUB-GMOD ON THE GITHUB RELESES PAGE! https://github.com/matbyte-com/vyhub-gmod/releases", "error")
|
||||
return
|
||||
end
|
||||
|
||||
local en = json.decode(f_en:Read())
|
||||
f_en:Close()
|
||||
|
||||
if not istable(en) then
|
||||
VyHub:msg("Could not load language file en.json!", "error")
|
||||
return
|
||||
end
|
||||
|
||||
VyHub.lang = en
|
||||
|
||||
VyHub:msg("Loaded language en.")
|
||||
|
||||
if VyHub.Config.lang != 'en' then
|
||||
local f_custom = file.Open(f("vyhub/lang/%s.json", VyHub.Config.lang), "r", "LUA")
|
||||
|
||||
if f_custom != nil then
|
||||
local custom = json.decode(f_custom:Read())
|
||||
f_custom:Close()
|
||||
|
||||
if istable(custom) then
|
||||
table.Merge(VyHub.lang, custom)
|
||||
VyHub:msg(f("Loaded language %s.", VyHub.Config.lang))
|
||||
else
|
||||
VyHub:msg(f("Could not load language file %s.json!", VyHub.Config.lang), "warning")
|
||||
end
|
||||
else
|
||||
VyHub:msg(f("Missing language file %s.json.", VyHub.Config.lang), "warning")
|
||||
end
|
||||
end
|
||||
|
||||
VyHub.Lang.compressed = util.Compress(json.encode(VyHub.lang))
|
||||
end
|
||||
|
||||
if VyHub.lang == nil then
|
||||
VyHub.Lang:load()
|
||||
end
|
||||
|
||||
net.Receive("vyhub_lang", function(_, ply)
|
||||
if not IsValid(ply) then return end
|
||||
if not VyHub.Lang.compressed then return end
|
||||
|
||||
local len = #VyHub.Lang.compressed
|
||||
|
||||
net.Start("vyhub_lang")
|
||||
net.WriteUInt(len, 16)
|
||||
net.WriteData(VyHub.Lang.compressed, len)
|
||||
net.Send(ply)
|
||||
end)
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
function VyHub.Lang:load()
|
||||
net.Start("vyhub_lang")
|
||||
net.SendToServer()
|
||||
end
|
||||
|
||||
net.Receive("vyhub_lang", function()
|
||||
timer.Remove("vyhub_lang_load")
|
||||
|
||||
local len = net.ReadUInt(16)
|
||||
local lang_compr = net.ReadData(len)
|
||||
|
||||
VyHub.lang = json.decode(util.Decompress(lang_compr))
|
||||
|
||||
VyHub:msg("Loaded language.")
|
||||
|
||||
hook.Run("vyhub_lang_loaded")
|
||||
end)
|
||||
|
||||
hook.Add("Initialize", "vyhub_lang_Initialize", function ()
|
||||
VyHub.Lang:load()
|
||||
|
||||
timer.Create("vyhub_lang_load", 5, 5, function ()
|
||||
if VyHub.lang == nil then
|
||||
VyHub.Lang:load()
|
||||
else
|
||||
timer.Remove("vyhub_lang_load")
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
322
addons/vyhub-gmod/lua/vyhub/shared/sh_util.lua
Normal file
322
addons/vyhub-gmod/lua/vyhub/shared/sh_util.lua
Normal file
@@ -0,0 +1,322 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local f = string.format
|
||||
local date = VyHub.Lib.date
|
||||
|
||||
VyHub.Util = VyHub.Util or {}
|
||||
VyHub.Util.chat_commands = VyHub.Util.chat_commands or {}
|
||||
|
||||
if SERVER then
|
||||
util.AddNetworkString("vyhub_print_chat")
|
||||
util.AddNetworkString("vyhub_play_sound")
|
||||
util.AddNetworkString("vyhub_open_url")
|
||||
end
|
||||
|
||||
function VyHub.Util:format_datetime(unix_timestamp)
|
||||
unix_timestamp = unix_timestamp or os.time()
|
||||
|
||||
local tz_wrong = os.date("%z", unix_timestamp)
|
||||
local timezone = f("%s:%s", string.sub(tz_wrong, 1, 3), string.sub(tz_wrong, 4, 5))
|
||||
|
||||
return os.date("%Y-%m-%dT%H:%M:%S" .. timezone, unix_timestamp)
|
||||
end
|
||||
|
||||
function VyHub.Util:is_server(obj)
|
||||
if type(obj) == "Entity" and (obj.EntIndex and obj:EntIndex() == 0) and !IsValid(obj) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:iso_to_unix_timestamp(datetime)
|
||||
if datetime == nil then return nil end
|
||||
|
||||
local pd = date(datetime)
|
||||
|
||||
if pd == nil then return nil end
|
||||
|
||||
local time = os.time(
|
||||
{
|
||||
year = pd:getyear(),
|
||||
month = pd:getmonth(),
|
||||
day = pd:getday(),
|
||||
hour = pd:gethours(),
|
||||
minute = pd:getminutes(),
|
||||
second = pd:getseconds(),
|
||||
}
|
||||
)
|
||||
|
||||
return time
|
||||
end
|
||||
|
||||
function VyHub.Util:get_ply_by_nick(nick)
|
||||
nick = string.lower(nick);
|
||||
|
||||
for _, v in ipairs(player.GetHumans()) do
|
||||
if(string.find(string.lower(v:Name()), nick, 1, true) != nil)
|
||||
then return v;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:register_chat_command(strCommand, Func)
|
||||
if !strCommand || !Func then return end
|
||||
|
||||
for k, v in pairs( VyHub.Util.chat_commands ) do
|
||||
if( strCommand == k ) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
VyHub.Util.chat_commands[ tostring( strCommand ) ] = Func;
|
||||
end
|
||||
|
||||
function VyHub.Util:concat_args(args, pos)
|
||||
local toconcat = {}
|
||||
|
||||
if pos > 1 then
|
||||
for i = pos, #args, 1 do
|
||||
toconcat[#toconcat+1] = args[i]
|
||||
end
|
||||
end
|
||||
|
||||
return string.Implode(" ", toconcat)
|
||||
end
|
||||
|
||||
|
||||
if SERVER then
|
||||
hook.Add("PlayerSay", "vyhub_util_PlayerSay", function(ply, message)
|
||||
if VyHub.ready then
|
||||
local chat_string = string.Explode(" ", message)
|
||||
local ret = nil
|
||||
|
||||
for k, v in pairs( VyHub.Util.chat_commands ) do
|
||||
if( string.lower(chat_string[1]) == string.lower(k) ) then
|
||||
table.remove(chat_string, 1)
|
||||
ret = v(ply, chat_string)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if ret != nil then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local colors = {
|
||||
red = Color(255, 24, 35),
|
||||
green = Color(45, 170, 0),
|
||||
blue = Color(0, 115, 204),
|
||||
yellow = Color(229, 221, 0),
|
||||
pink = Color(229, 0, 218),
|
||||
}
|
||||
|
||||
-- Takes a str message with colors and returns a table
|
||||
function VyHub.Util:replace_colors(message, no_color)
|
||||
local resultTable = {}
|
||||
local currentIndex = 1
|
||||
|
||||
local function getColor(colorName)
|
||||
if colors[colorName] then
|
||||
return colors[colorName]
|
||||
else
|
||||
return no_color
|
||||
end
|
||||
end
|
||||
|
||||
local function addStringToTable(str, color)
|
||||
table.insert(resultTable, color)
|
||||
table.insert(resultTable, str)
|
||||
end
|
||||
|
||||
local tags = {}
|
||||
|
||||
-- Extract all color tags and their corresponding content
|
||||
for tag, content in string.gmatch(message, "<([%l]+)>([^<]+)</%1>") do
|
||||
table.insert(tags, {tag = tag, content = content})
|
||||
end
|
||||
|
||||
-- Process the string, splitting it based on the color tags
|
||||
for _, tagData in ipairs(tags) do
|
||||
local startIndex, endIndex = string.find(message, f("<(%s)>[^<]+</%s>", string.PatternSafe(tagData.tag), string.PatternSafe(tagData.tag)), currentIndex, false)
|
||||
|
||||
if startIndex then
|
||||
local str = string.sub(message, currentIndex, startIndex - 1)
|
||||
|
||||
addStringToTable(str, no_color)
|
||||
addStringToTable(tagData.content, getColor(tagData.tag))
|
||||
|
||||
currentIndex = endIndex + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Append any remaining part of the string
|
||||
local str = string.sub(message, currentIndex)
|
||||
if str != "" then
|
||||
addStringToTable(str, no_color)
|
||||
end
|
||||
|
||||
return resultTable
|
||||
end
|
||||
|
||||
local color_tag = Color(0, 187, 255)
|
||||
|
||||
function VyHub.Util:print_chat(ply, message, tag, color)
|
||||
color = color or color_white
|
||||
|
||||
if SERVER then
|
||||
if IsValid(ply) then
|
||||
if not VyHub.Config.chat_tag then
|
||||
VyHub.Config.chat_tag = "[VyHub] "
|
||||
end
|
||||
|
||||
if not tag then
|
||||
tag = VyHub.Config.chat_tag
|
||||
end
|
||||
|
||||
message = string.Replace(message, '\r', '')
|
||||
message = string.Replace(message, '\n', '')
|
||||
|
||||
net.Start("vyhub_print_chat")
|
||||
net.WriteString(message)
|
||||
net.WriteString(tag)
|
||||
net.WriteColor(color)
|
||||
net.Send(ply)
|
||||
end
|
||||
elseif CLIENT then
|
||||
msg_table = VyHub.Util:replace_colors(message, color)
|
||||
|
||||
chat.AddText(color_tag, tag, color_white, unpack(msg_table))
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:print_chat_steamid(steamid, message, tag, color)
|
||||
if steamid != nil and steamid != false then
|
||||
local ply = player.GetBySteamID64(steamid)
|
||||
|
||||
if IsValid(ply) then
|
||||
VyHub.Util:print_chat(ply, message, tag, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:play_sound_steamid(steamid, url)
|
||||
if steamid then
|
||||
local ply = player.GetBySteamID64(steamid)
|
||||
|
||||
if IsValid(ply) then
|
||||
return VyHub.Util:play_sound(ply, url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:play_sound(ply, url)
|
||||
if SERVER then
|
||||
if IsValid(ply) then
|
||||
net.Start("vyhub_play_sound")
|
||||
net.WriteString(url)
|
||||
net.Send(ply)
|
||||
end
|
||||
elseif CLIENT then
|
||||
sound.PlayURL ( url, "", function() end)
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:open_url(ply, url)
|
||||
if SERVER then
|
||||
if IsValid(ply) then
|
||||
net.Start("vyhub_open_url")
|
||||
net.WriteString(url)
|
||||
net.Send(ply)
|
||||
end
|
||||
elseif CLIENT then
|
||||
gui.OpenURL(url)
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:print_chat_all(message, tag, color)
|
||||
for _, ply in ipairs(player.GetHumans()) do
|
||||
VyHub.Util:print_chat(ply, message, tag, color)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function VyHub.Util:get_player_by_nick(nick)
|
||||
nick = string.lower(nick);
|
||||
|
||||
for _,v in ipairs(player.GetHumans()) do
|
||||
if(string.find(string.lower(v:Name()), nick, 1, true) != nil)
|
||||
then return v;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function VyHub.Util:hex2rgb(hex)
|
||||
hex = hex:gsub("#","")
|
||||
if(string.len(hex) == 3) then
|
||||
return Color(tonumber("0x"..hex:sub(1,1)) * 17, tonumber("0x"..hex:sub(2,2)) * 17, tonumber("0x"..hex:sub(3,3)) * 17)
|
||||
elseif(string.len(hex) == 6) then
|
||||
return Color(tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6)))
|
||||
else
|
||||
return color_white
|
||||
end
|
||||
end
|
||||
|
||||
function VyHub.Util:iso_ts_to_local_str(iso_ts)
|
||||
local bias = VyHub.Config.time_offset != nil and -math.Round(VyHub.Config.time_offset * 60 * 60) or nil
|
||||
|
||||
return date(iso_ts):setbias(bias):tolocal():fmt(VyHub.Config.date_format)
|
||||
end
|
||||
|
||||
|
||||
function VyHub.Util:invalid_str(str_list)
|
||||
for _, str in ipairs(str_list) do
|
||||
if str == nil or string.Trim(str) == "" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function VyHub.Util:escape_concommand_str(str)
|
||||
str = string.Replace(str, '"', "'")
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
|
||||
|
||||
if CLIENT then
|
||||
net.Receive("vyhub_print_chat", function ()
|
||||
local message = net.ReadString()
|
||||
local tag = net.ReadString()
|
||||
local color = net.ReadColor()
|
||||
|
||||
VyHub.Util:print_chat(nil, message, tag, color)
|
||||
end)
|
||||
|
||||
net.Receive("vyhub_play_sound", function ()
|
||||
local url = net.ReadString()
|
||||
|
||||
VyHub.Util:play_sound(nil, url)
|
||||
end)
|
||||
|
||||
net.Receive("vyhub_open_url", function ()
|
||||
local url = net.ReadString()
|
||||
|
||||
VyHub.Util:open_url(nil, url)
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user