mirror of
https://github.com/RaidMax/IW4M-Admin.git
synced 2025-06-10 07:13:58 -05:00
QOL updates for profile meta
implement filterable meta for issue #158 update translations and use humanizer lib with datetime/timespan for issue #80
This commit is contained in:
@ -53,7 +53,6 @@ namespace SharedLibraryCore.Commands
|
||||
|
||||
public override Task ExecuteAsync(GameEvent E)
|
||||
{
|
||||
MetaService.Clear();
|
||||
E.Owner.Manager.Restart();
|
||||
E.Origin.Tell(_translationLookup["COMMANDS_RESTART_SUCCESS"]);
|
||||
return Task.CompletedTask;
|
||||
@ -292,7 +291,7 @@ namespace SharedLibraryCore.Commands
|
||||
switch ((await E.Target.TempBan(tempbanReason, length, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
|
||||
{
|
||||
case GameEvent.EventFailReason.None:
|
||||
E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(E.Target, length.TimeSpanText()));
|
||||
E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(E.Target, length.HumanizeForCurrentCulture()));
|
||||
break;
|
||||
case GameEvent.EventFailReason.Exception:
|
||||
E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
||||
@ -890,14 +889,9 @@ namespace SharedLibraryCore.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var P in db_players)
|
||||
foreach (var client in db_players)
|
||||
{
|
||||
// they're not going by another alias
|
||||
// /*P.AliasLink.Children.FirstOrDefault(a => a.Name.ToLower().Contains(E.Data.ToLower()))?.Name*/
|
||||
string msg = P.Name.ToLower().Contains(E.Data.ToLower()) ?
|
||||
$"[^3{P.Name}^7] [^3@{P.ClientId}^7] - [{ Utilities.ConvertLevelToColor((Permission)P.LevelInt, P.Level)}^7] - {P.IPAddress} | last seen {Utilities.GetTimePassed(P.LastConnection)}" :
|
||||
$"()->[^3{P.Name}^7] [^3@{P.ClientId}^7] - [{ Utilities.ConvertLevelToColor((Permission)P.LevelInt, P.Level)}^7] - {P.IPAddress} | last seen {Utilities.GetTimePassed(P.LastConnection)}";
|
||||
E.Origin.Tell(msg);
|
||||
E.Origin.Tell(_translationLookup["COMMANDS_FIND_FORMAT"].FormatExt(client.Name, client.ClientId, Utilities.ConvertLevelToColor((Permission)client.LevelInt, client.Level), client.IPAddress, client.LastConnectionText));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1259,7 +1253,7 @@ namespace SharedLibraryCore.Commands
|
||||
|
||||
else
|
||||
{
|
||||
string remainingTime = (penalty.Expires.Value - DateTime.UtcNow).TimeSpanText();
|
||||
string remainingTime = (penalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture();
|
||||
E.Origin.Tell(_translationLookup["COMMANDS_BANINFO_TB_SUCCESS"].FormatExt(E.Target.Name, penalty.Offense, remainingTime));
|
||||
}
|
||||
}
|
||||
@ -1543,7 +1537,9 @@ namespace SharedLibraryCore.Commands
|
||||
/// </summary>
|
||||
public class SetGravatarCommand : Command
|
||||
{
|
||||
public SetGravatarCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup)
|
||||
private readonly IMetaService _metaService;
|
||||
|
||||
public SetGravatarCommand(CommandConfiguration config, ITranslationLookup translationLookup, IMetaService metaService) : base(config, translationLookup)
|
||||
{
|
||||
Name = "setgravatar";
|
||||
Description = _translationLookup["COMMANDS_GRAVATAR_DESC"];
|
||||
@ -1558,17 +1554,17 @@ namespace SharedLibraryCore.Commands
|
||||
Required = true
|
||||
}
|
||||
};
|
||||
|
||||
_metaService = metaService;
|
||||
}
|
||||
|
||||
public override async Task ExecuteAsync(GameEvent E)
|
||||
{
|
||||
var metaSvc = new MetaService();
|
||||
|
||||
using (var md5 = MD5.Create())
|
||||
{
|
||||
string gravatarEmail = string.Concat(md5.ComputeHash(E.Data.ToLower().Select(d => Convert.ToByte(d)).ToArray())
|
||||
.Select(h => h.ToString("x2")));
|
||||
await metaSvc.AddPersistentMeta("GravatarEmail", gravatarEmail, E.Origin);
|
||||
await _metaService.AddPersistentMeta("GravatarEmail", gravatarEmail, E.Origin);
|
||||
}
|
||||
|
||||
E.Origin.Tell(_translationLookup["COMMANDS_GRAVATAR_SUCCESS_NEW"]);
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace SharedLibraryCore.Dtos
|
||||
{
|
||||
public class FindClientRequest : PaginationInfo
|
||||
public class FindClientRequest : PaginationRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// name of client
|
||||
|
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Requests
|
||||
{
|
||||
public class BaseClientMetaRequest : PaginationRequest
|
||||
{
|
||||
public int ClientId { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using SharedLibraryCore.QueryHelper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Requests
|
||||
{
|
||||
public class ReceivedPenaltyRequest : BaseClientMetaRequest
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Responses
|
||||
{
|
||||
public class AdministeredPenaltyResponse : ReceivedPenaltyResponse
|
||||
{
|
||||
}
|
||||
}
|
19
SharedLibraryCore/Dtos/Meta/Responses/BaseMetaResponse.cs
Normal file
19
SharedLibraryCore/Dtos/Meta/Responses/BaseMetaResponse.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Responses
|
||||
{
|
||||
public class BaseMetaResponse : IClientMeta, IClientMetaResponse
|
||||
{
|
||||
public int MetaId { get; set; }
|
||||
public int ClientId { get; set; }
|
||||
public MetaType Type { get; set; }
|
||||
public DateTime When { get; set; }
|
||||
public bool IsSensitive { get; set; }
|
||||
public bool ShouldDisplay { get; set; }
|
||||
public int? Column { get; set; }
|
||||
public int? Order { get; set; }
|
||||
}
|
||||
}
|
14
SharedLibraryCore/Dtos/Meta/Responses/InformationResponse.cs
Normal file
14
SharedLibraryCore/Dtos/Meta/Responses/InformationResponse.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Responses
|
||||
{
|
||||
public class InformationResponse : BaseMetaResponse
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string ToolTipText { get; set; }
|
||||
}
|
||||
}
|
12
SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs
Normal file
12
SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Responses
|
||||
{
|
||||
public class MessageResponse : BaseMetaResponse
|
||||
{
|
||||
public long ServerId { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using static SharedLibraryCore.Database.Models.EFPenalty;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Responses
|
||||
{
|
||||
public class ReceivedPenaltyResponse : BaseMetaResponse
|
||||
{
|
||||
public int PenaltyId { get; set; }
|
||||
public int OffenderClientId { get; set; }
|
||||
public string OffenderName { get; set; }
|
||||
public string PunisherName { get; set; }
|
||||
public int PunisherClientId { get; set; }
|
||||
public PenaltyType PenaltyType { get; set; }
|
||||
public string Offense { get; set; }
|
||||
public string AutomatedOffense { get; set; }
|
||||
public DateTime? ExpirationDate { get; set; }
|
||||
public string ExpiresInText => ExpirationDate.HasValue && ExpirationDate.Value > DateTime.UtcNow ? (ExpirationDate - DateTime.UtcNow).Value.HumanizeForCurrentCulture() : "";
|
||||
public string LengthText => ExpirationDate.HasValue ? (ExpirationDate.Value.AddMinutes(1) - When).HumanizeForCurrentCulture() : "";
|
||||
public bool IsLinked { get; set; }
|
||||
public int LinkedClientId { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta.Responses
|
||||
{
|
||||
public class UpdatedAliasResponse : BaseMetaResponse
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string IPAddress { get; set; } = "--";
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is UpdatedAliasResponse resp)
|
||||
{
|
||||
return resp.Name.StripColors() == Name.StripColors() && resp.IPAddress == IPAddress;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(Name.StripColors(), IPAddress);
|
||||
}
|
||||
}
|
13
SharedLibraryCore/Dtos/Meta/WebfrontTranslationHelper.cs
Normal file
13
SharedLibraryCore/Dtos/Meta/WebfrontTranslationHelper.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos.Meta
|
||||
{
|
||||
public class WebfrontTranslationHelper
|
||||
{
|
||||
public bool IsInterpolation { get; set; }
|
||||
public string MatchValue { get; set; }
|
||||
public string TranslationValue { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
namespace SharedLibraryCore.Dtos
|
||||
using System;
|
||||
|
||||
namespace SharedLibraryCore.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// pagination information holder class
|
||||
/// </summary>
|
||||
public class PaginationInfo
|
||||
public class PaginationRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// how many items to skip
|
||||
@ -24,6 +26,8 @@
|
||||
/// direction of ordering
|
||||
/// </summary>
|
||||
public SortDirection Direction { get; set; } = SortDirection.Descending;
|
||||
|
||||
public DateTime? Before { get; set; }
|
||||
}
|
||||
|
||||
public enum SortDirection
|
@ -21,8 +21,8 @@ namespace SharedLibraryCore.Dtos
|
||||
public PenaltyType PenaltyType { get; set; }
|
||||
public string PenaltyTypeText => PenaltyType.ToString();
|
||||
public DateTime TimePunished { get; set; }
|
||||
public string TimePunishedString => Utilities.GetTimePassed(TimePunished, true);
|
||||
public string TimeRemaining => DateTime.UtcNow > Expires ? "" : $"{((Expires ?? DateTime.MaxValue).Year == DateTime.MaxValue.Year ? Utilities.GetTimePassed(TimePunished, true) : Utilities.TimeSpanText((Expires ?? DateTime.MaxValue) - DateTime.UtcNow))}";
|
||||
public string TimePunishedString => TimePunished.HumanizeForCurrentCulture();
|
||||
public string TimeRemaining => DateTime.UtcNow > Expires ? "" : $"{((Expires ?? DateTime.MaxValue).Year == DateTime.MaxValue.Year ? TimePunishedString : ((Expires ?? DateTime.MaxValue) - DateTime.UtcNow).HumanizeForCurrentCulture())}";
|
||||
public bool Expired => Expires.HasValue && Expires <= DateTime.UtcNow;
|
||||
public DateTime? Expires { get; set; }
|
||||
public override bool Sensitive => PenaltyType == PenaltyType.Flag || PenaltyType == PenaltyType.Unflag;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Dtos.Meta.Responses;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Dtos
|
||||
{
|
||||
@ -19,11 +19,13 @@ namespace SharedLibraryCore.Dtos
|
||||
public bool HasActivePenalty { get; set; }
|
||||
public string ActivePenaltyType { get; set; }
|
||||
public bool Authenticated { get; set; }
|
||||
public List<ProfileMeta> Meta { get; set; }
|
||||
public List<InformationResponse> Meta { get; set; }
|
||||
public EFPenalty ActivePenalty { get; set; }
|
||||
public bool Online { get; set; }
|
||||
public string TimeOnline { get; set; }
|
||||
public DateTime LastConnection { get; set; }
|
||||
public string LastConnectionText => Utilities.GetTimePassed(LastConnection, true);
|
||||
public string LastConnectionText => (DateTime.UtcNow - LastConnection).HumanizeForCurrentCulture();
|
||||
public IDictionary<int, long> LinkedAccounts { get; set; }
|
||||
public MetaType? MetaFilterType { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Dtos
|
||||
{
|
||||
public class ProfileMeta : SharedInfo
|
||||
{
|
||||
public enum MetaType
|
||||
{
|
||||
Other,
|
||||
Information,
|
||||
AliasUpdate,
|
||||
ChatMessage,
|
||||
Penalized,
|
||||
ReceivedPenalty,
|
||||
QuickMessage
|
||||
}
|
||||
|
||||
public DateTime When { get; set; }
|
||||
public string WhenString => Utilities.GetTimePassed(When, false);
|
||||
public string Key { get; set; }
|
||||
public dynamic Value { get; set; }
|
||||
public string Extra { get; set; }
|
||||
public virtual string Class => Value.GetType().ToString();
|
||||
public MetaType Type { get; set; }
|
||||
public int? Column { get; set; }
|
||||
public int? Order { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SharedLibraryCore.Dtos.Meta.Responses;
|
||||
|
||||
namespace SharedLibraryCore.Helpers
|
||||
{
|
||||
|
@ -14,6 +14,6 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// </summary>
|
||||
/// <param name="paginationInfo">pagination info</param>
|
||||
/// <returns></returns>
|
||||
Task<IList<AuditInfo>> ListAuditInformation(PaginationInfo paginationInfo);
|
||||
Task<IList<AuditInfo>> ListAuditInformation(PaginationRequest paginationInfo);
|
||||
}
|
||||
}
|
||||
|
31
SharedLibraryCore/Interfaces/IClientMeta.cs
Normal file
31
SharedLibraryCore/Interfaces/IClientMeta.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// describes all the base attributes of a client meta object
|
||||
/// </summary>
|
||||
public interface IClientMeta
|
||||
{
|
||||
MetaType Type { get; }
|
||||
DateTime When { get; }
|
||||
|
||||
bool IsSensitive { get; }
|
||||
bool ShouldDisplay { get; }
|
||||
|
||||
// sorting purposes
|
||||
public int? Column { get; set; }
|
||||
public int? Order { get; set; }
|
||||
}
|
||||
|
||||
public enum MetaType
|
||||
{
|
||||
Other,
|
||||
Information,
|
||||
AliasUpdate,
|
||||
ChatMessage,
|
||||
Penalized,
|
||||
ReceivedPenalty,
|
||||
QuickMessage
|
||||
}
|
||||
}
|
12
SharedLibraryCore/Interfaces/IClientMetaResponse.cs
Normal file
12
SharedLibraryCore/Interfaces/IClientMetaResponse.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IClientMetaResponse
|
||||
{
|
||||
int ClientId { get;}
|
||||
int MetaId { get; }
|
||||
}
|
||||
}
|
11
SharedLibraryCore/Interfaces/IMetaRegistration.cs
Normal file
11
SharedLibraryCore/Interfaces/IMetaRegistration.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IMetaRegistration
|
||||
{
|
||||
void Register();
|
||||
}
|
||||
}
|
51
SharedLibraryCore/Interfaces/IMetaService.cs
Normal file
51
SharedLibraryCore/Interfaces/IMetaService.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.QueryHelper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IMetaService
|
||||
{
|
||||
/// <summary>
|
||||
/// adds or updates meta key and value to the database
|
||||
/// </summary>
|
||||
/// <param name="metaKey">key of meta data</param>
|
||||
/// <param name="metaValue">value of the meta data</param>
|
||||
/// <param name="client">client to save the meta for</param>
|
||||
/// <returns></returns>
|
||||
Task AddPersistentMeta(string metaKey, string metaValue, EFClient client);
|
||||
|
||||
/// <summary>
|
||||
/// retrieves meta data for given client and key
|
||||
/// </summary>
|
||||
/// <param name="metaKey">key to retrieve value for</param>
|
||||
/// <param name="client">client to retrieve meta for</param>
|
||||
/// <returns></returns>
|
||||
Task<EFMeta> GetPersistentMeta(string metaKey, EFClient client);
|
||||
|
||||
/// <summary>
|
||||
/// adds a meta task to the runtime meta list
|
||||
/// </summary>
|
||||
/// <param name="metaKey">type of meta</param>
|
||||
/// <param name="metaAction">action to perform</param>
|
||||
void AddRuntimeMeta<T,V>(MetaType metaKey, Func<T, Task<IEnumerable<V>>> metaAction) where V : IClientMeta where T: PaginationRequest;
|
||||
|
||||
/// <summary>
|
||||
/// retrieves all the runtime meta information for given client idea
|
||||
/// </summary>
|
||||
/// <param name="request">request information</param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<IClientMeta>> GetRuntimeMeta(ClientPaginationRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// retreives all the runtime of provided type
|
||||
/// </summary>
|
||||
/// <param name="request">>request information</param>
|
||||
/// <param name="metaType">type of meta to retreive</param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<T>> GetRuntimeMeta<T>(ClientPaginationRequest request, MetaType metaType) where T : IClientMeta;
|
||||
}
|
||||
}
|
@ -1,12 +1,23 @@
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace SharedLibraryCore.Localization
|
||||
{
|
||||
public class Layout
|
||||
{
|
||||
public string LocalizationName { get; set; }
|
||||
private string localizationName;
|
||||
public string LocalizationName
|
||||
{
|
||||
get => localizationName;
|
||||
set
|
||||
{
|
||||
localizationName = value;
|
||||
Culture = new CultureInfo(value);
|
||||
}
|
||||
}
|
||||
public TranslationLookup LocalizationIndex { get; set; }
|
||||
public CultureInfo Culture { get; private set; }
|
||||
|
||||
public Layout(Dictionary<string, string> set)
|
||||
{
|
||||
|
@ -618,7 +618,7 @@ namespace SharedLibraryCore.Database.Models
|
||||
if (tempbanPenalty != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their GUID is temporarily banned");
|
||||
Kick($"{loc["SERVER_TB_REMAIN"]} ({(tempbanPenalty.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient);
|
||||
Kick($"{loc["SERVER_TB_REMAIN"]} ({(tempbanPenalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
12
SharedLibraryCore/QueryHelper/ClientPaginationRequest.cs
Normal file
12
SharedLibraryCore/QueryHelper/ClientPaginationRequest.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using SharedLibraryCore.Dtos;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.QueryHelper
|
||||
{
|
||||
public class ClientPaginationRequest : PaginationRequest
|
||||
{
|
||||
public int ClientId { get; set; }
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ namespace SharedLibraryCore.Repositories
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IList<AuditInfo>> ListAuditInformation(PaginationInfo paginationInfo)
|
||||
public async Task<IList<AuditInfo>> ListAuditInformation(PaginationRequest paginationInfo)
|
||||
{
|
||||
using (var ctx = _contextFactory.CreateContext(enableTracking: false))
|
||||
{
|
||||
|
@ -1,169 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SharedLibraryCore.Database;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Services
|
||||
{
|
||||
public class MetaService
|
||||
{
|
||||
private static List<Func<int, int, int, DateTime?, Task<List<ProfileMeta>>>> _metaActions = new List<Func<int, int, int, DateTime?, Task<List<ProfileMeta>>>>();
|
||||
|
||||
/// <summary>
|
||||
/// adds or updates meta key and value to the database
|
||||
/// </summary>
|
||||
/// <param name="metaKey">key of meta data</param>
|
||||
/// <param name="metaValue">value of the meta data</param>
|
||||
/// <param name="client">client to save the meta for</param>
|
||||
/// <returns></returns>
|
||||
public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client)
|
||||
{
|
||||
// this seems to happen if the client disconnects before they've had time to authenticate and be added
|
||||
if (client.ClientId < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var ctx = new DatabaseContext())
|
||||
{
|
||||
var existingMeta = await ctx.EFMeta
|
||||
.Where(_meta => _meta.Key == metaKey)
|
||||
.Where(_meta => _meta.ClientId == client.ClientId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (existingMeta != null)
|
||||
{
|
||||
existingMeta.Value = metaValue;
|
||||
existingMeta.Updated = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ctx.EFMeta.Add(new EFMeta()
|
||||
{
|
||||
ClientId = client.ClientId,
|
||||
Created = DateTime.UtcNow,
|
||||
Key = metaKey,
|
||||
Value = metaValue
|
||||
});
|
||||
}
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Clear()
|
||||
{
|
||||
_metaActions.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieves meta data for given client and key
|
||||
/// </summary>
|
||||
/// <param name="metaKey">key to retrieve value for</param>
|
||||
/// <param name="client">client to retrieve meta for</param>
|
||||
/// <returns></returns>
|
||||
public async Task<EFMeta> GetPersistentMeta(string metaKey, EFClient client)
|
||||
{
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
return await ctx.EFMeta
|
||||
.Where(_meta => _meta.Key == metaKey)
|
||||
.Where(_meta => _meta.ClientId == client.ClientId)
|
||||
.Select(_meta => new EFMeta()
|
||||
{
|
||||
MetaId = _meta.MetaId,
|
||||
Key = _meta.Key,
|
||||
ClientId = _meta.ClientId,
|
||||
Value = _meta.Value
|
||||
})
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// aads a meta task to the runtime meta list
|
||||
/// </summary>
|
||||
/// <param name="metaAction"></param>
|
||||
public static void AddRuntimeMeta(Func<int, int, int, DateTime?, Task<List<ProfileMeta>>> metaAction)
|
||||
{
|
||||
_metaActions.Add(metaAction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieves all the runtime meta information for given client idea
|
||||
/// </summary>
|
||||
/// <param name="clientId">id of the client</param>
|
||||
/// <param name="count">number of meta items to retrieve</param>
|
||||
/// <param name="offset">offset from the first item</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<List<ProfileMeta>> GetRuntimeMeta(int clientId, int offset = 0, int count = int.MaxValue, DateTime? startAt = null)
|
||||
{
|
||||
var meta = new List<ProfileMeta>();
|
||||
|
||||
foreach (var action in _metaActions)
|
||||
{
|
||||
var metaItems = await action(clientId, offset, count, startAt);
|
||||
meta.AddRange(metaItems);
|
||||
}
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
var table = new List<List<ProfileMeta>>();
|
||||
var metaWithColumn = meta
|
||||
.Where(_meta => _meta.Column != null);
|
||||
|
||||
var columnGrouping = metaWithColumn
|
||||
.GroupBy(_meta => _meta.Column);
|
||||
|
||||
var metaToSort = meta.Except(metaWithColumn).ToList();
|
||||
|
||||
foreach (var metaItem in columnGrouping)
|
||||
{
|
||||
table.Add(new List<ProfileMeta>(metaItem));
|
||||
}
|
||||
|
||||
while (metaToSort.Count > 0)
|
||||
{
|
||||
var sortingMeta = metaToSort.First();
|
||||
|
||||
int indexOfSmallestColumn()
|
||||
{
|
||||
int index = 0;
|
||||
int smallestColumnSize = int.MaxValue;
|
||||
for (int i = 0; i < table.Count; i++)
|
||||
{
|
||||
if (table[i].Count < smallestColumnSize)
|
||||
{
|
||||
smallestColumnSize = table[i].Count;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
int columnIndex = indexOfSmallestColumn();
|
||||
|
||||
sortingMeta.Column = columnIndex;
|
||||
sortingMeta.Order = columnGrouping
|
||||
.First(_group => _group.Key == columnIndex)
|
||||
.Count();
|
||||
|
||||
table[columnIndex].Add(sortingMeta);
|
||||
|
||||
metaToSort.Remove(sortingMeta);
|
||||
}
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
return meta.OrderByDescending(_meta => _meta.When)
|
||||
.Take(count)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<PackageId>RaidMax.IW4MAdmin.SharedLibraryCore</PackageId>
|
||||
<Version>2.4.3</Version>
|
||||
<Version>2.4.6</Version>
|
||||
<Authors>RaidMax</Authors>
|
||||
<Company>Forever None</Company>
|
||||
<Configurations>Debug;Release;Prerelease</Configurations>
|
||||
@ -20,8 +20,8 @@
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<Description>Shared Library for IW4MAdmin</Description>
|
||||
<AssemblyVersion>2.4.3.0</AssemblyVersion>
|
||||
<FileVersion>2.4.3.0</FileVersion>
|
||||
<AssemblyVersion>2.4.6.0</AssemblyVersion>
|
||||
<FileVersion>2.4.6.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Prerelease|AnyCPU'">
|
||||
@ -30,30 +30,33 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="8.6.2" />
|
||||
<PackageReference Include="FluentValidation" Version="9.1.2" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.8.26" />
|
||||
<PackageReference Include="Humanizer.Core.pt" Version="2.8.26" />
|
||||
<PackageReference Include="Humanizer.Core.ru" Version="2.8.26" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Npgsql" Version="4.1.3.1" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.3" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
|
||||
<PackageReference Include="Npgsql" Version="4.1.4" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.2" />
|
||||
<PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
|
@ -1,5 +1,8 @@
|
||||
|
||||
using Humanizer;
|
||||
using Humanizer.Localisation;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Dtos.Meta;
|
||||
using SharedLibraryCore.Helpers;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
@ -381,57 +384,6 @@ namespace SharedLibraryCore
|
||||
return !ip.HasValue ? "" : new IPAddress(BitConverter.GetBytes(ip.Value)).ToString();
|
||||
}
|
||||
|
||||
public static string GetTimePassed(DateTime start)
|
||||
{
|
||||
return GetTimePassed(start, true);
|
||||
}
|
||||
|
||||
public static string GetTimePassed(DateTime start, bool includeAgo)
|
||||
{
|
||||
TimeSpan Elapsed = DateTime.UtcNow - start;
|
||||
string ago = includeAgo ? $" {CurrentLocalization.LocalizationIndex["WEBFRONT_PENALTY_TEMPLATE_AGO"]}" : "";
|
||||
|
||||
if (Elapsed.TotalSeconds < 30)
|
||||
{
|
||||
return CurrentLocalization.LocalizationIndex["GLOBAL_TIME_JUSTNOW"] + ago;
|
||||
}
|
||||
if (Elapsed.TotalMinutes < 120)
|
||||
{
|
||||
if (Elapsed.TotalMinutes < 1.5)
|
||||
{
|
||||
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_MINUTES"]}{ago}";
|
||||
}
|
||||
|
||||
return Math.Round(Elapsed.TotalMinutes, 0) + $" {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_MINUTES"]}{ago}";
|
||||
}
|
||||
if (Elapsed.TotalHours <= 24)
|
||||
{
|
||||
if (Elapsed.TotalHours < 1.5)
|
||||
{
|
||||
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]}{ago}";
|
||||
}
|
||||
|
||||
return Math.Round(Elapsed.TotalHours, 0) + $" { CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]}{ago}";
|
||||
}
|
||||
if (Elapsed.TotalDays <= 90)
|
||||
{
|
||||
if (Elapsed.TotalDays < 1.5)
|
||||
{
|
||||
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_DAYS"]}{ago}";
|
||||
}
|
||||
|
||||
return Math.Round(Elapsed.TotalDays, 0) + $" {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_DAYS"]}{ago}";
|
||||
}
|
||||
if (Elapsed.TotalDays <= 365)
|
||||
{
|
||||
return $"{Math.Round(Elapsed.TotalDays / 7)} {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_WEEKS"]}{ago}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{Math.Round(Elapsed.TotalDays / 30, 0)} {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_MONTHS"]}{ago}";
|
||||
}
|
||||
}
|
||||
|
||||
public static Game GetGame(string gameName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(gameName))
|
||||
@ -519,42 +471,6 @@ namespace SharedLibraryCore
|
||||
return new TimeSpan(1, 0, 0);
|
||||
}
|
||||
|
||||
public static string TimeSpanText(this TimeSpan span)
|
||||
{
|
||||
var loc = CurrentLocalization.LocalizationIndex;
|
||||
|
||||
if (span.TotalMinutes < 60)
|
||||
{
|
||||
return $"{span.Minutes} {loc["GLOBAL_TIME_MINUTES"]}";
|
||||
}
|
||||
else if (span.Hours >= 1 && span.TotalHours < 24)
|
||||
{
|
||||
return $"{span.Hours} {loc["GLOBAL_TIME_HOURS"]}";
|
||||
}
|
||||
else if (span.TotalDays >= 1 && span.TotalDays < 7)
|
||||
{
|
||||
return $"{span.Days} {loc["GLOBAL_TIME_DAYS"]}";
|
||||
}
|
||||
else if (span.TotalDays >= 7 && span.TotalDays < 90)
|
||||
{
|
||||
return $"{Math.Round(span.Days / 7.0, 0)} {loc["GLOBAL_TIME_WEEKS"]}";
|
||||
}
|
||||
else if (span.TotalDays >= 90 && span.TotalDays < 365)
|
||||
{
|
||||
return $"{Math.Round(span.Days / 30.0, 0)} {loc["GLOBAL_TIME_MONTHS"]}";
|
||||
}
|
||||
else if (span.TotalDays >= 365 && span.TotalDays < 36500)
|
||||
{
|
||||
return $"{Math.Round(span.Days / 365.0, 0)} {loc["GLOBAL_TIME_YEARS"]}";
|
||||
}
|
||||
else if (span.TotalDays >= 36500)
|
||||
{
|
||||
return loc["GLOBAL_TIME_FOREVER"];
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns a list of penalty types that should be shown across all profiles
|
||||
/// </summary>
|
||||
@ -932,7 +848,7 @@ namespace SharedLibraryCore
|
||||
/// <param name="penalty"></param>
|
||||
/// <param name="penaltyService"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <returns>true of the creat succeeds, false otherwise</returns>
|
||||
/// <returns>true of the create succeeds, false otherwise</returns>
|
||||
public static async Task<bool> TryCreatePenalty(this EFPenalty penalty, IEntityService<EFPenalty> penaltyService, ILogger logger)
|
||||
{
|
||||
try
|
||||
@ -969,7 +885,50 @@ namespace SharedLibraryCore
|
||||
}
|
||||
|
||||
public static bool ShouldHideLevel(this Permission perm) => perm == Permission.Flagged;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// parses translation string into tokens that are able to be formatted by the webfront
|
||||
/// </summary>
|
||||
/// <param name="translationKey">key for translation lookup</param>
|
||||
/// <returns></returns>
|
||||
public static WebfrontTranslationHelper[] SplitTranslationTokens(string translationKey)
|
||||
{
|
||||
string translationString = CurrentLocalization.LocalizationIndex[translationKey];
|
||||
var builder = new StringBuilder();
|
||||
var results = new List<WebfrontTranslationHelper>();
|
||||
|
||||
foreach (string word in translationString.Split(' '))
|
||||
{
|
||||
string finalWord = word;
|
||||
|
||||
if ((word.StartsWith("{{") && !word.EndsWith("}}")) ||
|
||||
(builder.Length > 0 && !word.EndsWith("}}")))
|
||||
{
|
||||
builder.Append($"{word} ");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
builder.Append(word);
|
||||
finalWord = builder.ToString();
|
||||
builder.Clear();
|
||||
}
|
||||
|
||||
var match = Regex.Match(finalWord, @"{{([^}|^-]+)(?:->)([^}]+)}}|{{([^}]+)}}");
|
||||
bool isInterpolation = match.Success;
|
||||
|
||||
results.Add(new WebfrontTranslationHelper
|
||||
{
|
||||
IsInterpolation = isInterpolation,
|
||||
MatchValue = isInterpolation ? match.Groups[3].Length > 0 ? match.Groups[3].ToString() : match.Groups[1].ToString() : finalWord,
|
||||
TranslationValue = isInterpolation && match.Groups[2].Length > 0 ? match.Groups[2].ToString() : ""
|
||||
});
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// indicates if running in development mode
|
||||
/// </summary>
|
||||
@ -991,5 +950,27 @@ namespace SharedLibraryCore
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// wrapper method for humanizee that uses current current culture
|
||||
/// </summary>
|
||||
public static string HumanizeForCurrentCulture(this TimeSpan timeSpan, int precision = 1, TimeUnit maxUnit = TimeUnit.Week,
|
||||
TimeUnit minUnit = TimeUnit.Millisecond, string collectionSeparator = ", ", bool toWords = false)
|
||||
{
|
||||
return timeSpan.Humanize(precision, CurrentLocalization.Culture, maxUnit, minUnit, collectionSeparator, toWords);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// wrapper method for humanizee that uses current current culture
|
||||
/// </summary>
|
||||
public static string HumanizeForCurrentCulture(this DateTime input, bool utcDate = true, DateTime? dateToCompareAgainst = null, CultureInfo culture = null)
|
||||
{
|
||||
return input.Humanize(utcDate, dateToCompareAgainst, CurrentLocalization.Culture);
|
||||
}
|
||||
|
||||
public static string ToTranslatedName(this MetaType metaType)
|
||||
{
|
||||
return CurrentLocalization.LocalizationIndex[$"META_TYPE_{metaType.ToString().ToUpper()}_NAME"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user