Show time passed since ban instead of "forever"
reworked event api to include all events (sans unknown)
This commit is contained in:
parent
5be6b75ccf
commit
e7c7145da1
@ -10,66 +10,69 @@ namespace IW4MAdmin.Application.API
|
||||
{
|
||||
class EventApi : IEventApi
|
||||
{
|
||||
Queue<EventInfo> Events = new Queue<EventInfo>();
|
||||
DateTime LastFlagEvent;
|
||||
static string[] FlaggedMessageContains =
|
||||
{
|
||||
" wh ",
|
||||
"hax",
|
||||
"cheat",
|
||||
" hack ",
|
||||
"aim",
|
||||
"wall",
|
||||
"cheto",
|
||||
"hak",
|
||||
"bot"
|
||||
};
|
||||
int FlaggedMessageCount;
|
||||
private const int MaxEvents = 32;
|
||||
private Queue<EventInfo> RecentEvents = new Queue<EventInfo>();
|
||||
|
||||
public Queue<EventInfo> GetEvents() => Events;
|
||||
public IEnumerable<EventInfo> GetEvents(bool shouldConsume)
|
||||
{
|
||||
var eventList = RecentEvents.ToArray();
|
||||
|
||||
// clear queue if events should be consumed
|
||||
if (shouldConsume)
|
||||
{
|
||||
RecentEvents.Clear();
|
||||
}
|
||||
|
||||
return eventList;
|
||||
}
|
||||
|
||||
public void OnServerEvent(object sender, GameEvent E)
|
||||
{
|
||||
if (E.Type == GameEvent.EventType.Say && E.Origin.Level < Player.Permission.Trusted)
|
||||
// don't want to clog up the api with unknown events
|
||||
if (E.Type == GameEvent.EventType.Unknown)
|
||||
return;
|
||||
|
||||
var apiEvent = new EventInfo()
|
||||
{
|
||||
bool flaggedMessage = false;
|
||||
foreach (string msg in FlaggedMessageContains)
|
||||
flaggedMessage = flaggedMessage ? flaggedMessage : E.Data.ToLower().Contains(msg);
|
||||
|
||||
if (flaggedMessage)
|
||||
FlaggedMessageCount++;
|
||||
|
||||
if (FlaggedMessageCount > 3)
|
||||
ExtraInfo = E.Extra?.ToString() ?? E.Data,
|
||||
OwnerEntity = new EntityInfo()
|
||||
{
|
||||
if (Events.Count > 20)
|
||||
Events.Dequeue();
|
||||
Name = E.Owner.Hostname,
|
||||
Id = E.Owner.GetHashCode()
|
||||
},
|
||||
OriginEntity = E.Origin == null ? null : new EntityInfo()
|
||||
{
|
||||
Id = E.Origin.ClientId,
|
||||
Name = E.Origin.Name
|
||||
},
|
||||
TargetEntity = E.Target == null ? null : new EntityInfo()
|
||||
{
|
||||
Id = E.Target.ClientId,
|
||||
Name = E.Target.Name
|
||||
},
|
||||
EventType = new EntityInfo()
|
||||
{
|
||||
Id = (int)E.Type,
|
||||
Name = E.Type.ToString()
|
||||
},
|
||||
EventTime = E.Time
|
||||
};
|
||||
|
||||
FlaggedMessageCount = 0;
|
||||
|
||||
E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_REPORT"]).Wait(5000);
|
||||
Events.Enqueue(new EventInfo(
|
||||
EventInfo.EventType.ALERT,
|
||||
EventInfo.EventVersion.IW4MAdmin,
|
||||
"Chat indicates there may be a cheater",
|
||||
"Alert",
|
||||
E.Owner.Hostname, ""));
|
||||
// add the new event to the list
|
||||
AddNewEvent(apiEvent);
|
||||
}
|
||||
|
||||
if ((DateTime.UtcNow - LastFlagEvent).Minutes >= 3)
|
||||
/// <summary>
|
||||
/// Adds event to the list and removes first added if reached max capacity
|
||||
/// </summary>
|
||||
/// <param name="info">EventInfo to add</param>
|
||||
private void AddNewEvent(EventInfo info)
|
||||
{
|
||||
FlaggedMessageCount = 0;
|
||||
LastFlagEvent = DateTime.Now;
|
||||
}
|
||||
}
|
||||
// remove the first added event
|
||||
if (RecentEvents.Count >= MaxEvents)
|
||||
RecentEvents.Dequeue();
|
||||
|
||||
if (E.Type == GameEvent.EventType.Report)
|
||||
{
|
||||
Events.Enqueue(new EventInfo(
|
||||
EventInfo.EventType.ALERT,
|
||||
EventInfo.EventVersion.IW4MAdmin,
|
||||
$"**{E.Origin.Name}** has reported **{E.Target.Name}** for: {E.Data.Trim()}",
|
||||
E.Target.Name, E.Origin.Name, ""));
|
||||
}
|
||||
RecentEvents.Enqueue(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
Type = GameEvent.EventType.JoinTeam,
|
||||
Data = cleanedEventLine,
|
||||
//Origin = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong()),
|
||||
Origin = server.GetPlayersAsList().FirstOrDefault(c => c.NetworkId == lineSplit[1].ConvertLong()),
|
||||
Owner = server
|
||||
};
|
||||
}
|
||||
|
@ -34,13 +34,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
Manager = mgr;
|
||||
}
|
||||
|
||||
~StatManager()
|
||||
{
|
||||
Servers.Clear();
|
||||
Log = null;
|
||||
Servers = null;
|
||||
}
|
||||
|
||||
public EFClientStatistics GetClientStats(int clientId, int serverId) => Servers[serverId].PlayerStats[clientId];
|
||||
|
||||
public async Task<List<TopStatsInfo>> GetTopStats(int start, int count)
|
||||
@ -445,6 +438,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
switch (penalty.ClientPenalty)
|
||||
{
|
||||
case Penalty.PenaltyType.Ban:
|
||||
if (attacker.Level == Player.Permission.Banned)
|
||||
break;
|
||||
await saveLog();
|
||||
await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new Player()
|
||||
{
|
||||
@ -461,7 +456,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
});
|
||||
break;
|
||||
case Penalty.PenaltyType.Flag:
|
||||
if (attacker.Level == Player.Permission.Flagged)
|
||||
if (attacker.Level != Player.Permission.User)
|
||||
break;
|
||||
await saveLog();
|
||||
var e = new GameEvent()
|
||||
|
@ -65,8 +65,6 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
break;
|
||||
case GameEvent.EventType.Ban:
|
||||
break;
|
||||
case GameEvent.EventType.Remote:
|
||||
break;
|
||||
case GameEvent.EventType.Unknown:
|
||||
break;
|
||||
case GameEvent.EventType.Report:
|
||||
@ -83,8 +81,6 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
if (!E.Owner.CustomCallback)
|
||||
await Manager.AddStandardKill(E.Origin, E.Target);
|
||||
break;
|
||||
case GameEvent.EventType.Death:
|
||||
break;
|
||||
case GameEvent.EventType.Damage:
|
||||
// if (!E.Owner.CustomCallback)
|
||||
Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Target.ClientId, E.Owner.GetHashCode());
|
||||
|
@ -117,9 +117,9 @@ namespace SharedLibraryCore.Commands
|
||||
{
|
||||
if (E.Origin.Level > E.Target.Level)
|
||||
{
|
||||
E.Owner.Manager.GetEventHandler().AddEvent(new GameEvent(GameEvent.EventType.Kick, E.Data, E.Origin, E.Target, E.Owner));
|
||||
await E.Target.Kick(E.Data, E.Origin);
|
||||
await E.Origin.Tell($"^5{E.Target} ^7{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_SUCCESS"]}");
|
||||
E.Owner.Manager.GetEventHandler().AddEvent(new GameEvent(GameEvent.EventType.Kick, E.Data, E.Origin, E.Target, E.Owner));
|
||||
}
|
||||
else
|
||||
await E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_FAIL"]} {E.Target.Name}");
|
||||
@ -179,6 +179,14 @@ namespace SharedLibraryCore.Commands
|
||||
{
|
||||
await E.Target.TempBan(Message, length, E.Origin);
|
||||
await E.Origin.Tell($"^5{E.Target} ^7{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_SUCCESS"]} ^5{length.TimeSpanText()}");
|
||||
E.Owner.Manager.GetEventHandler().AddEvent(new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.TempBan,
|
||||
Data = E.Data,
|
||||
Origin = E.Origin,
|
||||
Target = E.Target,
|
||||
Owner = E.Owner
|
||||
});
|
||||
}
|
||||
else
|
||||
await E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_FAIL"]} {E.Target.Name}");
|
||||
@ -209,6 +217,15 @@ namespace SharedLibraryCore.Commands
|
||||
{
|
||||
await E.Target.Ban(E.Data, E.Origin);
|
||||
await E.Origin.Tell($"^5{E.Target} ^7{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_SUCCESS"]}");
|
||||
|
||||
E.Owner.Manager.GetEventHandler().AddEvent(new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Ban,
|
||||
Data = E.Data,
|
||||
Origin = E.Origin,
|
||||
Target = E.Target,
|
||||
Owner = E.Owner
|
||||
});
|
||||
}
|
||||
else
|
||||
await E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_FAIL"]} {E.Target.Name}");
|
||||
@ -753,6 +770,16 @@ namespace SharedLibraryCore.Commands
|
||||
E.Target.Level = Player.Permission.User;
|
||||
await E.Owner.Manager.GetClientService().Update(E.Target);
|
||||
await E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_UNFLAG"]} ^5{E.Target.Name}");
|
||||
|
||||
E.Owner.Manager.GetEventHandler().AddEvent(new GameEvent()
|
||||
{
|
||||
Data = E.Data,
|
||||
Origin = E.Origin,
|
||||
Target = E.Target,
|
||||
Owner = E.Owner,
|
||||
Type = GameEvent.EventType.Unflag
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -17,6 +17,7 @@ namespace SharedLibraryCore.Database
|
||||
public DbSet<EFAliasLink> AliasLinks { get; set; }
|
||||
public DbSet<EFPenalty> Penalties { get; set; }
|
||||
public DbSet<EFMeta> EFMeta { get; set; }
|
||||
public DbSet<EFChangeHistory> EFChangeHistory { get; set; }
|
||||
|
||||
private static string _ConnectionString;
|
||||
|
||||
@ -79,6 +80,11 @@ namespace SharedLibraryCore.Database
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<EFAlias>(ent =>
|
||||
{
|
||||
ent.HasIndex(a => a.IPAddress);
|
||||
});
|
||||
|
||||
// force full name for database conversion
|
||||
modelBuilder.Entity<EFClient>().ToTable("EFClients");
|
||||
modelBuilder.Entity<EFAlias>().ToTable("EFAlias");
|
||||
|
27
SharedLibraryCore/Database/Models/EFChangeHistory.cs
Normal file
27
SharedLibraryCore/Database/Models/EFChangeHistory.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Database.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// This class models the change to different entities
|
||||
/// </summary>
|
||||
public class EFChangeHistory : SharedEntity
|
||||
{
|
||||
public enum ChangeType
|
||||
{
|
||||
Permission
|
||||
}
|
||||
|
||||
[Key]
|
||||
public int ChangeHistoryId { get; set; }
|
||||
public int OriginEntityId { get; set; }
|
||||
public int TargetEntityId { get; set; }
|
||||
public ChangeType TypeOfChange { get; set; }
|
||||
public DateTime TimeChanged { get; set; } = DateTime.UtcNow;
|
||||
[MaxLength(128)]
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
15
SharedLibraryCore/Dtos/EntityInfo.cs
Normal file
15
SharedLibraryCore/Dtos/EntityInfo.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// This class holds the basic info for api entities
|
||||
/// </summary>
|
||||
public class EntityInfo
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -1,39 +1,19 @@
|
||||
using System;
|
||||
using static SharedLibraryCore.GameEvent;
|
||||
|
||||
namespace SharedLibraryCore.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// This class wraps the information related to a generated event for the API
|
||||
/// </summary>
|
||||
public class EventInfo
|
||||
{
|
||||
public EventInfo(EventType Ty, EventVersion V, string M, string T, string O, string Ta)
|
||||
{
|
||||
Type = Ty;
|
||||
Version = V;
|
||||
Message = System.Web.HttpUtility.HtmlEncode(M);
|
||||
Title = T;
|
||||
Origin = System.Web.HttpUtility.HtmlEncode(O);
|
||||
Target = System.Web.HttpUtility.HtmlEncode(Ta);
|
||||
|
||||
ID = Math.Abs(DateTime.Now.GetHashCode());
|
||||
}
|
||||
|
||||
public enum EventType
|
||||
{
|
||||
NOTIFICATION,
|
||||
STATUS,
|
||||
ALERT,
|
||||
}
|
||||
|
||||
public enum EventVersion
|
||||
{
|
||||
IW4MAdmin
|
||||
}
|
||||
|
||||
public EventType Type;
|
||||
public EventVersion Version;
|
||||
public string Message;
|
||||
public string Title;
|
||||
public string Origin;
|
||||
public string Target;
|
||||
public int ID;
|
||||
public EntityInfo OriginEntity { get; set; }
|
||||
public EntityInfo TargetEntity { get; set; }
|
||||
public EntityInfo EventType { get; set; }
|
||||
public EntityInfo OwnerEntity { get; set; }
|
||||
public DateTime EventTime { get; set; }
|
||||
public string ExtraInfo { get; set; }
|
||||
public string Id { get; private set; } = Guid.NewGuid().ToString();
|
||||
}
|
||||
}
|
@ -8,36 +8,37 @@ namespace SharedLibraryCore
|
||||
{
|
||||
public enum EventType
|
||||
{
|
||||
//FROM SERVER
|
||||
Unknown,
|
||||
|
||||
// events "generated" by the server
|
||||
Start,
|
||||
Stop,
|
||||
Connect,
|
||||
// this is for IW5 compatibility
|
||||
Join,
|
||||
Quit,
|
||||
Disconnect,
|
||||
Say,
|
||||
MapChange,
|
||||
MapEnd,
|
||||
MapChange,
|
||||
|
||||
//FROM ADMIN
|
||||
Broadcast,
|
||||
Tell,
|
||||
Kick,
|
||||
Ban,
|
||||
Remote,
|
||||
Unknown,
|
||||
|
||||
//FROM PLAYER
|
||||
// events "generated" by clients
|
||||
Say,
|
||||
Report,
|
||||
Flag,
|
||||
Unflag,
|
||||
Kick,
|
||||
TempBan,
|
||||
Ban,
|
||||
Command,
|
||||
|
||||
// FROM GAME
|
||||
// events "generated" by IW4MAdmin
|
||||
Broadcast,
|
||||
Tell,
|
||||
|
||||
// events "generated" by script/log
|
||||
ScriptDamage,
|
||||
ScriptKill,
|
||||
Kill,
|
||||
Damage,
|
||||
Death,
|
||||
Kill,
|
||||
JoinTeam,
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,17 @@ namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IEventApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Processes event from server as event info
|
||||
/// </summary>
|
||||
/// <param name="sender">Object state from Delegate method call</param>
|
||||
/// <param name="E">Event to process</param>
|
||||
void OnServerEvent(object sender, GameEvent E);
|
||||
Queue<EventInfo> GetEvents();
|
||||
/// <summary>
|
||||
/// Get list of recent events
|
||||
/// </summary>
|
||||
/// <param name="shouldConsume">specify wether the request should clear all events after retrieving</param>
|
||||
/// <returns>List of recent event</returns>
|
||||
IEnumerable<EventInfo> GetEvents(bool shouldConsume);
|
||||
}
|
||||
}
|
||||
|
639
SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.Designer.cs
generated
Normal file
639
SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.Designer.cs
generated
Normal file
@ -0,0 +1,639 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Microsoft.EntityFrameworkCore.Storage.Internal;
|
||||
using SharedLibraryCore.Database;
|
||||
using SharedLibraryCore.Objects;
|
||||
using System;
|
||||
|
||||
namespace SharedLibraryCore.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20180614014303_IndexForEFAlias")]
|
||||
partial class IndexForEFAlias
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
|
||||
{
|
||||
b.Property<int>("SnapshotId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ClientId");
|
||||
|
||||
b.Property<int>("CurrentSessionLength");
|
||||
|
||||
b.Property<double>("CurrentStrain");
|
||||
|
||||
b.Property<int?>("CurrentViewAngleVector3Id");
|
||||
|
||||
b.Property<int>("Deaths");
|
||||
|
||||
b.Property<double>("Distance");
|
||||
|
||||
b.Property<double>("EloRating");
|
||||
|
||||
b.Property<int?>("HitDestinationVector3Id");
|
||||
|
||||
b.Property<int>("HitLocation");
|
||||
|
||||
b.Property<int?>("HitOriginVector3Id");
|
||||
|
||||
b.Property<int>("HitType");
|
||||
|
||||
b.Property<int>("Hits");
|
||||
|
||||
b.Property<int>("Kills");
|
||||
|
||||
b.Property<int?>("LastStrainAngleVector3Id");
|
||||
|
||||
b.Property<double>("SessionAngleOffset");
|
||||
|
||||
b.Property<double>("SessionSPM");
|
||||
|
||||
b.Property<int>("SessionScore");
|
||||
|
||||
b.Property<double>("StrainAngleBetween");
|
||||
|
||||
b.Property<int>("TimeSinceLastEvent");
|
||||
|
||||
b.Property<int>("WeaponId");
|
||||
|
||||
b.Property<DateTime>("When");
|
||||
|
||||
b.HasKey("SnapshotId");
|
||||
|
||||
b.HasIndex("ClientId");
|
||||
|
||||
b.HasIndex("CurrentViewAngleVector3Id");
|
||||
|
||||
b.HasIndex("HitDestinationVector3Id");
|
||||
|
||||
b.HasIndex("HitOriginVector3Id");
|
||||
|
||||
b.HasIndex("LastStrainAngleVector3Id");
|
||||
|
||||
b.ToTable("EFACSnapshot");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
|
||||
{
|
||||
b.Property<long>("KillId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("AttackerId");
|
||||
|
||||
b.Property<int>("Damage");
|
||||
|
||||
b.Property<int?>("DeathOriginVector3Id");
|
||||
|
||||
b.Property<int>("DeathType");
|
||||
|
||||
b.Property<int>("HitLoc");
|
||||
|
||||
b.Property<int?>("KillOriginVector3Id");
|
||||
|
||||
b.Property<int>("Map");
|
||||
|
||||
b.Property<int>("ServerId");
|
||||
|
||||
b.Property<int>("VictimId");
|
||||
|
||||
b.Property<int?>("ViewAnglesVector3Id");
|
||||
|
||||
b.Property<int>("Weapon");
|
||||
|
||||
b.Property<DateTime>("When");
|
||||
|
||||
b.HasKey("KillId");
|
||||
|
||||
b.HasIndex("AttackerId");
|
||||
|
||||
b.HasIndex("DeathOriginVector3Id");
|
||||
|
||||
b.HasIndex("KillOriginVector3Id");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.HasIndex("VictimId");
|
||||
|
||||
b.HasIndex("ViewAnglesVector3Id");
|
||||
|
||||
b.ToTable("EFClientKills");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
|
||||
{
|
||||
b.Property<long>("MessageId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ClientId");
|
||||
|
||||
b.Property<string>("Message");
|
||||
|
||||
b.Property<int>("ServerId");
|
||||
|
||||
b.Property<DateTime>("TimeSent");
|
||||
|
||||
b.HasKey("MessageId");
|
||||
|
||||
b.HasIndex("ClientId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.ToTable("EFClientMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
|
||||
{
|
||||
b.Property<int>("RatingHistoryId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ClientId");
|
||||
|
||||
b.HasKey("RatingHistoryId");
|
||||
|
||||
b.HasIndex("ClientId");
|
||||
|
||||
b.ToTable("EFClientRatingHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
|
||||
{
|
||||
b.Property<int>("ClientId");
|
||||
|
||||
b.Property<int>("ServerId");
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("Deaths");
|
||||
|
||||
b.Property<double>("EloRating");
|
||||
|
||||
b.Property<int>("Kills");
|
||||
|
||||
b.Property<double>("MaxStrain");
|
||||
|
||||
b.Property<double>("RollingWeightedKDR");
|
||||
|
||||
b.Property<double>("SPM");
|
||||
|
||||
b.Property<double>("Skill");
|
||||
|
||||
b.Property<int>("TimePlayed");
|
||||
|
||||
b.HasKey("ClientId", "ServerId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.ToTable("EFClientStatistics");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
|
||||
{
|
||||
b.Property<int>("HitLocationCountId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ClientId")
|
||||
.HasColumnName("EFClientStatistics_ClientId");
|
||||
|
||||
b.Property<int>("HitCount");
|
||||
|
||||
b.Property<float>("HitOffsetAverage");
|
||||
|
||||
b.Property<int>("Location");
|
||||
|
||||
b.Property<float>("MaxAngleDistance");
|
||||
|
||||
b.Property<int>("ServerId")
|
||||
.HasColumnName("EFClientStatistics_ServerId");
|
||||
|
||||
b.HasKey("HitLocationCountId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.HasIndex("ClientId", "ServerId");
|
||||
|
||||
b.ToTable("EFHitLocationCounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
|
||||
{
|
||||
b.Property<int>("RatingId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ActivityAmount");
|
||||
|
||||
b.Property<bool>("Newest");
|
||||
|
||||
b.Property<double>("Performance");
|
||||
|
||||
b.Property<int>("Ranking");
|
||||
|
||||
b.Property<int>("RatingHistoryId");
|
||||
|
||||
b.Property<int?>("ServerId");
|
||||
|
||||
b.HasKey("RatingId");
|
||||
|
||||
b.HasIndex("RatingHistoryId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.ToTable("EFRating");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
|
||||
{
|
||||
b.Property<int>("ServerId");
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("Port");
|
||||
|
||||
b.HasKey("ServerId");
|
||||
|
||||
b.ToTable("EFServers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
|
||||
{
|
||||
b.Property<int>("StatisticId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ServerId");
|
||||
|
||||
b.Property<long>("TotalKills");
|
||||
|
||||
b.Property<long>("TotalPlayTime");
|
||||
|
||||
b.HasKey("StatisticId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.ToTable("EFServerStatistics");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
|
||||
{
|
||||
b.Property<int>("AliasId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<DateTime>("DateAdded");
|
||||
|
||||
b.Property<int>("IPAddress");
|
||||
|
||||
b.Property<int>("LinkId");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("AliasId");
|
||||
|
||||
b.HasIndex("IPAddress");
|
||||
|
||||
b.HasIndex("LinkId");
|
||||
|
||||
b.ToTable("EFAlias");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
|
||||
{
|
||||
b.Property<int>("AliasLinkId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.HasKey("AliasLinkId");
|
||||
|
||||
b.ToTable("EFAliasLinks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
|
||||
{
|
||||
b.Property<int>("ClientId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("AliasLinkId");
|
||||
|
||||
b.Property<int>("Connections");
|
||||
|
||||
b.Property<int>("CurrentAliasId");
|
||||
|
||||
b.Property<DateTime>("FirstConnection");
|
||||
|
||||
b.Property<DateTime>("LastConnection");
|
||||
|
||||
b.Property<int>("Level");
|
||||
|
||||
b.Property<bool>("Masked");
|
||||
|
||||
b.Property<long>("NetworkId");
|
||||
|
||||
b.Property<string>("Password");
|
||||
|
||||
b.Property<string>("PasswordSalt");
|
||||
|
||||
b.Property<int>("TotalConnectionTime");
|
||||
|
||||
b.HasKey("ClientId");
|
||||
|
||||
b.HasIndex("AliasLinkId");
|
||||
|
||||
b.HasIndex("CurrentAliasId");
|
||||
|
||||
b.HasIndex("NetworkId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("EFClients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
|
||||
{
|
||||
b.Property<int>("MetaId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ClientId");
|
||||
|
||||
b.Property<DateTime>("Created");
|
||||
|
||||
b.Property<string>("Extra");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<DateTime>("Updated");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("MetaId");
|
||||
|
||||
b.HasIndex("ClientId");
|
||||
|
||||
b.ToTable("EFMeta");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
|
||||
{
|
||||
b.Property<int>("PenaltyId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<string>("AutomatedOffense");
|
||||
|
||||
b.Property<DateTime>("Expires");
|
||||
|
||||
b.Property<int>("LinkId");
|
||||
|
||||
b.Property<int>("OffenderId");
|
||||
|
||||
b.Property<string>("Offense")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("PunisherId");
|
||||
|
||||
b.Property<int>("Type");
|
||||
|
||||
b.Property<DateTime>("When");
|
||||
|
||||
b.HasKey("PenaltyId");
|
||||
|
||||
b.HasIndex("LinkId");
|
||||
|
||||
b.HasIndex("OffenderId");
|
||||
|
||||
b.HasIndex("PunisherId");
|
||||
|
||||
b.ToTable("EFPenalties");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
|
||||
{
|
||||
b.Property<int>("Vector3Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int?>("EFACSnapshotSnapshotId");
|
||||
|
||||
b.Property<float>("X");
|
||||
|
||||
b.Property<float>("Y");
|
||||
|
||||
b.Property<float>("Z");
|
||||
|
||||
b.HasKey("Vector3Id");
|
||||
|
||||
b.ToTable("Vector3");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||
.WithMany()
|
||||
.HasForeignKey("ClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
|
||||
.WithMany()
|
||||
.HasForeignKey("CurrentViewAngleVector3Id");
|
||||
|
||||
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
|
||||
.WithMany()
|
||||
.HasForeignKey("HitDestinationVector3Id");
|
||||
|
||||
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
|
||||
.WithMany()
|
||||
.HasForeignKey("HitOriginVector3Id");
|
||||
|
||||
b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
|
||||
.WithMany()
|
||||
.HasForeignKey("LastStrainAngleVector3Id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker")
|
||||
.WithMany()
|
||||
.HasForeignKey("AttackerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("SharedLibraryCore.Helpers.Vector3", "DeathOrigin")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeathOriginVector3Id");
|
||||
|
||||
b.HasOne("SharedLibraryCore.Helpers.Vector3", "KillOrigin")
|
||||
.WithMany()
|
||||
.HasForeignKey("KillOriginVector3Id");
|
||||
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim")
|
||||
.WithMany()
|
||||
.HasForeignKey("VictimId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("SharedLibraryCore.Helpers.Vector3", "ViewAngles")
|
||||
.WithMany()
|
||||
.HasForeignKey("ViewAnglesVector3Id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||
.WithMany()
|
||||
.HasForeignKey("ClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||
.WithMany()
|
||||
.HasForeignKey("ClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||
.WithMany()
|
||||
.HasForeignKey("ClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||
.WithMany()
|
||||
.HasForeignKey("ClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics")
|
||||
.WithMany("HitLocations")
|
||||
.HasForeignKey("ClientId", "ServerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
|
||||
{
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory")
|
||||
.WithMany("Ratings")
|
||||
.HasForeignKey("RatingHistoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
|
||||
{
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("LinkId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink")
|
||||
.WithMany()
|
||||
.HasForeignKey("AliasLinkId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias")
|
||||
.WithMany()
|
||||
.HasForeignKey("CurrentAliasId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||
.WithMany("Meta")
|
||||
.HasForeignKey("ClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
|
||||
{
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
|
||||
.WithMany("ReceivedPenalties")
|
||||
.HasForeignKey("LinkId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender")
|
||||
.WithMany("ReceivedPenalties")
|
||||
.HasForeignKey("OffenderId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher")
|
||||
.WithMany("AdministeredPenalties")
|
||||
.HasForeignKey("PunisherId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
|
||||
{
|
||||
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot")
|
||||
.WithMany("PredictedViewAngles")
|
||||
.HasForeignKey("EFACSnapshotSnapshotId");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SharedLibraryCore.Migrations
|
||||
{
|
||||
public partial class IndexForEFAlias : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_EFAlias_IPAddress",
|
||||
table: "EFAlias",
|
||||
column: "IPAddress");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_EFAlias_IPAddress",
|
||||
table: "EFAlias");
|
||||
}
|
||||
}
|
||||
}
|
@ -312,6 +312,8 @@ namespace SharedLibraryCore.Migrations
|
||||
|
||||
b.HasKey("AliasId");
|
||||
|
||||
b.HasIndex("IPAddress");
|
||||
|
||||
b.HasIndex("LinkId");
|
||||
|
||||
b.ToTable("EFAlias");
|
||||
@ -448,8 +450,6 @@ namespace SharedLibraryCore.Migrations
|
||||
|
||||
b.HasKey("Vector3Id");
|
||||
|
||||
//b.HasIndex("EFACSnapshotSnapshotId");
|
||||
|
||||
b.ToTable("Vector3");
|
||||
});
|
||||
|
||||
|
@ -139,6 +139,13 @@ namespace SharedLibraryCore
|
||||
#else
|
||||
Logger.WriteVerbose(Message.StripColors());
|
||||
#endif
|
||||
Manager.GetEventHandler().AddEvent(new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Broadcast,
|
||||
Data = Message,
|
||||
Owner = this
|
||||
});
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ namespace SharedLibraryCore.Services
|
||||
Level = hasExistingAlias ?
|
||||
(await context.Clients.Where(c => c.AliasLinkId == existingAlias.LinkId)
|
||||
.OrderByDescending(c => c.Level)
|
||||
.FirstAsync()).Level :
|
||||
.FirstOrDefaultAsync())?.Level ?? Player.Permission.User :
|
||||
Player.Permission.User,
|
||||
FirstConnection = DateTime.UtcNow,
|
||||
Connections = 1,
|
||||
@ -170,11 +170,16 @@ namespace SharedLibraryCore.Services
|
||||
{
|
||||
// get all clients that use the same aliasId
|
||||
var matchingClients = context.Clients
|
||||
.Where(c => c.CurrentAliasId == client.CurrentAliasId);
|
||||
.Where(c => c.CurrentAliasId == client.CurrentAliasId)
|
||||
// make sure we don't select ourselves twice
|
||||
.Where(c => c.ClientId != entity.ClientId);
|
||||
|
||||
// update all related clients level
|
||||
await matchingClients.ForEachAsync(c => c.Level = (client.Level == Player.Permission.Banned) ?
|
||||
client.Level : entity.Level);
|
||||
await matchingClients.ForEachAsync(c =>
|
||||
{
|
||||
c.Level = (client.Level == Player.Permission.Banned) ? client.Level : entity.Level;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// their alias has been updated and not yet saved
|
||||
|
@ -9,13 +9,10 @@ namespace WebfrontCore.Controllers.API
|
||||
{
|
||||
[HttpGet]
|
||||
[Route("event")]
|
||||
public ActionResult Index()
|
||||
public ActionResult Index(bool shouldConsume = true)
|
||||
{
|
||||
var events = Manager.GetEventApi().GetEvents();
|
||||
var eventsDto = new List<EventInfo>();
|
||||
while (events.Count > 0)
|
||||
eventsDto.Add(events.Dequeue());
|
||||
return Json(eventsDto);
|
||||
var events = Manager.GetEventApi().GetEvents(shouldConsume);
|
||||
return Json(events);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ namespace WebfrontCore.ViewComponents
|
||||
Offense = User.Identity.IsAuthenticated && !string.IsNullOrEmpty(p.AutomatedOffense) ? p.AutomatedOffense : p.Offense,
|
||||
Type = p.Type.ToString(),
|
||||
TimePunished = Utilities.GetTimePassed(p.When, false),
|
||||
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : Utilities.TimeSpanText(p.Expires - DateTime.UtcNow),
|
||||
// show time passed if ban
|
||||
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : $"{(p.Expires.Year == DateTime.MaxValue.Year ? Utilities.GetTimePassed(p.When, true) : Utilities.TimeSpanText(p.Expires - DateTime.UtcNow))}",
|
||||
Sensitive = p.Type == Penalty.PenaltyType.Flag,
|
||||
AutomatedOffense = p.AutomatedOffense
|
||||
});
|
||||
|
@ -70,7 +70,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<span> @Model.TimeRemaining @loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]</span>
|
||||
<span> @Model.TimeRemaining <!-- @loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"] --></span>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
|
Loading…
Reference in New Issue
Block a user