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/Views/Plugins/Stats
|
||||||
/WebfrontCore/wwwroot/**/dds
|
/WebfrontCore/wwwroot/**/dds
|
||||||
|
|
||||||
|
/DiscordWebhook/env
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
|
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
|
||||||
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
|
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
|
||||||
<Version>2.1.2</Version>
|
<Version>2.1.4</Version>
|
||||||
<Authors>RaidMax</Authors>
|
<Authors>RaidMax</Authors>
|
||||||
<Company>Forever None</Company>
|
<Company>Forever None</Company>
|
||||||
<Product>IW4MAdmin</Product>
|
<Product>IW4MAdmin</Product>
|
||||||
|
@ -65,6 +65,12 @@ namespace IW4MAdmin.Application.Core
|
|||||||
|
|
||||||
public IList<Player> GetAuthenticatedClients()
|
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();
|
return AuthenticatedClients.Values.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
class IW4EventParser : IEventParser
|
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)
|
public virtual GameEvent GetEvent(Server server, string logLine)
|
||||||
{
|
{
|
||||||
@ -121,7 +121,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
// join
|
// join
|
||||||
if (eventType == "J")
|
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)
|
if (regexMatch.Success)
|
||||||
{
|
{
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
@ -141,7 +141,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
|
|
||||||
if (eventType == "Q")
|
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)
|
if (regexMatch.Success)
|
||||||
{
|
{
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
|
@ -39,7 +39,7 @@ namespace IW4MAdmin.Application
|
|||||||
|
|
||||||
catch (Exception) { }
|
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)
|
lock (ThreadLock)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Application.Misc
|
namespace IW4MAdmin.Application.Misc
|
||||||
{
|
{
|
||||||
public class VPNCheck
|
public class VPNCheck
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
using Application.RconParsers;
|
using SharedLibraryCore.RCon;
|
||||||
using SharedLibraryCore.RCon;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Application.RconParsers
|
namespace IW4MAdmin.Application.RconParsers
|
||||||
{
|
{
|
||||||
class IW3RConParser : IW4RConParser
|
class IW3RConParser : IW4RConParser
|
||||||
{
|
{
|
||||||
private static CommandPrefix Prefixes = new CommandPrefix()
|
private static readonly CommandPrefix Prefixes = new CommandPrefix()
|
||||||
{
|
{
|
||||||
Tell = "tell {0} {1}",
|
Tell = "tell {0} {1}",
|
||||||
Say = "say {0}",
|
Say = "say {0}",
|
||||||
|
@ -10,7 +10,7 @@ using SharedLibraryCore;
|
|||||||
using SharedLibraryCore.RCon;
|
using SharedLibraryCore.RCon;
|
||||||
using SharedLibraryCore.Exceptions;
|
using SharedLibraryCore.Exceptions;
|
||||||
|
|
||||||
namespace Application.RconParsers
|
namespace IW4MAdmin.Application.RconParsers
|
||||||
{
|
{
|
||||||
class IW4RConParser : IRConParser
|
class IW4RConParser : IRConParser
|
||||||
{
|
{
|
||||||
@ -111,18 +111,12 @@ namespace Application.RconParsers
|
|||||||
Name = name,
|
Name = name,
|
||||||
NetworkId = networkId,
|
NetworkId = networkId,
|
||||||
ClientNumber = clientNumber,
|
ClientNumber = clientNumber,
|
||||||
IPAddress = ip,
|
IPAddress = ip == 0 ? int.MinValue : ip,
|
||||||
Ping = ping,
|
Ping = ping,
|
||||||
Score = score,
|
Score = score,
|
||||||
IsBot = ip == 0
|
IsBot = ip == 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (P.IsBot)
|
|
||||||
{
|
|
||||||
// set it to 127.0.0.2
|
|
||||||
P.IPAddress = 33554559;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusPlayers.Add(P);
|
StatusPlayers.Add(P);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
using SharedLibraryCore.Objects;
|
using SharedLibraryCore.Objects;
|
||||||
using SharedLibraryCore.RCon;
|
using SharedLibraryCore.RCon;
|
||||||
using SharedLibraryCore.Exceptions;
|
using SharedLibraryCore.Exceptions;
|
||||||
using System.Text;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace Application.RconParsers
|
namespace IW4MAdmin.WApplication.RconParsers
|
||||||
{
|
{
|
||||||
public class IW5MRConParser : IRConParser
|
public class IW5MRConParser : IRConParser
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ using System.Text;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace Application.RconParsers
|
namespace IW4MAdmin.Application.RconParsers
|
||||||
{
|
{
|
||||||
public class T6MRConParser : IRConParser
|
public class T6MRConParser : IRConParser
|
||||||
{
|
{
|
||||||
|
@ -14,13 +14,14 @@ using SharedLibraryCore.Database.Models;
|
|||||||
using SharedLibraryCore.Dtos;
|
using SharedLibraryCore.Dtos;
|
||||||
using SharedLibraryCore.Configuration;
|
using SharedLibraryCore.Configuration;
|
||||||
using SharedLibraryCore.Exceptions;
|
using SharedLibraryCore.Exceptions;
|
||||||
|
using SharedLibraryCore.Localization;
|
||||||
|
|
||||||
using Application.Misc;
|
using IW4MAdmin.Application.Misc;
|
||||||
using Application.RconParsers;
|
using IW4MAdmin.Application.RconParsers;
|
||||||
using IW4MAdmin.Application.EventParsers;
|
using IW4MAdmin.Application.EventParsers;
|
||||||
using IW4MAdmin.Application.IO;
|
using IW4MAdmin.Application.IO;
|
||||||
using SharedLibraryCore.Localization;
|
|
||||||
using IW4MAdmin.Application.Core;
|
using IW4MAdmin.Application.Core;
|
||||||
|
using IW4MAdmin.WApplication.RconParsers;
|
||||||
|
|
||||||
namespace IW4MAdmin
|
namespace IW4MAdmin
|
||||||
{
|
{
|
||||||
@ -56,7 +57,6 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
public async Task OnPlayerJoined(Player logClient)
|
public async Task OnPlayerJoined(Player logClient)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Players[logClient.ClientNumber] == null ||
|
if (Players[logClient.ClientNumber] == null ||
|
||||||
Players[logClient.ClientNumber].NetworkId != logClient.NetworkId)
|
Players[logClient.ClientNumber].NetworkId != logClient.NetworkId)
|
||||||
{
|
{
|
||||||
@ -184,6 +184,16 @@ namespace IW4MAdmin
|
|||||||
player = client.AsPlayer();
|
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...");
|
Logger.WriteInfo($"Client {player} connected...");
|
||||||
|
|
||||||
// Do the player specific stuff
|
// Do the player specific stuff
|
||||||
@ -590,7 +600,6 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
AuthQueue.AuthenticateClients(CurrentPlayers);
|
AuthQueue.AuthenticateClients(CurrentPlayers);
|
||||||
|
|
||||||
|
|
||||||
// all polled players should be authenticated
|
// all polled players should be authenticated
|
||||||
var addPlayerTasks = AuthQueue.GetAuthenticatedClients()
|
var addPlayerTasks = AuthQueue.GetAuthenticatedClients()
|
||||||
.Select(client => AddPlayer(client));
|
.Select(client => AddPlayer(client));
|
||||||
@ -796,7 +805,7 @@ namespace IW4MAdmin
|
|||||||
CustomCallback = await ScriptLoaded();
|
CustomCallback = await ScriptLoaded();
|
||||||
string mainPath = EventParser.GetGameDir();
|
string mainPath = EventParser.GetGameDir();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
basepath.Value = @"D:\";
|
basepath.Value = @"\\192.168.88.253\Call of Duty Black Ops II";
|
||||||
#endif
|
#endif
|
||||||
string logPath;
|
string logPath;
|
||||||
if (GameName == Game.IW5)
|
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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IW4ScriptCommands", "Plugins\IW4ScriptCommands\IW4ScriptCommands.csproj", "{6C706CE5-A206-4E46-8712-F8C48D526091}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IW4ScriptCommands", "Plugins\IW4ScriptCommands\IW4ScriptCommands.csproj", "{6C706CE5-A206-4E46-8712-F8C48D526091}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "DiscordWebhook", "DiscordWebhook\DiscordWebhook.pyproj", "{15A81D6E-7502-46CE-8530-0647A380B5F4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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|x64.Build.0 = Release|Any CPU
|
||||||
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.ActiveCfg = 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
|
{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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -411,14 +411,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
kill.DeathType == IW4Info.MeansOfDeath.MOD_HEAD_SHOT)
|
kill.DeathType == IW4Info.MeansOfDeath.MOD_HEAD_SHOT)
|
||||||
{
|
{
|
||||||
clientStats.HitLocations.Single(hl => hl.Location == kill.HitLoc).HitCount += 1;
|
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)
|
if (Plugin.Config.Configuration().EnableAntiCheat)
|
||||||
{
|
{
|
||||||
async Task executePenalty(Cheat.DetectionPenaltyResult penalty)
|
async Task executePenalty(Cheat.DetectionPenaltyResult penalty)
|
||||||
|
@ -14,6 +14,7 @@ namespace SharedLibraryCore.Configuration
|
|||||||
public bool UseT6MParser { get; set; }
|
public bool UseT6MParser { get; set; }
|
||||||
public bool UseIW5MParser { get; set; }
|
public bool UseIW5MParser { get; set; }
|
||||||
public string ManualLogPath { get; set; }
|
public string ManualLogPath { get; set; }
|
||||||
|
public int ReservedSlotNumber { get; set; }
|
||||||
|
|
||||||
public IBaseConfiguration Generate()
|
public IBaseConfiguration Generate()
|
||||||
{
|
{
|
||||||
@ -46,6 +47,8 @@ namespace SharedLibraryCore.Configuration
|
|||||||
if (UseIW5MParser)
|
if (UseIW5MParser)
|
||||||
ManualLogPath = Utilities.PromptString(loc["SETUP_SERVER_MANUALLOG"]);
|
ManualLogPath = Utilities.PromptString(loc["SETUP_SERVER_MANUALLOG"]);
|
||||||
|
|
||||||
|
ReservedSlotNumber = loc["SETUP_SERVER_RESERVEDSLOT"].PromptInt(0, 32);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ namespace SharedLibraryCore.Dtos
|
|||||||
public string PunisherName { get; set; }
|
public string PunisherName { get; set; }
|
||||||
public int PunisherId { get; set; }
|
public int PunisherId { get; set; }
|
||||||
public string PunisherLevel { get; set; }
|
public string PunisherLevel { get; set; }
|
||||||
|
public int PunisherLevelId { get; set; }
|
||||||
public string Offense { get; set; }
|
public string Offense { get; set; }
|
||||||
public string AutomatedOffense { get; set; }
|
public string AutomatedOffense { get; set; }
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
@ -199,7 +199,8 @@ namespace SharedLibraryCore
|
|||||||
return id;
|
return id;
|
||||||
var bot = Regex.Match(str, @"bot[0-9]+").Value;
|
var bot = Regex.Match(str, @"bot[0-9]+").Value;
|
||||||
if (!string.IsNullOrEmpty(bot))
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +366,7 @@ namespace SharedLibraryCore
|
|||||||
CurrentAlias = client.CurrentAlias,
|
CurrentAlias = client.CurrentAlias,
|
||||||
CurrentAliasId = client.CurrentAlias.AliasId,
|
CurrentAliasId = client.CurrentAlias.AliasId,
|
||||||
// todo: make sure this is up to date
|
// todo: make sure this is up to date
|
||||||
IsBot = client.NetworkId == -1,
|
IsBot = client.IPAddress == int.MinValue,
|
||||||
Password = client.Password,
|
Password = client.Password,
|
||||||
PasswordSalt = client.PasswordSalt
|
PasswordSalt = client.PasswordSalt
|
||||||
};
|
};
|
||||||
@ -379,6 +380,33 @@ namespace SharedLibraryCore
|
|||||||
return (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y';
|
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)
|
public static string PromptString(string question)
|
||||||
{
|
{
|
||||||
string response;
|
string response;
|
||||||
@ -455,6 +483,5 @@ namespace SharedLibraryCore
|
|||||||
var response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
|
var response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
|
||||||
return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
|
return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using SharedLibraryCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -39,8 +40,8 @@ namespace WebfrontCore.Controllers.API
|
|||||||
player.Ping,
|
player.Ping,
|
||||||
State = player.State.ToString(),
|
State = player.State.ToString(),
|
||||||
player.ClientNumber,
|
player.ClientNumber,
|
||||||
ConnectionTime = (DateTime.UtcNow - player.ConnectionTime).TotalSeconds,
|
ConnectionTime = Math.Round((DateTime.UtcNow - player.ConnectionTime).TotalSeconds, 0),
|
||||||
player.Level,
|
Level = player.Level.ToLocalizedLevelName(),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ namespace WebfrontCore.ViewComponents
|
|||||||
PunisherId = p.PunisherId,
|
PunisherId = p.PunisherId,
|
||||||
PunisherName = p.Punisher.Name,
|
PunisherName = p.Punisher.Name,
|
||||||
PunisherLevel = p.Punisher.Level.ToLocalizedLevelName(),
|
PunisherLevel = p.Punisher.Level.ToLocalizedLevelName(),
|
||||||
|
PunisherLevelId = (int)p.Punisher.Level,
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Offense = !string.IsNullOrEmpty(p.AutomatedOffense) ? p.AutomatedOffense : p.Offense,
|
Offense = !string.IsNullOrEmpty(p.AutomatedOffense) ? p.AutomatedOffense : p.Offense,
|
||||||
#else
|
#else
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
{
|
{
|
||||||
<div class="row pt-2 pb-2 bg-dark">
|
<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-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 class="col-3 text-right">@client.LastSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"]</div>
|
||||||
</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 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 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))
|
@if (string.IsNullOrEmpty(gravatarUrl))
|
||||||
{
|
{
|
||||||
<span class="profile-shortcode">@shortCode</span>
|
<span class="profile-shortcode">@shortCode</span>
|
||||||
@ -71,7 +71,7 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div id="profile_level" class="text-muted mb-2">
|
<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>
|
||||||
<div id="profile_time_played" class="text-muted">
|
<div id="profile_time_played" class="text-muted">
|
||||||
@loc["WEBFRONT_PROFILE_PLAYER"] <span class="text-primary">@Model.TimePlayed</span> @loc["GLOBAL_TIME_HOURS"]
|
@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">
|
<tr class="d-table-row d-md-none bg-dark">
|
||||||
<th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_ADMIN"]</th>
|
<th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_ADMIN"]</th>
|
||||||
<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>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@ -60,7 +60,7 @@
|
|||||||
@Model.Offense
|
@Model.Offense
|
||||||
</td>
|
</td>
|
||||||
<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>
|
||||||
<td class="text-right text-light">
|
<td class="text-right text-light">
|
||||||
@{
|
@{
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
@{
|
@{
|
||||||
for (int i = 0; i < half; i++)
|
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 />
|
<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++)
|
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 />
|
<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\css\global.min.css" CopyToPublishDirectory="Always" />
|
||||||
<None Include="wwwroot\js\global.min.js" CopyToPublishDirectory="Always" />
|
<None Include="wwwroot\js\global.min.js" CopyToPublishDirectory="Always" />
|
||||||
<None Include="wwwroot\images\icon.png" 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.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.woff" CopyToPublishDirectory="Always" />
|
||||||
<None Include="wwwroot\lib\open-iconic\font\fonts\open-iconic.otf" CopyToPublishDirectory="Always" />
|
<None Include="wwwroot\lib\open-iconic\font\fonts\open-iconic.otf" CopyToPublishDirectory="Always" />
|
||||||
|
@ -2,81 +2,81 @@
|
|||||||
background-color: grey;
|
background-color: grey;
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-color-user, .level-color-guest {
|
.level-color-user, .level-color-guest, .level-color-0 {
|
||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
color: rgba(255, 255, 255, 0.68);
|
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: #6c757d;
|
||||||
background-color: rgba(255, 255, 255, 0.68);
|
background-color: rgba(255, 255, 255, 0.68);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-color-trusted {
|
.level-color-trusted, .level-color-2 {
|
||||||
color: #749363;
|
color: #749363;
|
||||||
color: rgba(116,147,99,1);
|
color: rgba(116,147,99,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-bgcolor-trusted {
|
.level-bgcolor-trusted, .level-bgcolor-2 {
|
||||||
background-color: #749363;
|
background-color: #749363;
|
||||||
background-color: rgba(116,147,99,1);
|
background-color: rgba(116,147,99,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-color-flagged {
|
.level-color-flagged, .level-color-1 {
|
||||||
color: #fd9c38;
|
color: #fd9c38;
|
||||||
color: rgba(253, 139, 22, 0.85);
|
color: rgba(253, 139, 22, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-bgcolor-flagged {
|
.level-bgcolor-flagged, .level-bgcolor-1 {
|
||||||
background-color: #fd9c38;
|
background-color: #fd9c38;
|
||||||
background-color: rgba(253, 139, 22, 0.85);
|
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: #ff6060;
|
||||||
color: rgba(255, 69, 69, 0.85);
|
color: rgba(255, 69, 69, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-bgcolor-banned {
|
.level-bgcolor-banned, .level-bgcolor--1 {
|
||||||
background-color: #ff6060;
|
background-color: #ff6060;
|
||||||
background-color: rgba(255, 69, 69, 0.85);
|
background-color: rgba(255, 69, 69, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-color-moderator {
|
.level-color-moderator, .level-color-3 {
|
||||||
color: #f0de8b;
|
color: #f0de8b;
|
||||||
color: rgba(235, 211, 101, 0.75);
|
color: rgba(235, 211, 101, 0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-bgcolor-moderator {
|
.level-bgcolor-moderator, .level-bgcolor-3 {
|
||||||
background-color: #f0de8b;
|
background-color: #f0de8b;
|
||||||
background-color: rgba(235, 211, 101, 0.75);
|
background-color: rgba(235, 211, 101, 0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-color-administrator {
|
.level-color-administrator, .level-color-4 {
|
||||||
color: #f1a8e8;
|
color: #f1a8e8;
|
||||||
color: rgba(236, 130, 222, 0.69);
|
color: rgba(236, 130, 222, 0.69);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-bgcolor-administrator {
|
.level-bgcolor-administrator, .level.bgcolor-4 {
|
||||||
background-color: #f1a8e8;
|
background-color: #f1a8e8;
|
||||||
background-color: rgba(236, 130, 222, 0.69);
|
background-color: rgba(236, 130, 222, 0.69);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-color-senioradmin {
|
.level-color-senioradmin, .level-color-5 {
|
||||||
color: #50bcc3;
|
color: #50bcc3;
|
||||||
color: rgba(50, 177, 185, 0.85);
|
color: rgba(50, 177, 185, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-bgcolor-senioradmin {
|
.level-bgcolor-senioradmin, .level-bgcolor-5 {
|
||||||
background-color: #50bcc3;
|
background-color: #50bcc3;
|
||||||
background-color: rgba(50, 177, 185, 0.85);
|
background-color: rgba(50, 177, 185, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-color-owner {
|
.level-color-owner, .level-color-6 {
|
||||||
color: rgb(0, 122, 204);
|
color: rgb(0, 122, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-bgcolor-owner {
|
.level-bgcolor-owner, .level-bgcolor-6 {
|
||||||
background-color: rgb(0, 122, 204);
|
background-color: rgb(0, 122, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user