cleaned up some namespace discrepancies
fixed the coloring for custom groups translation add reserved slots add webhook project to show notifications in discord
This commit is contained in:
parent
bbade07646
commit
a0fafe5797
1
.gitignore
vendored
1
.gitignore
vendored
@ -226,3 +226,4 @@ bootstrap-custom.min.css
|
||||
/WebfrontCore/Views/Plugins/Stats
|
||||
/WebfrontCore/wwwroot/**/dds
|
||||
|
||||
/DiscordWebhook/env
|
||||
|
@ -5,7 +5,7 @@
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
|
||||
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
|
||||
<Version>2.1.2</Version>
|
||||
<Version>2.1.4</Version>
|
||||
<Authors>RaidMax</Authors>
|
||||
<Company>Forever None</Company>
|
||||
<Product>IW4MAdmin</Product>
|
||||
|
@ -65,6 +65,12 @@ namespace IW4MAdmin.Application.Core
|
||||
|
||||
public IList<Player> GetAuthenticatedClients()
|
||||
{
|
||||
if (AuthenticatedClients.Values.Count > 18)
|
||||
{
|
||||
Program.ServerManager.GetLogger().WriteWarning($"auth client count is {AuthenticatedClients.Values.Count}, this is bad");
|
||||
return AuthenticatedClients.Values.Take(18).ToList();
|
||||
}
|
||||
|
||||
return AuthenticatedClients.Values.ToList();
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
class IW4EventParser : IEventParser
|
||||
{
|
||||
private const string SayRegex = @"(say|sayteam);(.{16,32});([0-9]+)(.*);(.*)";
|
||||
private const string SayRegex = @"(say|sayteam);(.{1,32});([0-9]+)(.*);(.*)";
|
||||
|
||||
public virtual GameEvent GetEvent(Server server, string logLine)
|
||||
{
|
||||
@ -121,7 +121,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
// join
|
||||
if (eventType == "J")
|
||||
{
|
||||
var regexMatch = Regex.Match(logLine, @"^(J;)(.{4,32});([0-9]+);(.*)$");
|
||||
var regexMatch = Regex.Match(logLine, @"^(J;)(.{1,32});([0-9]+);(.*)$");
|
||||
if (regexMatch.Success)
|
||||
{
|
||||
return new GameEvent()
|
||||
@ -141,7 +141,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
|
||||
if (eventType == "Q")
|
||||
{
|
||||
var regexMatch = Regex.Match(logLine, @"^(Q;)(.{4,32});([0-9]+);(.*)$");
|
||||
var regexMatch = Regex.Match(logLine, @"^(Q;)(.{1,32});([0-9]+);(.*)$");
|
||||
if (regexMatch.Success)
|
||||
{
|
||||
return new GameEvent()
|
||||
|
@ -39,7 +39,7 @@ namespace IW4MAdmin.Application
|
||||
|
||||
catch (Exception) { }
|
||||
|
||||
string LogLine = $"[{DateTime.Now.ToString("HH:mm:ss")}] - {stringType}: {msg}";
|
||||
string LogLine = $"[{DateTime.Now.ToString("MM.dd.yyy HH:mm:ss.fff")}] - {stringType}: {msg}";
|
||||
lock (ThreadLock)
|
||||
{
|
||||
#if DEBUG
|
||||
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Application.Misc
|
||||
namespace IW4MAdmin.Application.Misc
|
||||
{
|
||||
public class VPNCheck
|
||||
{
|
||||
|
@ -1,14 +1,13 @@
|
||||
using Application.RconParsers;
|
||||
using SharedLibraryCore.RCon;
|
||||
using SharedLibraryCore.RCon;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Application.RconParsers
|
||||
namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
class IW3RConParser : IW4RConParser
|
||||
{
|
||||
private static CommandPrefix Prefixes = new CommandPrefix()
|
||||
private static readonly CommandPrefix Prefixes = new CommandPrefix()
|
||||
{
|
||||
Tell = "tell {0} {1}",
|
||||
Say = "say {0}",
|
||||
|
@ -10,7 +10,7 @@ using SharedLibraryCore;
|
||||
using SharedLibraryCore.RCon;
|
||||
using SharedLibraryCore.Exceptions;
|
||||
|
||||
namespace Application.RconParsers
|
||||
namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
class IW4RConParser : IRConParser
|
||||
{
|
||||
@ -111,18 +111,12 @@ namespace Application.RconParsers
|
||||
Name = name,
|
||||
NetworkId = networkId,
|
||||
ClientNumber = clientNumber,
|
||||
IPAddress = ip,
|
||||
IPAddress = ip == 0 ? int.MinValue : ip,
|
||||
Ping = ping,
|
||||
Score = score,
|
||||
IsBot = ip == 0
|
||||
};
|
||||
|
||||
if (P.IsBot)
|
||||
{
|
||||
// set it to 127.0.0.2
|
||||
P.IPAddress = 33554559;
|
||||
}
|
||||
|
||||
StatusPlayers.Add(P);
|
||||
}
|
||||
}
|
||||
|
@ -2,17 +2,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text;
|
||||
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.Objects;
|
||||
using SharedLibraryCore.RCon;
|
||||
using SharedLibraryCore.Exceptions;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Application.RconParsers
|
||||
namespace IW4MAdmin.WApplication.RconParsers
|
||||
{
|
||||
public class IW5MRConParser : IRConParser
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ using System.Text;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Application.RconParsers
|
||||
namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
public class T6MRConParser : IRConParser
|
||||
{
|
||||
|
@ -14,13 +14,14 @@ using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Exceptions;
|
||||
using SharedLibraryCore.Localization;
|
||||
|
||||
using Application.Misc;
|
||||
using Application.RconParsers;
|
||||
using IW4MAdmin.Application.Misc;
|
||||
using IW4MAdmin.Application.RconParsers;
|
||||
using IW4MAdmin.Application.EventParsers;
|
||||
using IW4MAdmin.Application.IO;
|
||||
using SharedLibraryCore.Localization;
|
||||
using IW4MAdmin.Application.Core;
|
||||
using IW4MAdmin.WApplication.RconParsers;
|
||||
|
||||
namespace IW4MAdmin
|
||||
{
|
||||
@ -56,7 +57,6 @@ namespace IW4MAdmin
|
||||
|
||||
public async Task OnPlayerJoined(Player logClient)
|
||||
{
|
||||
|
||||
if (Players[logClient.ClientNumber] == null ||
|
||||
Players[logClient.ClientNumber].NetworkId != logClient.NetworkId)
|
||||
{
|
||||
@ -184,6 +184,16 @@ namespace IW4MAdmin
|
||||
player = client.AsPlayer();
|
||||
}
|
||||
|
||||
// reserved slots stuff
|
||||
if ((MaxClients - ClientNum) < ServerConfig.ReservedSlotNumber &&
|
||||
! player.IsPrivileged())
|
||||
{
|
||||
Logger.WriteDebug($"Kicking {polledPlayer} their spot is reserved");
|
||||
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, loc["SERVER_KICK_SLOT_IS_RESERVED"]);
|
||||
await this.ExecuteCommandAsync(formattedKick);
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger.WriteInfo($"Client {player} connected...");
|
||||
|
||||
// Do the player specific stuff
|
||||
@ -590,7 +600,6 @@ namespace IW4MAdmin
|
||||
|
||||
AuthQueue.AuthenticateClients(CurrentPlayers);
|
||||
|
||||
|
||||
// all polled players should be authenticated
|
||||
var addPlayerTasks = AuthQueue.GetAuthenticatedClients()
|
||||
.Select(client => AddPlayer(client));
|
||||
@ -796,7 +805,7 @@ namespace IW4MAdmin
|
||||
CustomCallback = await ScriptLoaded();
|
||||
string mainPath = EventParser.GetGameDir();
|
||||
#if DEBUG
|
||||
basepath.Value = @"D:\";
|
||||
basepath.Value = @"\\192.168.88.253\Call of Duty Black Ops II";
|
||||
#endif
|
||||
string logPath;
|
||||
if (GameName == Game.IW5)
|
||||
|
134
DiscordWebhook/DiscordWebhook.py
Normal file
134
DiscordWebhook/DiscordWebhook.py
Normal file
@ -0,0 +1,134 @@
|
||||
import requests
|
||||
import time
|
||||
import json
|
||||
import collections
|
||||
|
||||
class WebhookAuthor():
|
||||
def __init__(self, name=None, url=None, icon_url=None):
|
||||
if name:
|
||||
self.name = name
|
||||
if url:
|
||||
self.url = url
|
||||
if icon_url:
|
||||
self.icon_url = icon_url
|
||||
|
||||
class WebhookField():
|
||||
def __init__(self, name=None, value=None, inline=False):
|
||||
if name:
|
||||
self.name = name
|
||||
if value:
|
||||
self.value = value
|
||||
if inline:
|
||||
self.inline = inline
|
||||
|
||||
class WebhookEmbed():
|
||||
def __init__(self):
|
||||
self.author = ''
|
||||
self.title = ''
|
||||
self.url = ''
|
||||
self.description = ''
|
||||
self.color = 0
|
||||
self.fields = []
|
||||
self.thumbnail = {}
|
||||
|
||||
class WebhookParams():
|
||||
def __init__(self, username=None, avatar_url=None, content=None):
|
||||
self.username = ''
|
||||
self.avatar_url = ''
|
||||
self.content = ''
|
||||
self.embeds = []
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True)
|
||||
|
||||
def get_client_profile(profile_id):
|
||||
return '{}/Client/ProfileAsync/{}'.format(base_url, str(profile_id))
|
||||
|
||||
with open('config.json') as json_config_file:
|
||||
json_config = json.load(json_config_file)
|
||||
|
||||
# this should be an URL to an IP or FQN to an IW4MAdmin instance
|
||||
# ie http://127.0.0.1 or http://IW4MAdmin.com
|
||||
base_url = json_config['IW4MAdminUrl']
|
||||
end_point = '/api/event'
|
||||
request_url = base_url + end_point
|
||||
# this should be the full discord webhook url
|
||||
# ie https://discordapp.com/api/webhooks/<id>/<token>
|
||||
discord_webhook_url = json_config['DiscordWebhookUrl']
|
||||
# this should be the numerical id of the discord group
|
||||
# 12345678912345678
|
||||
notify_role_ids = json_config['NotifyRoleIds']
|
||||
|
||||
def get_new_events():
|
||||
events = []
|
||||
response = requests.get(request_url)
|
||||
data = response.json()
|
||||
|
||||
for event in data:
|
||||
# commonly used event info items
|
||||
event_type = event['eventType']['name']
|
||||
server_name = event['ownerEntity']['name']
|
||||
|
||||
webhook_item = WebhookParams()
|
||||
webhook_item_embed = WebhookEmbed()
|
||||
|
||||
webhook_item.username = 'IW4MAdmin'
|
||||
webhook_item.avatar_url = 'https://raidmax.org/IW4MAdmin/img/iw4adminicon-3.png'
|
||||
webhook_item_embed.color = 31436
|
||||
webhook_item_embed.url = base_url
|
||||
webhook_item_embed.thumbnail = { 'url' : 'https://raidmax.org/IW4MAdmin/img/iw4adminicon-3.png' }
|
||||
webhook_item.embeds.append(webhook_item_embed)
|
||||
|
||||
role_ids_string = ''
|
||||
for id in notify_role_ids:
|
||||
role_ids_string += '\r\n<@&{}>\r\n'.format(id)
|
||||
|
||||
webhook_notifyrole = WebhookField('Notifies',role_ids_string)
|
||||
|
||||
if event_type == 'Report':
|
||||
origin_client_name = event['originEntity']['name']
|
||||
origin_client_id = int(event['originEntity']['id'])
|
||||
|
||||
target_client_name = event['targetEntity']['name']
|
||||
target_client_id = int(event['targetEntity']['id'])
|
||||
|
||||
report_reason = event['extraInfo']
|
||||
|
||||
server_field = WebhookField('Server', server_name)
|
||||
report_reason_field = WebhookField('Reason', report_reason)
|
||||
reported_by_field = WebhookField('By', '[{}]({})'.format(origin_client_name, get_client_profile(origin_client_id)))
|
||||
reported_field = WebhookField('Reported Player', '[{}]({})'.format(target_client_name, get_client_profile(target_client_id)))
|
||||
|
||||
webhook_item_embed.title = 'Player Reported'
|
||||
webhook_item_embed.fields.append(server_field)
|
||||
webhook_item_embed.fields.append(reported_field)
|
||||
webhook_item_embed.fields.append(reported_by_field)
|
||||
webhook_item_embed.fields.append(report_reason_field)
|
||||
|
||||
#make sure there's at least one group to notify
|
||||
if len(notify_role_ids) > 0:
|
||||
webhook_item.content = role_ids_string
|
||||
|
||||
else:
|
||||
continue
|
||||
|
||||
events.append(webhook_item)
|
||||
|
||||
return events
|
||||
|
||||
def execute_webhook(data):
|
||||
for event in data:
|
||||
event_json = event.to_json()
|
||||
response = requests.post(discord_webhook_url, data=event_json, headers={'Content-type' : 'application/json'})
|
||||
|
||||
def run():
|
||||
while True:
|
||||
try:
|
||||
new_events = get_new_events()
|
||||
execute_webhook(new_events)
|
||||
except:
|
||||
print('failed to get new events')
|
||||
time.sleep(2.5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
50
DiscordWebhook/DiscordWebhook.pyproj
Normal file
50
DiscordWebhook/DiscordWebhook.pyproj
Normal file
@ -0,0 +1,50 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>15a81d6e-7502-46ce-8530-0647a380b5f4</ProjectGuid>
|
||||
<ProjectHome>.</ProjectHome>
|
||||
<StartupFile>DiscordWebhook.py</StartupFile>
|
||||
<SearchPath>
|
||||
</SearchPath>
|
||||
<WorkingDirectory>.</WorkingDirectory>
|
||||
<OutputPath>.</OutputPath>
|
||||
<Name>DiscordWebhook</Name>
|
||||
<RootNamespace>DiscordWebhook</RootNamespace>
|
||||
<InterpreterId>MSBuild|env|$(MSBuildProjectFullPath)</InterpreterId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DiscordWebhook.py" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Interpreter Include="env\">
|
||||
<Id>env</Id>
|
||||
<Version>3.6</Version>
|
||||
<Description>env (Python 3.6 (64-bit))</Description>
|
||||
<InterpreterPath>Scripts\python.exe</InterpreterPath>
|
||||
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
|
||||
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
|
||||
<Architecture>X64</Architecture>
|
||||
</Interpreter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="config.json" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
|
||||
<!-- Uncomment the CoreCompile target to enable the Build command in
|
||||
Visual Studio and specify your pre- and post-build commands in
|
||||
the BeforeBuild and AfterBuild targets below. -->
|
||||
<!--<Target Name="CoreCompile" />-->
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
</Project>
|
5
DiscordWebhook/config.json
Normal file
5
DiscordWebhook/config.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"IW4MAdminUrl": "",
|
||||
"DiscordWebhookUrl": "",
|
||||
"NotifyRoleIds": []
|
||||
}
|
@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Plugins\Tests\Test
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IW4ScriptCommands", "Plugins\IW4ScriptCommands\IW4ScriptCommands.csproj", "{6C706CE5-A206-4E46-8712-F8C48D526091}"
|
||||
EndProject
|
||||
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "DiscordWebhook", "DiscordWebhook\DiscordWebhook.pyproj", "{15A81D6E-7502-46CE-8530-0647A380B5F4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -287,6 +289,18 @@ Global
|
||||
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.Build.0 = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|x64.ActiveCfg = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|x86.ActiveCfg = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -411,14 +411,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
kill.DeathType == IW4Info.MeansOfDeath.MOD_HEAD_SHOT)
|
||||
{
|
||||
clientStats.HitLocations.Single(hl => hl.Location == kill.HitLoc).HitCount += 1;
|
||||
|
||||
//statsSvc.ClientStatSvc.Update(clientStats);
|
||||
// await statsSvc.ClientStatSvc.SaveChangesAsync();
|
||||
}
|
||||
|
||||
//statsSvc.KillStatsSvc.Insert(kill);
|
||||
//await statsSvc.KillStatsSvc.SaveChangesAsync();
|
||||
|
||||
if (Plugin.Config.Configuration().EnableAntiCheat)
|
||||
{
|
||||
async Task executePenalty(Cheat.DetectionPenaltyResult penalty)
|
||||
|
@ -14,6 +14,7 @@ namespace SharedLibraryCore.Configuration
|
||||
public bool UseT6MParser { get; set; }
|
||||
public bool UseIW5MParser { get; set; }
|
||||
public string ManualLogPath { get; set; }
|
||||
public int ReservedSlotNumber { get; set; }
|
||||
|
||||
public IBaseConfiguration Generate()
|
||||
{
|
||||
@ -46,6 +47,8 @@ namespace SharedLibraryCore.Configuration
|
||||
if (UseIW5MParser)
|
||||
ManualLogPath = Utilities.PromptString(loc["SETUP_SERVER_MANUALLOG"]);
|
||||
|
||||
ReservedSlotNumber = loc["SETUP_SERVER_RESERVEDSLOT"].PromptInt(0, 32);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ namespace SharedLibraryCore.Dtos
|
||||
public string PunisherName { get; set; }
|
||||
public int PunisherId { get; set; }
|
||||
public string PunisherLevel { get; set; }
|
||||
public int PunisherLevelId { get; set; }
|
||||
public string Offense { get; set; }
|
||||
public string AutomatedOffense { get; set; }
|
||||
public string Type { get; set; }
|
||||
|
@ -199,7 +199,8 @@ namespace SharedLibraryCore
|
||||
return id;
|
||||
var bot = Regex.Match(str, @"bot[0-9]+").Value;
|
||||
if (!string.IsNullOrEmpty(bot))
|
||||
return -1;//Convert.ToInt64(bot.Substring(3)) + 1;
|
||||
// should set their GUID to the negation of their 1 based index (-1 - -18)
|
||||
return -(Convert.ToInt64(bot.Substring(3)) + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -365,7 +366,7 @@ namespace SharedLibraryCore
|
||||
CurrentAlias = client.CurrentAlias,
|
||||
CurrentAliasId = client.CurrentAlias.AliasId,
|
||||
// todo: make sure this is up to date
|
||||
IsBot = client.NetworkId == -1,
|
||||
IsBot = client.IPAddress == int.MinValue,
|
||||
Password = client.Password,
|
||||
PasswordSalt = client.PasswordSalt
|
||||
};
|
||||
@ -379,6 +380,33 @@ namespace SharedLibraryCore
|
||||
return (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// prompt user to enter a number
|
||||
/// </summary>
|
||||
/// <param name="question">question to prompt with</param>
|
||||
/// <param name="maxValue">maximum value to allow</param>
|
||||
/// <param name="minValue">minimum value to allow</param>
|
||||
/// <returns>integer from user's input</returns>
|
||||
public static int PromptInt(this string question, int minValue = 0, int maxValue = int.MaxValue)
|
||||
{
|
||||
Console.Write($"{question}: ");
|
||||
int response;
|
||||
|
||||
while (!int.TryParse(Console.ReadLine(), out response) ||
|
||||
response < minValue ||
|
||||
response > maxValue)
|
||||
{
|
||||
string range = "";
|
||||
if (minValue != 0 || maxValue != int.MaxValue)
|
||||
{
|
||||
range = $" [{minValue}-{maxValue}]";
|
||||
}
|
||||
Console.Write($"Please enter a valid number{range}: ");
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static string PromptString(string question)
|
||||
{
|
||||
string response;
|
||||
@ -455,6 +483,5 @@ namespace SharedLibraryCore
|
||||
var response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
|
||||
return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SharedLibraryCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -39,8 +40,8 @@ namespace WebfrontCore.Controllers.API
|
||||
player.Ping,
|
||||
State = player.State.ToString(),
|
||||
player.ClientNumber,
|
||||
ConnectionTime = (DateTime.UtcNow - player.ConnectionTime).TotalSeconds,
|
||||
player.Level,
|
||||
ConnectionTime = Math.Round((DateTime.UtcNow - player.ConnectionTime).TotalSeconds, 0),
|
||||
Level = player.Level.ToLocalizedLevelName(),
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -21,6 +21,7 @@ namespace WebfrontCore.ViewComponents
|
||||
PunisherId = p.PunisherId,
|
||||
PunisherName = p.Punisher.Name,
|
||||
PunisherLevel = p.Punisher.Level.ToLocalizedLevelName(),
|
||||
PunisherLevelId = (int)p.Punisher.Level,
|
||||
#if DEBUG
|
||||
Offense = !string.IsNullOrEmpty(p.AutomatedOffense) ? p.AutomatedOffense : p.Offense,
|
||||
#else
|
||||
|
@ -16,7 +16,7 @@
|
||||
{
|
||||
<div class="row pt-2 pb-2 bg-dark">
|
||||
<div class="col-5">@Html.ActionLink(client.Name, "ProfileAsync", "Client", new { id = client.ClientId })</div>
|
||||
<div class="col-4 level-color-@client.Level.ToLower()">@client.Level</div>
|
||||
<div class="col-4 level-color-@client.LevelInt">@client.Level</div>
|
||||
<div class="col-3 text-right">@client.LastSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"]</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
<div id="profile_wrapper" class="row d-flex d-sm-inline-flex justify-content-center justify-content-left pb-3">
|
||||
<div class="mr-auto ml-auto ml-sm-0 mr-sm-0">
|
||||
<div id="profile_avatar" class="mb-4 mb-md-0 text-center level-bgcolor-@Model.Level.ToLower()" style="background-image:url('@string.Format("https://gravatar.com/avatar/{0}?size=168&default=blank&rating=pg", gravatarUrl)">
|
||||
<div id="profile_avatar" class="mb-4 mb-md-0 text-center level-bgcolor-@Model.LevelInt" style="background-image:url('@string.Format("https://gravatar.com/avatar/{0}?size=168&default=blank&rating=pg", gravatarUrl)">
|
||||
@if (string.IsNullOrEmpty(gravatarUrl))
|
||||
{
|
||||
<span class="profile-shortcode">@shortCode</span>
|
||||
@ -71,7 +71,7 @@
|
||||
}
|
||||
</div>
|
||||
<div id="profile_level" class="text-muted mb-2">
|
||||
<h5><span class="level-color-@Model.Level.ToLower()"><strong>@Model.Level</strong></span></h5>
|
||||
<h5><span class="level-color-@Model.LevelInt"><strong>@Model.Level</strong></span></h5>
|
||||
</div>
|
||||
<div id="profile_time_played" class="text-muted">
|
||||
@loc["WEBFRONT_PROFILE_PLAYER"] <span class="text-primary">@Model.TimePlayed</span> @loc["GLOBAL_TIME_HOURS"]
|
||||
|
@ -29,7 +29,7 @@
|
||||
<tr class="d-table-row d-md-none bg-dark">
|
||||
<th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_ADMIN"]</th>
|
||||
<td>
|
||||
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + Model.PunisherLevel.ToLower() })
|
||||
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + Model.PunisherLevelId }) })
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
@Model.Offense
|
||||
</td>
|
||||
<td>
|
||||
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + Model.PunisherLevel.ToLower() })
|
||||
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + Model.PunisherLevelId }) })
|
||||
</td>
|
||||
<td class="text-right text-light">
|
||||
@{
|
||||
|
@ -36,7 +36,7 @@
|
||||
@{
|
||||
for (int i = 0; i < half; i++)
|
||||
{
|
||||
string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].Level.ToLower()}";
|
||||
string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}";
|
||||
<span>@Html.ActionLink(Model.Players[i].Name, "ProfileAsync", "Client", new { id = Model.Players[i].ClientId }, new { @class = levelColorClass })</span><br />
|
||||
}
|
||||
}
|
||||
@ -45,7 +45,7 @@
|
||||
@{
|
||||
for (int i = half; i < Model.ClientCount; i++)
|
||||
{
|
||||
string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].Level.ToLower()}";
|
||||
string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}";
|
||||
<span>@Html.ActionLink(Model.Players[i].Name, "ProfileAsync", "Client", new { id = Model.Players[i].ClientId }, new { @class = levelColorClass })</span><br />
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
<None Include="wwwroot\css\global.min.css" CopyToPublishDirectory="Always" />
|
||||
<None Include="wwwroot\js\global.min.js" CopyToPublishDirectory="Always" />
|
||||
<None Include="wwwroot\images\icon.png" CopyToPublishDirectory="Always" />
|
||||
<None Include="wwwroot\images\icons\**\*.png" CopyToPublishDirectory="Always"/>
|
||||
<None Include="wwwroot\lib\open-iconic\font\fonts\open-iconic.ttf" CopyToPublishDirectory="Always" />
|
||||
<None Include="wwwroot\lib\open-iconic\font\fonts\open-iconic.woff" CopyToPublishDirectory="Always" />
|
||||
<None Include="wwwroot\lib\open-iconic\font\fonts\open-iconic.otf" CopyToPublishDirectory="Always" />
|
||||
|
@ -2,81 +2,81 @@
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
.level-color-user, .level-color-guest {
|
||||
.level-color-user, .level-color-guest, .level-color-0 {
|
||||
color: #6c757d;
|
||||
color: rgba(255, 255, 255, 0.68);
|
||||
}
|
||||
|
||||
.level-bgcolor-user, .level-bgcolor-guest {
|
||||
.level-bgcolor-user, .level-bgcolor-guest, .level-bgcolor-0 {
|
||||
background-color: #6c757d;
|
||||
background-color: rgba(255, 255, 255, 0.68);
|
||||
}
|
||||
|
||||
.level-color-trusted {
|
||||
.level-color-trusted, .level-color-2 {
|
||||
color: #749363;
|
||||
color: rgba(116,147,99,1);
|
||||
}
|
||||
|
||||
.level-bgcolor-trusted {
|
||||
.level-bgcolor-trusted, .level-bgcolor-2 {
|
||||
background-color: #749363;
|
||||
background-color: rgba(116,147,99,1);
|
||||
}
|
||||
|
||||
.level-color-flagged {
|
||||
.level-color-flagged, .level-color-1 {
|
||||
color: #fd9c38;
|
||||
color: rgba(253, 139, 22, 0.85);
|
||||
}
|
||||
|
||||
.level-bgcolor-flagged {
|
||||
.level-bgcolor-flagged, .level-bgcolor-1 {
|
||||
background-color: #fd9c38;
|
||||
background-color: rgba(253, 139, 22, 0.85);
|
||||
}
|
||||
|
||||
.level-color-banned, .level-color-console {
|
||||
.level-color-banned, .level-color-console, .level-color--1 {
|
||||
color: #ff6060;
|
||||
color: rgba(255, 69, 69, 0.85);
|
||||
}
|
||||
|
||||
.level-bgcolor-banned {
|
||||
.level-bgcolor-banned, .level-bgcolor--1 {
|
||||
background-color: #ff6060;
|
||||
background-color: rgba(255, 69, 69, 0.85);
|
||||
}
|
||||
|
||||
.level-color-moderator {
|
||||
.level-color-moderator, .level-color-3 {
|
||||
color: #f0de8b;
|
||||
color: rgba(235, 211, 101, 0.75);
|
||||
}
|
||||
|
||||
.level-bgcolor-moderator {
|
||||
.level-bgcolor-moderator, .level-bgcolor-3 {
|
||||
background-color: #f0de8b;
|
||||
background-color: rgba(235, 211, 101, 0.75);
|
||||
}
|
||||
|
||||
.level-color-administrator {
|
||||
.level-color-administrator, .level-color-4 {
|
||||
color: #f1a8e8;
|
||||
color: rgba(236, 130, 222, 0.69);
|
||||
}
|
||||
|
||||
.level-bgcolor-administrator {
|
||||
.level-bgcolor-administrator, .level.bgcolor-4 {
|
||||
background-color: #f1a8e8;
|
||||
background-color: rgba(236, 130, 222, 0.69);
|
||||
}
|
||||
|
||||
.level-color-senioradmin {
|
||||
.level-color-senioradmin, .level-color-5 {
|
||||
color: #50bcc3;
|
||||
color: rgba(50, 177, 185, 0.85);
|
||||
}
|
||||
|
||||
.level-bgcolor-senioradmin {
|
||||
.level-bgcolor-senioradmin, .level-bgcolor-5 {
|
||||
background-color: #50bcc3;
|
||||
background-color: rgba(50, 177, 185, 0.85);
|
||||
}
|
||||
|
||||
.level-color-owner {
|
||||
.level-color-owner, .level-color-6 {
|
||||
color: rgb(0, 122, 204);
|
||||
}
|
||||
|
||||
.level-bgcolor-owner {
|
||||
.level-bgcolor-owner, .level-bgcolor-6 {
|
||||
background-color: rgb(0, 122, 204);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user