continue rework of profile

start moving profile info out of javascript into componentview
rework meta data to include count and offset
This commit is contained in:
RaidMax 2019-03-27 19:40:26 -05:00
parent 1e2e2218e3
commit 7b8126d57e
17 changed files with 277 additions and 250 deletions

View File

@ -388,42 +388,80 @@ namespace IW4MAdmin.Application
#endregion #endregion
#region META #region META
async Task<List<ProfileMeta>> getLastMap(int clientId) async Task<List<ProfileMeta>> getProfileMeta(int clientId, int offset, int count)
{ {
var meta = await _metaService.GetPersistentMeta("LastMapPlayed", new EFClient() { ClientId = clientId }); var metaList = new List<ProfileMeta>();
return meta == null ? new List<ProfileMeta>() : new List<ProfileMeta>() // we don't want to return anything because it means we're trying to retrieve paged meta data
if (count > 1)
{ {
new ProfileMeta() return metaList;
{ }
Id = meta.MetaId,
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_MAP"],
Value = meta.Value,
Show = true
}
}; var lastMapMeta = await _metaService.GetPersistentMeta("LastMapPlayed", new EFClient() { ClientId = clientId });
}
async Task<List<ProfileMeta>> getLastServer(int clientId) metaList.Add(new ProfileMeta()
{
var meta = await _metaService.GetPersistentMeta("LastServerPlayed", new EFClient() { ClientId = clientId });
return meta == null ? new List<ProfileMeta>() : new List<ProfileMeta>()
{ {
new ProfileMeta() Id = lastMapMeta.MetaId,
{ Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_MAP"],
Id = meta.MetaId, Value = lastMapMeta.Value,
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_SERVER"], Show = true,
Value = meta.Value, Type = ProfileMeta.MetaType.Information
Show = true });
}
}; var lastServerMeta = await _metaService.GetPersistentMeta("LastServerPlayed", new EFClient() { ClientId = clientId });
}
MetaService.AddRuntimeMeta(getLastMap); metaList.Add(new ProfileMeta()
MetaService.AddRuntimeMeta(getLastServer); {
Id = lastServerMeta.MetaId,
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_SERVER"],
Value = lastServerMeta.Value,
Show = true,
Type = ProfileMeta.MetaType.Information
});
var client = await GetClientService().Get(clientId);
metaList.Add(new ProfileMeta()
{
Id = client.ClientId,
Key = $"{Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]} {Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_PLAYER"]}",
Value = Math.Round(client.TotalConnectionTime / 3600.0, 1).ToString("#,##0"),
Show = true,
Type = ProfileMeta.MetaType.Information
});
metaList.Add(new ProfileMeta()
{
Id = client.ClientId,
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_FSEEN"],
Value = Utilities.GetTimePassed(client.FirstConnection, false),
Show = true,
Type = ProfileMeta.MetaType.Information
});
metaList.Add(new ProfileMeta()
{
Id = client.ClientId,
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_LSEEN"],
Value = Utilities.GetTimePassed(client.LastConnection, false),
Show = true,
Type = ProfileMeta.MetaType.Information
});
metaList.Add(new ProfileMeta()
{
Id = client.ClientId,
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_CONNECTIONS"],
Value = client.Connections,
Show = true,
Type = ProfileMeta.MetaType.Information
});
return metaList;
};
MetaService.AddRuntimeMeta(getProfileMeta);
#endregion #endregion
#region INIT #region INIT

View File

@ -124,8 +124,13 @@ namespace IW4MAdmin.Plugins.Stats
"/Stats/TopPlayersAsync"); "/Stats/TopPlayersAsync");
// meta data info // meta data info
async Task<List<ProfileMeta>> getStats(int clientId) async Task<List<ProfileMeta>> getStats(int clientId, int offset, int count)
{ {
if (count > 1)
{
return new List<ProfileMeta>();
}
IList<EFClientStatistics> clientStats; IList<EFClientStatistics> clientStats;
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
{ {
@ -146,38 +151,50 @@ namespace IW4MAdmin.Plugins.Stats
{ {
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_RANKING"], Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_RANKING"],
Value = "#" + await StatManager.GetClientOverallRanking(clientId), Value = "#" + await StatManager.GetClientOverallRanking(clientId),
Type = ProfileMeta.MetaType.Information
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"], Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"],
Value = kills Value = kills,
Type = ProfileMeta.MetaType.Information
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"], Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"],
Value = deaths Value = deaths,
Type = ProfileMeta.MetaType.Information
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"], Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"],
Value = kdr Value = kdr,
Type = ProfileMeta.MetaType.Information
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_PERFORMANCE"], Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_PERFORMANCE"],
Value = performance Value = performance,
Type = ProfileMeta.MetaType.Information
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"], Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"],
Value = spm Value = spm,
Type = ProfileMeta.MetaType.Information
} }
}; };
} }
async Task<List<ProfileMeta>> getAnticheatInfo(int clientId) async Task<List<ProfileMeta>> getAnticheatInfo(int clientId, int offset, int count)
{ {
if (count > 1)
{
return new List<ProfileMeta>();
}
IList<EFClientStatistics> clientStats; IList<EFClientStatistics> clientStats;
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
{ {
clientStats = await ctx.Set<EFClientStatistics>() clientStats = await ctx.Set<EFClientStatistics>()
@ -221,24 +238,28 @@ namespace IW4MAdmin.Plugins.Stats
{ {
Key = "Chest Ratio", Key = "Chest Ratio",
Value = chestRatio, Value = chestRatio,
Type = ProfileMeta.MetaType.Information,
Sensitive = true Sensitive = true
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = "Abdomen Ratio", Key = "Abdomen Ratio",
Value = abdomenRatio, Value = abdomenRatio,
Type = ProfileMeta.MetaType.Information,
Sensitive = true Sensitive = true
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = "Chest To Abdomen Ratio", Key = "Chest To Abdomen Ratio",
Value = chestAbdomenRatio, Value = chestAbdomenRatio,
Type = ProfileMeta.MetaType.Information,
Sensitive = true Sensitive = true
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = "Headshot Ratio", Key = "Headshot Ratio",
Value = headRatio, Value = headRatio,
Type = ProfileMeta.MetaType.Information,
Sensitive = true Sensitive = true
}, },
new ProfileMeta() new ProfileMeta()
@ -246,49 +267,64 @@ namespace IW4MAdmin.Plugins.Stats
Key = "Hit Offset Average", Key = "Hit Offset Average",
// todo: make sure this is wrapped somewhere else // todo: make sure this is wrapped somewhere else
Value = $"{Math.Round(((float)hitOffsetAverage), 4).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))}°", Value = $"{Math.Round(((float)hitOffsetAverage), 4).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))}°",
Type = ProfileMeta.MetaType.Information,
Sensitive = true Sensitive = true
}, },
new ProfileMeta() new ProfileMeta()
{ {
Key = "Max Strain", Key = "Max Strain",
Value = Math.Round(maxStrain, 3), Value = Math.Round(maxStrain, 3),
Type = ProfileMeta.MetaType.Information,
Sensitive = true Sensitive = true
}, },
}; };
} }
async Task<List<ProfileMeta>> getMessages(int clientId) async Task<List<ProfileMeta>> getMessages(int clientId, int offset, int count)
{ {
if (count <= 1)
{
using (var ctx = new DatabaseContext(true))
{
return new List<ProfileMeta>
{
new ProfileMeta()
{
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGES"],
Value = await ctx.Set<EFClientMessage>().CountAsync(),
Type = ProfileMeta.MetaType.Information
}
};
}
}
List<ProfileMeta> messageMeta; List<ProfileMeta> messageMeta;
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
{ {
var messages = ctx.Set<EFClientMessage>().Where(m => m.ClientId == clientId); var messages = ctx.Set<EFClientMessage>().Where(m => m.ClientId == clientId)
.OrderByDescending(_message => _message.TimeSent)
.Skip(offset)
.Take(count);
messageMeta = await messages.Select(m => new ProfileMeta() messageMeta = await messages.Select(m => new ProfileMeta()
{ {
Key = "EventMessage", Key = null,
Value = m.Message, Value = m.Message,
When = m.TimeSent, When = m.TimeSent,
Extra = m.ServerId.ToString() Extra = m.ServerId.ToString(),
Type = ProfileMeta.MetaType.ChatMessage
}).ToListAsync(); }).ToListAsync();
} }
messageMeta.Add(new ProfileMeta()
{
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGES"],
Value = messageMeta.Count
});
return messageMeta; return messageMeta;
} }
MetaService.AddRuntimeMeta(getStats);
if (Config.Configuration().EnableAntiCheat) if (Config.Configuration().EnableAntiCheat)
{ {
MetaService.AddRuntimeMeta(getAnticheatInfo); MetaService.AddRuntimeMeta(getAnticheatInfo);
} }
MetaService.AddRuntimeMeta(getStats);
MetaService.AddRuntimeMeta(getMessages); MetaService.AddRuntimeMeta(getMessages);
async Task<string> totalKills(Server server) async Task<string> totalKills(Server server)

View File

@ -10,17 +10,19 @@ namespace SharedLibraryCore.Dtos
{ {
public string OffenderName { get; set; } public string OffenderName { get; set; }
public int OffenderId { get; set; } public int OffenderId { get; set; }
public ulong OffenderNetworkId { get; set; }
public string OffenderIPAddress { get; set; }
public string PunisherName { get; set; } public string PunisherName { get; set; }
public int PunisherId { get; set; } public int PunisherId { get; set; }
public ulong PunisherNetworkId { get; set; }
public string PunisherIPAddress { get; set; }
public string PunisherLevel { get; set; } public string PunisherLevel { get; set; }
public int PunisherLevelId { 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 PenaltyType { get; set; }
public string TimePunished { get; set; } public string TimePunished { get; set; }
public string TimeRemaining { get; set; } public string TimeRemaining { get; set; }
public bool Expired { get; set; } public bool Expired { get; set; }
public string IPAddress { get; set; }
public ulong NetworkId { get; set; }
} }
} }

View File

@ -18,10 +18,10 @@ namespace SharedLibraryCore.Dtos
public List<string> IPs { get; set; } public List<string> IPs { get; set; }
public bool HasActivePenalty { get; set; } public bool HasActivePenalty { get; set; }
public string ActivePenaltyType { get; set; } public string ActivePenaltyType { get; set; }
public int ConnectionCount { get; set; } //public int ConnectionCount { get; set; }
public string LastSeen { get; set; } //public string LastSeen { get; set; }
public string FirstSeen { get; set; } //public string FirstSeen { get; set; }
public string TimePlayed { get; set; } //public string TimePlayed { get; set; }
public bool Authenticated { get; set; } public bool Authenticated { get; set; }
public List<ProfileMeta> Meta { get; set; } public List<ProfileMeta> Meta { get; set; }
public bool Online { get; set; } public bool Online { get; set; }

View File

@ -8,11 +8,22 @@ namespace SharedLibraryCore.Dtos
{ {
public class ProfileMeta : SharedInfo public class ProfileMeta : SharedInfo
{ {
public enum MetaType
{
Other,
Information,
AliasUpdate,
ChatMessage
}
public DateTime When { get; set; } public DateTime When { get; set; }
public string WhenString => Utilities.GetTimePassed(When, false); public string WhenString => Utilities.GetTimePassed(When, false);
public string Key { get; set; } public string Key { get; set; }
public dynamic Value { get; set; } public dynamic Value { get; set; }
public string Extra { get; set; } public string Extra { get; set; }
public virtual string Class => Value.GetType().ToString(); public virtual string Class => Value.GetType().ToString();
public MetaType Type { get; set; }
public int? Column { get; set; }
public int? Order { get; set; }
} }
} }

View File

@ -11,7 +11,7 @@ namespace SharedLibraryCore.Services
{ {
public class MetaService public class MetaService
{ {
private static List<Func<int, Task<List<ProfileMeta>>>> _metaActions = new List<Func<int, Task<List<ProfileMeta>>>>(); private static List<Func<int, int, int, Task<List<ProfileMeta>>>> _metaActions = new List<Func<int, int, int, Task<List<ProfileMeta>>>>();
/// <summary> /// <summary>
/// adds or updates meta key and value to the database /// adds or updates meta key and value to the database
@ -71,7 +71,7 @@ namespace SharedLibraryCore.Services
/// aads a meta task to the runtime meta list /// aads a meta task to the runtime meta list
/// </summary> /// </summary>
/// <param name="metaAction"></param> /// <param name="metaAction"></param>
public static void AddRuntimeMeta(Func<int, Task<List<ProfileMeta>>> metaAction) public static void AddRuntimeMeta(Func<int, int, int, Task<List<ProfileMeta>>> metaAction)
{ {
_metaActions.Add(metaAction); _metaActions.Add(metaAction);
} }
@ -80,14 +80,16 @@ namespace SharedLibraryCore.Services
/// retrieves all the runtime meta information for given client idea /// retrieves all the runtime meta information for given client idea
/// </summary> /// </summary>
/// <param name="clientId">id of the client</param> /// <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> /// <returns></returns>
public static async Task<List<ProfileMeta>> GetRuntimeMeta(int clientId) public static async Task<List<ProfileMeta>> GetRuntimeMeta(int clientId, int offset = 0, int count = int.MaxValue)
{ {
var meta = new List<ProfileMeta>(); var meta = new List<ProfileMeta>();
foreach (var action in _metaActions) foreach (var action in _metaActions)
{ {
meta.AddRange(await action(clientId)); meta.AddRange(await action(clientId, offset, count));
} }
return meta; return meta;

View File

@ -195,7 +195,7 @@ namespace SharedLibraryCore.Services
PunisherName = punisherAlias.Name, PunisherName = punisherAlias.Name,
PunisherId = penalty.PunisherId, PunisherId = penalty.PunisherId,
Offense = penalty.Offense, Offense = penalty.Offense,
Type = penalty.Type.ToString(), PenaltyType = penalty.Type.ToString(),
TimeRemaining = penalty.Expires.HasValue ? (now > penalty.Expires ? "" : penalty.Expires.ToString()) : DateTime.MaxValue.ToString(), TimeRemaining = penalty.Expires.HasValue ? (now > penalty.Expires ? "" : penalty.Expires.ToString()) : DateTime.MaxValue.ToString(),
AutomatedOffense = penalty.AutomatedOffense, AutomatedOffense = penalty.AutomatedOffense,
Expired = penalty.Expires.HasValue && penalty.Expires <= DateTime.UtcNow Expired = penalty.Expires.HasValue && penalty.Expires <= DateTime.UtcNow
@ -208,9 +208,9 @@ namespace SharedLibraryCore.Services
list.ForEach(p => list.ForEach(p =>
{ {
// todo: why does this have to be done? // todo: why does this have to be done?
if (((PenaltyInfo)p.Value).Type.Length < 2) if (((PenaltyInfo)p.Value).PenaltyType.Length < 2)
{ {
((PenaltyInfo)p.Value).Type = ((Penalty.PenaltyType)Convert.ToInt32(((PenaltyInfo)p.Value).Type)).ToString(); ((PenaltyInfo)p.Value).PenaltyType = ((Penalty.PenaltyType)Convert.ToInt32(((PenaltyInfo)p.Value).PenaltyType)).ToString();
} }
var pi = ((PenaltyInfo)p.Value); var pi = ((PenaltyInfo)p.Value);
@ -251,7 +251,7 @@ namespace SharedLibraryCore.Services
PunisherName = punisherAlias.Name, PunisherName = punisherAlias.Name,
PunisherId = penalty.PunisherId, PunisherId = penalty.PunisherId,
Offense = penalty.Offense, Offense = penalty.Offense,
Type = penalty.Type.ToString(), PenaltyType = penalty.Type.ToString(),
AutomatedOffense = penalty.AutomatedOffense AutomatedOffense = penalty.AutomatedOffense
}, },
When = penalty.When, When = penalty.When,
@ -263,9 +263,9 @@ namespace SharedLibraryCore.Services
list.ForEach(p => list.ForEach(p =>
{ {
// todo: why does this have to be done? // todo: why does this have to be done?
if (((PenaltyInfo)p.Value).Type.Length < 2) if (((PenaltyInfo)p.Value).PenaltyType.Length < 2)
{ {
((PenaltyInfo)p.Value).Type = ((Penalty.PenaltyType)Convert.ToInt32(((PenaltyInfo)p.Value).Type)).ToString(); ((PenaltyInfo)p.Value).PenaltyType = ((Penalty.PenaltyType)Convert.ToInt32(((PenaltyInfo)p.Value).PenaltyType)).ToString();
} }
}); });

View File

@ -34,10 +34,6 @@ namespace WebfrontCore.Controllers
ClientId = client.ClientId, ClientId = client.ClientId,
IPAddress = client.IPAddressString, IPAddress = client.IPAddressString,
NetworkId = client.NetworkId, NetworkId = client.NetworkId,
ConnectionCount = client.Connections,
FirstSeen = Utilities.GetTimePassed(client.FirstConnection, false),
LastSeen = Utilities.GetTimePassed(client.LastConnection, false),
TimePlayed = Math.Round(client.TotalConnectionTime / 3600.0, 1).ToString("#,##0"),
Meta = new List<ProfileMeta>(), Meta = new List<ProfileMeta>(),
Aliases = client.AliasLink.Children Aliases = client.AliasLink.Children
.Where(a => a.Name != client.Name) .Where(a => a.Name != client.Name)
@ -59,7 +55,7 @@ namespace WebfrontCore.Controllers
LinkedAccounts = client.LinkedAccounts LinkedAccounts = client.LinkedAccounts
}; };
var meta = await MetaService.GetRuntimeMeta(client.ClientId); var meta = await MetaService.GetRuntimeMeta(client.ClientId, 0, 1);
var penaltyMeta = await Manager.GetPenaltyService() var penaltyMeta = await Manager.GetPenaltyService()
.ReadGetClientPenaltiesAsync(client.ClientId); .ReadGetClientPenaltiesAsync(client.ClientId);
var administeredPenaltiesMeta = await Manager.GetPenaltyService() var administeredPenaltiesMeta = await Manager.GetPenaltyService()
@ -76,19 +72,19 @@ namespace WebfrontCore.Controllers
}); });
} }
if (Authorized) //if (Authorized)
{ //{
clientDto.Meta.AddRange(client.AliasLink.Children // clientDto.Meta.AddRange(client.AliasLink.Children
.GroupBy(a => a.Name) // .GroupBy(a => a.Name)
.Select(a => a.First()) // .Select(a => a.First())
.Select(a => new ProfileMeta() // .Select(a => new ProfileMeta()
{ // {
Key = "AliasEvent", // Value = $"{Localization["WEBFRONT_CLIENT_META_JOINED"]} {a.Name}",
Value = $"{Localization["WEBFRONT_CLIENT_META_JOINED"]} {a.Name}", // Sensitive = true,
Sensitive = true, // When = a.DateAdded,
When = a.DateAdded // Type = ProfileMeta.MetaType.AliasUpdate
})); // }));
} //}
if (Authorized) if (Authorized)
{ {
@ -118,6 +114,7 @@ namespace WebfrontCore.Controllers
Value = m.Value, Value = m.Value,
Show = false, Show = false,
})); }));
clientDto.Meta = clientDto.Meta clientDto.Meta = clientDto.Meta
.OrderByDescending(m => m.When) .OrderByDescending(m => m.When)
.ToList(); .ToList();
@ -173,13 +170,25 @@ namespace WebfrontCore.Controllers
Name = c.Name, Name = c.Name,
Level = c.Level.ToLocalizedLevelName(), Level = c.Level.ToLocalizedLevelName(),
LevelInt = (int)c.Level, LevelInt = (int)c.Level,
ClientId = c.ClientId, // todo: add back last seen for search
LastSeen = Utilities.GetTimePassed(c.LastConnection, false) ClientId = c.ClientId
}) })
.ToList(); .ToList();
ViewBag.Title = $"{clientsDto.Count} {Localization["WEBFRONT_CLIENT_SEARCH_MATCHING"]} \"{clientName}\""; ViewBag.Title = $"{clientsDto.Count} {Localization["WEBFRONT_CLIENT_SEARCH_MATCHING"]} \"{clientName}\"";
return View("Find/Index", clientsDto); return View("Find/Index", clientsDto);
} }
public async Task<IActionResult> Meta(int id, int count, int offset)
{
var meta = await MetaService.GetRuntimeMeta(id, offset, count);
if (meta.Count == 0)
{
return Ok();
}
return View("Components/ProfileMetaList/_List", meta);
}
} }
} }

View File

@ -46,20 +46,25 @@ namespace WebfrontCore.Controllers
{ {
// todo: this seems like it's pulling unnecessary info from LINQ to entities. // todo: this seems like it's pulling unnecessary info from LINQ to entities.
var iqPenalties = ctx.Penalties var iqPenalties = ctx.Penalties
.AsNoTracking()
.Where(p => p.Type == SharedLibraryCore.Objects.Penalty.PenaltyType.Ban && p.Active) .Where(p => p.Type == SharedLibraryCore.Objects.Penalty.PenaltyType.Ban && p.Active)
.OrderByDescending(_penalty => _penalty.When) .OrderByDescending(_penalty => _penalty.When)
.Select(p => new PenaltyInfo() .Select(p => new PenaltyInfo()
{ {
Id = p.PenaltyId, Id = p.PenaltyId,
OffenderId = p.OffenderId, OffenderId = p.OffenderId,
OffenderName = p.Offender.CurrentAlias.Name,
OffenderNetworkId = (ulong)p.Offender.NetworkId,
OffenderIPAddress = Authorized ? p.Offender.CurrentAlias.IPAddress.ConvertIPtoString() : null,
Offense = p.Offense, Offense = p.Offense,
PunisherId = p.PunisherId, PunisherId = p.PunisherId,
Type = p.Type.ToString(), PunisherNetworkId = (ulong)p.Punisher.NetworkId,
PunisherName = p.Punisher.CurrentAlias.Name,
PunisherIPAddress = Authorized ? p.Punisher.CurrentAlias.IPAddress.ConvertIPtoString() : null,
PenaltyType = p.Type.ToString(),
TimePunished = p.When.ToString(), TimePunished = p.When.ToString(),
TimeRemaining = "", TimeRemaining = null,
AutomatedOffense = Authorized ? p.AutomatedOffense : "", AutomatedOffense = Authorized ? p.AutomatedOffense : null,
NetworkId = (ulong)p.Offender.NetworkId,
IPAddress = Authorized ? p.Offender.IPAddressString : ""
}); });
#if DEBUG == true #if DEBUG == true
var querySql = iqPenalties.ToSql(); var querySql = iqPenalties.ToSql();

View File

@ -29,6 +29,19 @@ namespace WebfrontCore
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
// allow CORS
services.AddCors(_options =>
{
_options.AddPolicy("AllowAll",
_builder =>
{
_builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
// Add framework services. // Add framework services.
var mvcBuilder = services.AddMvc() var mvcBuilder = services.AddMvc()
.ConfigureApplicationPartManager(_ => .ConfigureApplicationPartManager(_ =>
@ -98,6 +111,7 @@ namespace WebfrontCore
app.UseStaticFiles(); app.UseStaticFiles();
app.UseAuthentication(); app.UseAuthentication();
app.UseCors("AllowAll");
app.UseMvc(routes => app.UseMvc(routes =>
{ {

View File

@ -33,7 +33,7 @@ namespace WebfrontCore.ViewComponents
$"{showEvadeString(p)}{p.AutomatedOffense}" : $"{showEvadeString(p)}{p.AutomatedOffense}" :
$"{showEvadeString(p)}{p.Offense}", $"{showEvadeString(p)}{p.Offense}",
#endif #endif
Type = p.Type.ToString(), PenaltyType = p.Type.ToString(),
TimePunished = Utilities.GetTimePassed(p.When, false), TimePunished = Utilities.GetTimePassed(p.When, false),
// show time passed if ban // show time passed if ban
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : $"{((p.Expires ?? DateTime.MaxValue).Year == DateTime.MaxValue.Year ? Utilities.GetTimePassed(p.When, true) : Utilities.TimeSpanText((p.Expires ?? DateTime.MaxValue) - DateTime.UtcNow))}", TimeRemaining = DateTime.UtcNow > p.Expires ? "" : $"{((p.Expires ?? DateTime.MaxValue).Year == DateTime.MaxValue.Year ? Utilities.GetTimePassed(p.When, true) : Utilities.TimeSpanText((p.Expires ?? DateTime.MaxValue) - DateTime.UtcNow))}",

View File

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore.Services;
using System.Threading.Tasks;
namespace WebfrontCore.ViewComponents
{
public class ProfileMetaListViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(int clientId, int count, int offset)
{
var meta = await MetaService.GetRuntimeMeta(clientId, offset, count);
return View("_List", meta);
}
}
}

View File

@ -17,7 +17,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.LevelInt">@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>
} }
} }

View File

@ -5,6 +5,9 @@
var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex; var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex;
string gravatarUrl = Model.Meta.FirstOrDefault(m => m.Key == "GravatarEmail")?.Value; string gravatarUrl = Model.Meta.FirstOrDefault(m => m.Key == "GravatarEmail")?.Value;
bool isTempBanned = Model.ActivePenaltyType == "TempBan"; bool isTempBanned = Model.ActivePenaltyType == "TempBan";
var informationMeta = Model.Meta
.Where(_meta => _meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.Information)
.ToList();
} }
<div id="profile_wrapper" class="pb-3 row d-flex flex-column flex-lg-row"> <div id="profile_wrapper" class="pb-3 row d-flex flex-column flex-lg-row">
@ -76,27 +79,41 @@
</div> </div>
<div id="profile_info" class="row d-block d-lg-flex flex-row border-bottom border-top pt-2 pb-2"> <div id="profile_info" class="row d-block d-lg-flex flex-row border-bottom border-top pt-2 pb-2">
<div id="profile_meta_0" class="text-center text-lg-left mr-0 mr-lg-4"> <div id="profile_meta_0" class="text-center text-lg-left mr-0 mr-lg-4">
<div id="profile_time_played" class="text-muted"> @for (int i = 0; i < informationMeta.Count; i += 3)
@loc["WEBFRONT_PROFILE_PLAYER"] <span class="text-primary">@Model.TimePlayed</span> @loc["GLOBAL_TIME_HOURS"] {
</div> <div class="profile-meta-entry">
<div id="profile_first_seen" class="text-muted"> <span class="profile-meta-value text-primary">@informationMeta[i].Value</span>
@loc["WEBFRONT_PROFILE_FSEEN"] <span class="text-primary">@Model.FirstSeen</span> @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"] <span class="profile-meta-title text-muted"> @informationMeta[i].Key</span>
</div> </div>
<div id="profile_last_seen" class="text-muted"> }
@loc["WEBFRONT_PROFILE_LSEEN"] <span class="text-primary">@Model.LastSeen</span> @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"]
</div>
</div> </div>
<div class="text-center text-lg-left mr-0 mr-lg-4" id="profile_meta_1"> <div class="text-center text-lg-left mr-0 mr-lg-4" id="profile_meta_1">
@for (int i = 1; i < informationMeta.Count; i += 3)
{
<div class="profile-meta-entry">
<span class="profile-meta-value text-primary">@informationMeta[i].Value</span>
<span class="profile-meta-title text-muted"> @informationMeta[i].Key</span>
</div>
}
</div> </div>
<div class="text-center text-lg-left" id="profile_meta_2"> <div class="text-center text-lg-left" id="profile_meta_2">
@for (int i = 2; i < informationMeta.Count; i += 3)
{
<div class="profile-meta-entry">
<span class="profile-meta-value text-primary">@informationMeta[i].Value</span>
<span class="profile-meta-title text-muted"> @informationMeta[i].Key</span>
</div>
}
</div> </div>
</div> </div>
<div class="row d-md-flex pt-2"> <div class="row d-md-flex pt-2">
<div id="profile_events" class="text-muted text-left ml-sm-0"> <div id="profile_events" class="text-muted text-left ml-sm-0">
@await Component.InvokeAsync("ProfileMetaList", new { clientId = Model.ClientId, count = 30, offset = 0 })
</div> </div>
</div> </div>
@ -105,12 +122,9 @@
} }
@section scripts { @section scripts {
<script>
const clientInfo = {};
clientInfo.clientId = @Model.ClientId;
clientInfo.Meta = @Html.Raw(Json.Serialize(@Model.Meta.Where(m => m.Show)));
</script>
<environment include="Development"> <environment include="Development">
<script type="text/javascript" src="~/js/loader.js"></script>
<script type="text/javascript" src="~/js/profile.js"></script> <script type="text/javascript" src="~/js/profile.js"></script>
</environment> </environment>
<script>initLoader('/Client/Meta/@Model.ClientId', '#profile_events', 30);</script>
} }

View File

@ -13,9 +13,9 @@
</tr> </tr>
<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_TYPE"]</th> <th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_PenaltyType"]</th>
<td class="penalties-color-@Model.Type.ToLower()"> <td class="penalties-color-@Model.PenaltyType.ToLower()">
@Model.Type @Model.PenaltyType
</td> </td>
</tr> </tr>
@ -53,8 +53,8 @@
<td> <td>
@Html.ActionLink(Model.OffenderName, "ProfileAsync", "Client", new { id = Model.OffenderId }, new { @class = "link-inverse" }) @Html.ActionLink(Model.OffenderName, "ProfileAsync", "Client", new { id = Model.OffenderId }, new { @class = "link-inverse" })
</td> </td>
<td class="penalties-color-@Model.Type.ToLower()"> <td class="penalties-color-@Model.PenaltyType.ToLower()">
@Model.Type @Model.PenaltyType
</td> </td>
<td class="text-light w-50"> <td class="text-light w-50">
@Model.Offense @Model.Offense

View File

@ -0,0 +1,20 @@
@model List<SharedLibraryCore.Dtos.ProfileMeta>
@{Layout = null;}
<div class="p2 text-white profile-event-timestep">
<span class="text-primary">&mdash;</span>
<span>@SharedLibraryCore.Utilities.GetTimePassed(Model.FirstOrDefault()?.When ?? DateTime.Now, true)</span>
</div>
@foreach (var meta in Model)
{
@switch (meta.Type)
{
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.ChatMessage:
<div>
<span style="color:white;">></span>
<span class="client-message text-muted" data-serverid="@meta.Extra" data-when="@meta.When"> @meta.Value</span>
</div>
break;
}
}

View File

@ -1,13 +1,4 @@
// keeps track of how many events have been displayed $(document).ready(function () {
let count = 1;
let metaIndex = 0;
$(document).ready(function () {
if (typeof clientInfo === 'undefined') {
return false;
}
/* /*
Expand alias tab if they have any Expand alias tab if they have any
*/ */
@ -19,51 +10,6 @@ $(document).ready(function () {
} }
}); });
/*
load the initial 40 events
*/
$.each(clientInfo.Meta, function (index, meta) {
if (meta.key.includes("Event")) {
loadMeta(meta);
if (count % 40 === 0) {
count++;
return false;
}
count++;
}
});
/*
load additional events on scroll
*/
$(window).scroll(function () {
if ($(window).scrollTop() === $(document).height() - $(window).height() || $(document).height() === $(window).height()) {
while (count % 40 !== 0 && count < clientInfo.Meta.length) {
loadMeta(clientInfo.Meta[count - 1]);
count++;
}
count++;
}
});
/*
load meta thats not an event
*/
$.each(clientInfo.Meta, function (index, meta) {
if (!meta.key.includes("Event")) {
let metaString = `<div class="profile-meta-entry"><span class="profile-meta-value text-primary">${meta.value}</span><span class="profile-meta-title text-muted"> ${meta.key}</span></div>`;
// todo: fix the view so we don't have the 3 hardcoded meta
if (metaIndex % 3 == 0 && metaIndex < 7) {
metaIndex++;
}
let selector = '#profile_meta_' + (metaIndex % 3);
$(selector).append(metaString);
metaIndex++;
}
});
/* /*
* load context of chat * load context of chat
*/ */
@ -150,88 +96,3 @@ $(document).ready(function () {
}); });
}); });
}); });
function penaltyToName(penaltyName) {
switch (penaltyName) {
case "Flag":
return "Flagged";
case "Warning":
return "Warned";
case "Report":
return "Reported";
case "Ban":
return "Banned";
case "Kick":
return "Kicked";
case "TempBan":
return "Temp Banned";
case "Unban":
return "Unbanned";
}
}
function shouldIncludePlural(num) {
return num > 1 ? 's' : '';
}
let mostRecentDate = 0;
let currentStepAmount = 0;
let lastStep = '';
// todo: fix
function timeStep(stepDifference) {
let hours = stepDifference / (1000 * 60 * 60);
let days = stepDifference / (1000 * 60 * 60 * 24);
let weeks = stepDifference / (1000 * 60 * 60 * 24 * 7);
if (Math.round(weeks) > Math.round(currentStepAmount / 24 * 7)) {
currentStepAmount = Math.round(weeks);
return `${currentStepAmount} week${shouldIncludePlural(currentStepAmount)} ago`;
}
if (Math.round(days) > Math.round(currentStepAmount / 24)) {
currentStepAmount = Math.round(days);
return `${currentStepAmount} day${shouldIncludePlural(currentStepAmount)} ago`;
}
if (Math.round(hours) > currentStepAmount) {
currentStepAmount = Math.round(hours);
return `${currentStepAmount} hour${shouldIncludePlural(currentStepAmount)} ago`;
}
}
function loadMeta(meta) {
let eventString = '';
const metaDate = moment.utc(meta.when).valueOf();
if (mostRecentDate === 0) {
mostRecentDate = metaDate;
}
const step = timeStep(moment.utc().valueOf() - metaDate);
if (step !== lastStep && step !== undefined && metaDate > 0) {
$('#profile_events').append('<span class="p2 text-white profile-event-timestep"><span class="text-primary">&mdash;</span> ' + step + '</span>');
lastStep = step;
}
// it's a penalty
if (meta.class.includes("Penalty")) {
if (meta.value.punisherId !== clientInfo.clientId) {
const timeRemaining = meta.value.type === 'TempBan' && meta.value.timeRemaining.length > 0 ?
`(${meta.value.timeRemaining})` :
'';
eventString = `<div><span class="penalties-color-${meta.value.type.toLowerCase()}">${penaltyToName(meta.value.type)}</span> by <span class="text-highlight"> <a class="link-inverse" href="${meta.value.punisherId}">${meta.value.punisherName}</a></span > for <span style="color: white; " class="automated-penalty-info-detailed" data-clientid="${meta.value.offenderId}">${meta.value.offense}</span><span class="text-muted"> ${timeRemaining}</span></div>`;
}
else {
eventString = `<div><span class="penalties-color-${meta.value.type.toLowerCase()}">${penaltyToName(meta.value.type)} </span> <span class="text-highlight"><a class="link-inverse" href="${meta.value.offenderId}"> ${meta.value.offenderName}</a></span > for <span style="color: white;" class="automated-penalty-info-detailed" data-clientid="${meta.value.offenderId}">${meta.value.offense}</span></div>`;
}
}
else if (meta.key.includes("Alias")) {
eventString = `<div><span class="text-success">${meta.value}</span></div>`;
}
// it's a message
else if (meta.key.includes("Event")) {
eventString = `<div><span style="color:white;">></span><span class="client-message text-muted" data-serverid="${meta.extra}" data-when="${meta.when}"> ${meta.value}</span></div>`;
}
$('#profile_events').append(eventString);
}