public async Task OnEventAsync(GameEvent E, Server S) { if (E.Type == GameEvent.EventType.Join) { EFClient newPlayer = E.Origin; if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked) { E.Owner.Broadcast(await ProcessAnnouncement(Config.Configuration().PrivilegedAnnouncementMessage, newPlayer)); } newPlayer.Tell(await ProcessAnnouncement(Config.Configuration().UserWelcomeMessage, newPlayer)); if (newPlayer.Level == Permission.Flagged) { string penaltyReason; using (var ctx = new DatabaseContext(disableTracking: true)) { penaltyReason = await ctx.Penalties .Where(p => p.OffenderId == newPlayer.ClientId && p.Type == Penalty.PenaltyType.Flag) .OrderByDescending(p => p.When) .Select(p => p.AutomatedOffense ?? p.Offense) .FirstOrDefaultAsync(); } E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name} ^7({penaltyReason}) has joined!"); } else { E.Owner.Broadcast(await ProcessAnnouncement(Config.Configuration().UserAnnouncementMessage, newPlayer)); } } }
public async Task OnLoadAsync(IManager manager) { AuthorizedClients = new ConcurrentDictionary <int, bool>(); var cfg = new BaseConfigurationHandler <Configuration>("LoginPluginSettings"); if (cfg.Configuration() == null) { cfg.Set((Configuration) new Configuration().Generate()); await cfg.Save(); } Config = cfg.Configuration(); }
public async Task OnLoadAsync(IManager manager) { var cfg = new BaseConfigurationHandler <Configuration>("AutomessageFeedPluginSettings"); if (cfg.Configuration() == null) { cfg.Set((Configuration) new Configuration().Generate()); await cfg.Save(); } _configuration = cfg.Configuration(); manager.GetMessageTokens().Add(new MessageToken("FEED", GetNextFeedItem)); }
public async Task OnEventAsync(GameEvent E, Server S) { HookSender hookSender = new DiscordAlertDotNet.HookSender(Config.Configuration().HookId, Config.Configuration().HookToken); if (E.Type == GameEvent.EventType.Connect) { Player p = E.Origin; if (p.Level >= Player.Permission.Trusted) { await E.Owner.Broadcast(Announce($"Player ^1{p.Name} ^7announced in ^1D^7iscord!", p)); } try { await hookSender.Send(Config.Configuration().OnJoinedMessage.Replace("player", p.Name).Replace("svname", S.Hostname), Config.Configuration().BotName, null, false, null); } catch (Exception e) { Console.WriteLine(e.StackTrace); } } if (E.Type == GameEvent.EventType.Disconnect) { Player p = E.Origin; if (p.Level >= Player.Permission.Trusted) { await E.Owner.Broadcast(Announce($"Player ^1{p.Name} ^7announced in ^1D^7iscord!", p)); } try { await hookSender.Send(Config.Configuration().OnLeftMessage.Replace("player", p.Name).Replace("svname", S.Hostname), Config.Configuration().BotName, null, false, null); } catch (Exception e) { Console.WriteLine(e.StackTrace); } } if (E.Type == GameEvent.EventType.Report) { await hookSender.Send($"**{E.Origin.Name}** has reported **{E.Target.Name}** for: {E.Data.Trim()}", E.Target.Name, E.Origin.Name); } }
public async Task OnLoadAsync(IManager manager) { Config = new BaseConfigurationHandler <DiscordAlertCfg>("DiscordAlertCfg"); if (Config.Configuration() == null) { Config.Set((DiscordAlertCfg) new DiscordAlertCfg().Generate()); await Config.Save(); } }
public async Task OnLoadAsync(IManager manager) { // load custom configuration Config = new BaseConfigurationHandler <WelcomeConfiguration>("WelcomePluginSettings"); if (Config.Configuration() == null) { Config.Set((WelcomeConfiguration) new WelcomeConfiguration().Generate()); await Config.Save(); } }
public async Task OnLoadAsync(IManager manager) { // load custom configuration Settings = new BaseConfigurationHandler <Configuration>("ProfanityDetermentSettings"); if (Settings.Configuration() == null) { Settings.Set((Configuration) new Configuration().Generate()); await Settings.Save(); } ProfanityCounts = new ConcurrentDictionary <int, Tracking>(); Manager = manager; }
public async Task OnEventAsync(GameEvent E, Server S) { if (E.Type == GameEvent.EventType.Connect) { Player newPlayer = E.Origin; if (newPlayer.Level >= Player.Permission.Trusted && !E.Origin.Masked) { await E.Owner.Broadcast(ProcessAnnouncement(Config.Configuration().PrivilegedAnnouncementMessage, newPlayer)); } await newPlayer.Tell(ProcessAnnouncement(Config.Configuration().UserWelcomeMessage, newPlayer)); if (newPlayer.Level == Player.Permission.Flagged) { var penalty = await new GenericRepository <EFPenalty>().FindAsync(p => p.OffenderId == newPlayer.ClientId && p.Type == Penalty.PenaltyType.Flag); await E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name} ^7({penalty.FirstOrDefault()?.Offense}) has joined!"); } else { await E.Owner.Broadcast(ProcessAnnouncement(Config.Configuration().UserAnnouncementMessage, newPlayer)); } } }
public async Task OnEventAsync(GameEvent E, Server S) { if (!Settings.Configuration().EnableProfanityDeterment) { return; } if (E.Type == GameEvent.EventType.Connect) { if (!ProfanityCounts.TryAdd(E.Origin.ClientId, new Tracking(E.Origin))) { S.Logger.WriteWarning("Could not add client to profanity tracking"); } } if (E.Type == GameEvent.EventType.Disconnect) { if (!ProfanityCounts.TryRemove(E.Origin.ClientId, out Tracking old)) { S.Logger.WriteWarning("Could not remove client from profanity tracking"); } } if (E.Type == GameEvent.EventType.Say) { var objectionalWords = Settings.Configuration().OffensiveWords; bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Data.ToLower().Contains(w)) != null; if (containsObjectionalWord) { var clientProfanity = ProfanityCounts[E.Origin.ClientId]; if (clientProfanity.Infringements >= Settings.Configuration().KickAfterInfringementCount) { await clientProfanity.Client.Kick(Settings.Configuration().ProfanityKickMessage, new Player() { ClientId = 1 }); } else if (clientProfanity.Infringements < Settings.Configuration().KickAfterInfringementCount) { clientProfanity.Infringements++; await clientProfanity.Client.Warn(Settings.Configuration().ProfanityWarningMessage, new Player() { ClientId = 1 }); } } } }
public async Task Init() { #region DATABASE var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted)) .Select(c => new { c.Password, c.PasswordSalt, c.ClientId, c.Level, c.Name }); foreach (var a in ipList) { try { PrivilegedClients.Add(a.ClientId, new Player() { Name = a.Name, ClientId = a.ClientId, Level = a.Level, PasswordSalt = a.PasswordSalt, Password = a.Password }); } catch (ArgumentException) { continue; } } #endregion #region CONFIG var config = ConfigHandler.Configuration(); // copy over default config if it doesn't exist if (config == null) { var defaultConfig = new BaseConfigurationHandler <DefaultConfiguration>("DefaultSettings").Configuration(); ConfigHandler.Set((ApplicationConfiguration) new ApplicationConfiguration().Generate()); var newConfig = ConfigHandler.Configuration(); newConfig.AutoMessagePeriod = defaultConfig.AutoMessagePeriod; newConfig.AutoMessages = defaultConfig.AutoMessages; newConfig.GlobalRules = defaultConfig.GlobalRules; newConfig.Maps = defaultConfig.Maps; if (newConfig.Servers == null) { ConfigHandler.Set(newConfig); newConfig.Servers = new List <ServerConfiguration>(); do { newConfig.Servers.Add((ServerConfiguration) new ServerConfiguration().Generate()); } while (Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationSet["SETUP_SERVER_SAVE"])); config = newConfig; await ConfigHandler.Save(); } } else if (config != null) { if (string.IsNullOrEmpty(config.Id)) { config.Id = Guid.NewGuid().ToString(); await ConfigHandler.Save(); } if (string.IsNullOrEmpty(config.WebfrontBindUrl)) { config.WebfrontBindUrl = "http://127.0.0.1:1624"; await ConfigHandler.Save(); } } else if (config.Servers.Count == 0) { throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid"); } Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252"); #endregion #region PLUGINS SharedLibraryCore.Plugins.PluginImporter.Load(this); foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins) { try { await Plugin.OnLoadAsync(this); } catch (Exception e) { Logger.WriteError($"An error occured loading plugin {Plugin.Name}"); Logger.WriteDebug($"Exception: {e.Message}"); Logger.WriteDebug($"Stack Trace: {e.StackTrace}"); } } #endregion #region COMMANDS if (ClientSvc.GetOwners().Result.Count == 0) { Commands.Add(new COwner()); } Commands.Add(new CQuit()); Commands.Add(new CKick()); Commands.Add(new CSay()); Commands.Add(new CTempBan()); Commands.Add(new CBan()); Commands.Add(new CWhoAmI()); Commands.Add(new CList()); Commands.Add(new CHelp()); Commands.Add(new CFastRestart()); Commands.Add(new CMapRotate()); Commands.Add(new CSetLevel()); Commands.Add(new CUsage()); Commands.Add(new CUptime()); Commands.Add(new CWarn()); Commands.Add(new CWarnClear()); Commands.Add(new CUnban()); Commands.Add(new CListAdmins()); Commands.Add(new CLoadMap()); Commands.Add(new CFindPlayer()); Commands.Add(new CListRules()); Commands.Add(new CPrivateMessage()); Commands.Add(new CFlag()); Commands.Add(new CReport()); Commands.Add(new CListReports()); Commands.Add(new CListBanInfo()); Commands.Add(new CListAlias()); Commands.Add(new CExecuteRCON()); Commands.Add(new CPlugins()); Commands.Add(new CIP()); Commands.Add(new CMask()); Commands.Add(new CPruneAdmins()); Commands.Add(new CKillServer()); Commands.Add(new CSetPassword()); Commands.Add(new CPing()); foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands) { Commands.Add(C); } #endregion #region INIT async Task Init(ServerConfiguration Conf) { try { var ServerInstance = new IW4MServer(this, Conf); await ServerInstance.Initialize(); lock (_servers) { _servers.Add(ServerInstance); } Logger.WriteVerbose($"Now monitoring {ServerInstance.Hostname}"); // this way we can keep track of execution time and see if problems arise. var Status = new AsyncStatus(ServerInstance, UPDATE_FREQUENCY); lock (TaskStatuses) { TaskStatuses.Add(Status); } } catch (ServerException e) { Logger.WriteError($"Not monitoring server {Conf.IPAddress}:{Conf.Port} due to uncorrectable errors"); if (e.GetType() == typeof(DvarException)) { Logger.WriteDebug($"Could not get the dvar value for {(e as DvarException).Data["dvar_name"]} (ensure the server has a map loaded)"); } else if (e.GetType() == typeof(NetworkException)) { Logger.WriteDebug(e.Message); } // throw the exception to the main method to stop before instantly exiting throw e; } } await Task.WhenAll(config.Servers.Select(c => Init(c)).ToArray()); #endregion Running = true; }
public async Task OnLoadAsync(IManager manager) { // load custom configuration Config = new BaseConfigurationHandler <StatsConfiguration>("StatsPluginSettings"); if (Config.Configuration() == null) { Config.Set((StatsConfiguration) new StatsConfiguration().Generate()); await Config.Save(); } // meta data info async Task <List <ProfileMeta> > getStats(int clientId) { var statsSvc = new GenericRepository <EFClientStatistics>(); var clientStats = await statsSvc.FindAsync(c => c.ClientId == clientId); int kills = clientStats.Sum(c => c.Kills); int deaths = clientStats.Sum(c => c.Deaths); double kdr = Math.Round(kills / (double)deaths, 2); double skill = Math.Round(clientStats.Sum(c => c.Skill) / clientStats.Count, 2); double spm = Math.Round(clientStats.Sum(c => c.SPM), 1); return(new List <ProfileMeta>() { new ProfileMeta() { Key = "Kills", Value = kills }, new ProfileMeta() { Key = "Deaths", Value = deaths }, new ProfileMeta() { Key = "KDR", Value = kdr }, new ProfileMeta() { Key = "Skill", Value = skill }, new ProfileMeta() { Key = "Score Per Minute", Value = spm } }); } async Task <List <ProfileMeta> > getAnticheatInfo(int clientId) { var statsSvc = new GenericRepository <EFClientStatistics>(); var clientStats = await statsSvc.FindAsync(c => c.ClientId == clientId); double headRatio = 0; double chestRatio = 0; double abdomenRatio = 0; double chestAbdomenRatio = 0; double hitOffsetAverage = 0; if (clientStats.Where(cs => cs.HitLocations.Count > 0).FirstOrDefault() != null) { chestRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0) .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount)), 2); abdomenRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount)), 2); chestAbdomenRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount), 2); headRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.head).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0) .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount)), 2); hitOffsetAverage = clientStats.Sum(c => c.AverageHitOffset) / Math.Max(1, clientStats.Where(c => c.AverageHitOffset > 0).Count()); } return(new List <ProfileMeta>() { new ProfileMeta() { Key = "Chest Ratio", Value = chestRatio, Sensitive = true }, new ProfileMeta() { Key = "Abdomen Ratio", Value = abdomenRatio, Sensitive = true }, new ProfileMeta() { Key = "Chest To Abdomen Ratio", Value = chestAbdomenRatio, Sensitive = true }, new ProfileMeta() { Key = "Headshot Ratio", Value = headRatio, Sensitive = true }, new ProfileMeta() { Key = "Hit Offset Average", Value = $"{Math.Round(((float)hitOffsetAverage).ToDegrees(), 4)}°", Sensitive = true } }); } async Task <List <ProfileMeta> > getMessages(int clientId) { var messageSvc = new GenericRepository <EFClientMessage>(); var messages = await messageSvc.FindAsync(m => m.ClientId == clientId); var messageMeta = messages.Select(m => new ProfileMeta() { Key = "EventMessage", Value = m.Message, When = m.TimeSent }).ToList(); messageMeta.Add(new ProfileMeta() { Key = "Messages", Value = messages.Count }); return(messageMeta); } MetaService.AddMeta(getStats); if (Config.Configuration().EnableAntiCheat) { MetaService.AddMeta(getAnticheatInfo); } MetaService.AddMeta(getMessages); string totalKills() { var serverStats = new GenericRepository <EFServerStatistics>(); return(serverStats.Find(s => s.Active) .Sum(c => c.TotalKills).ToString("#,##0")); } string totalPlayTime() { var serverStats = new GenericRepository <EFServerStatistics>(); return(Math.Ceiling((serverStats.GetQuery(s => s.Active) .Sum(c => c.TotalPlayTime) / 3600.0)).ToString("#,##0")); } manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", totalKills)); manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", totalPlayTime)); ServerManager = manager; Manager = new StatManager(manager); }
public async Task OnLoadAsync(IManager manager) { // load custom configuration Config = new BaseConfigurationHandler <StatsConfiguration>("StatsPluginSettings"); if (Config.Configuration() == null) { Config.Set((StatsConfiguration) new StatsConfiguration().Generate()); await Config.Save(); } // register the topstats page // todo:generate the URL/Location instead of hardcoding manager.GetPageList() .Pages.Add( Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_TOP_TEXT"], "/Stats/TopPlayersAsync"); // meta data info async Task <List <ProfileMeta> > getStats(int clientId, int offset, int count, DateTime?startAt) { if (count > 1) { return(new List <ProfileMeta>()); } IList <EFClientStatistics> clientStats; using (var ctx = new DatabaseContext(disableTracking: true)) { clientStats = await ctx.Set <EFClientStatistics>().Where(c => c.ClientId == clientId).ToListAsync(); } int kills = clientStats.Sum(c => c.Kills); int deaths = clientStats.Sum(c => c.Deaths); double kdr = Math.Round(kills / (double)deaths, 2); var validPerformanceValues = clientStats.Where(c => c.Performance > 0); int performancePlayTime = validPerformanceValues.Sum(s => s.TimePlayed); double performance = Math.Round(validPerformanceValues.Sum(c => c.Performance * c.TimePlayed / performancePlayTime), 2); double spm = Math.Round(clientStats.Sum(c => c.SPM) / clientStats.Where(c => c.SPM > 0).Count(), 1); return(new List <ProfileMeta>() { new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_RANKING"], Value = "#" + (await StatManager.GetClientOverallRanking(clientId)).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Column = 0, Order = 0, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"], Value = kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Column = 0, Order = 1, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"], Value = deaths.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Column = 0, Order = 2, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"], Value = kdr.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Column = 0, Order = 3, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_PERFORMANCE"], Value = performance.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Column = 0, Order = 4, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"], Value = spm.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Column = 0, Order = 5, Type = ProfileMeta.MetaType.Information } }); } async Task <List <ProfileMeta> > getAnticheatInfo(int clientId, int offset, int count, DateTime?startAt) { if (count > 1) { return(new List <ProfileMeta>()); } IList <EFClientStatistics> clientStats; using (var ctx = new DatabaseContext(disableTracking: true)) { clientStats = await ctx.Set <EFClientStatistics>() .Include(c => c.HitLocations) .Where(c => c.ClientId == clientId) .ToListAsync(); } double headRatio = 0; double chestRatio = 0; double abdomenRatio = 0; double chestAbdomenRatio = 0; double hitOffsetAverage = 0; double maxStrain = clientStats.Count(c => c.MaxStrain > 0) == 0 ? 0 : clientStats.Max(cs => cs.MaxStrain); if (clientStats.Where(cs => cs.HitLocations.Count > 0).FirstOrDefault() != null) { chestRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0) .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); abdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); chestAbdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount)) * 100.0, 0); headRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.head).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0) .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); var validOffsets = clientStats.Where(c => c.HitLocations.Count(hl => hl.HitCount > 0) > 0).SelectMany(hl => hl.HitLocations); hitOffsetAverage = validOffsets.Sum(o => o.HitCount * o.HitOffsetAverage) / (double)validOffsets.Sum(o => o.HitCount); } return(new List <ProfileMeta>() { new ProfileMeta() { Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 1", Value = chestRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%', Type = ProfileMeta.MetaType.Information, Column = 2, Order = 0, Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM1"], Sensitive = true }, new ProfileMeta() { Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 2", Value = abdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%', Type = ProfileMeta.MetaType.Information, Column = 2, Order = 1, Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM2"], Sensitive = true }, new ProfileMeta() { Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 3", Value = chestAbdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%', Type = ProfileMeta.MetaType.Information, Column = 2, Order = 2, Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM3"], Sensitive = true }, new ProfileMeta() { Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 4", Value = headRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%', Type = ProfileMeta.MetaType.Information, Column = 2, Order = 3, Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM4"], Sensitive = true }, new ProfileMeta() { Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 5", // todo: make sure this is wrapped somewhere else Value = $"{Math.Round(((float)hitOffsetAverage), 4).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))}°", Type = ProfileMeta.MetaType.Information, Column = 2, Order = 4, Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM5"], Sensitive = true }, new ProfileMeta() { Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 6", Value = Math.Round(maxStrain, 3).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Type = ProfileMeta.MetaType.Information, Column = 2, Order = 5, Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM6"], Sensitive = true }, }); } async Task <List <ProfileMeta> > getMessages(int clientId, int offset, int count, DateTime?startAt) { 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(_message => _message.ClientId == clientId)) .ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Column = 1, Order = 4, Type = ProfileMeta.MetaType.Information } }); } } List <ProfileMeta> messageMeta; using (var ctx = new DatabaseContext(disableTracking: true)) { var messages = ctx.Set <EFClientMessage>() .Where(m => m.ClientId == clientId) .Where(_message => _message.TimeSent < startAt) .OrderByDescending(_message => _message.TimeSent) .Skip(offset) .Take(count); messageMeta = await messages.Select(m => new ProfileMeta() { Key = null, Value = new { m.Message, m.Server.GameName }, When = m.TimeSent, Extra = m.ServerId.ToString(), Type = ProfileMeta.MetaType.ChatMessage }).ToListAsync(); foreach (var message in messageMeta) { if ((message.Value.Message as string).IsQuickMessage()) { try { var quickMessages = ServerManager.GetApplicationSettings().Configuration() .QuickMessages .First(_qm => _qm.Game == message.Value.GameName); message.Value = quickMessages.Messages[(message.Value.Message as string).Substring(1)]; message.Type = ProfileMeta.MetaType.QuickMessage; } catch { message.Value = message.Value.Message; } } else { message.Value = message.Value.Message; } } } return(messageMeta); } if (Config.Configuration().EnableAntiCheat) { MetaService.AddRuntimeMeta(getAnticheatInfo); } MetaService.AddRuntimeMeta(getStats); MetaService.AddRuntimeMeta(getMessages); async Task <string> totalKills(Server server) { using (var ctx = new DatabaseContext(disableTracking: true)) { long kills = await ctx.Set <EFServerStatistics>().Where(s => s.Active).SumAsync(s => s.TotalKills); return(kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))); } } async Task <string> totalPlayTime(Server server) { using (var ctx = new DatabaseContext(disableTracking: true)) { long playTime = await ctx.Set <EFServerStatistics>().Where(s => s.Active).SumAsync(s => s.TotalPlayTime); return((playTime / 3600.0).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))); } } async Task <string> topStats(Server s) { return(string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s))); } async Task <string> mostPlayed(Server s) { return(string.Join(Environment.NewLine, await Commands.MostPlayed.GetMostPlayed(s))); } manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", totalKills)); manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", totalPlayTime)); manager.GetMessageTokens().Add(new MessageToken("TOPSTATS", topStats)); manager.GetMessageTokens().Add(new MessageToken("MOSTPLAYED", mostPlayed)); ServerManager = manager; Manager = new StatManager(manager); }
public async Task UpdateServerStates(CancellationToken token) { // store the server hash code and task for it var runningUpdateTasks = new Dictionary <long, Task>(); while (Running) { // select the server ids that have completed the update task var serverTasksToRemove = runningUpdateTasks .Where(ut => ut.Value.Status == TaskStatus.RanToCompletion || ut.Value.Status == TaskStatus.Canceled || ut.Value.Status == TaskStatus.Faulted) .Select(ut => ut.Key) .ToList(); // this is to prevent the log reader from starting before the initial // query of players on the server if (serverTasksToRemove.Count > 0) { IsInitialized = true; } // remove the update tasks as they have completd foreach (long serverId in serverTasksToRemove) { runningUpdateTasks.Remove(serverId); } // select the servers where the tasks have completed var serverIds = Servers.Select(s => s.EndPoint).Except(runningUpdateTasks.Select(r => r.Key)).ToList(); foreach (var server in Servers.Where(s => serverIds.Contains(s.EndPoint))) { runningUpdateTasks.Add(server.EndPoint, Task.Run(async() => { try { await server.ProcessUpdatesAsync(token); if (server.Throttled) { await Task.Delay((int)_throttleTimeout.TotalMilliseconds); } } catch (Exception e) { Logger.WriteWarning($"Failed to update status for {server}"); Logger.WriteDebug(e.GetExceptionInfo()); } finally { server.IsInitialized = true; } })); } #if DEBUG Logger.WriteDebug($"{runningUpdateTasks.Count} servers queued for stats updates"); ThreadPool.GetMaxThreads(out int workerThreads, out int n); ThreadPool.GetAvailableThreads(out int availableThreads, out int m); Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks"); #endif try { await Task.Delay(ConfigHandler.Configuration().RConPollRate, token); } // if a cancellation is received, we want to return immediately catch { break; } } }
public Task OnEventAsync(GameEvent E, Server S) { if (!Settings.Configuration().EnableProfanityDeterment) { return(Task.CompletedTask); } if (E.Type == GameEvent.EventType.Connect) { if (!ProfanityCounts.TryAdd(E.Origin.ClientId, new Tracking(E.Origin))) { S.Logger.WriteWarning("Could not add client to profanity tracking"); } var objectionalWords = Settings.Configuration().OffensiveWords; bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Origin.Name.ToLower().Contains(w)) != null; // we want to run regex against it just incase if (!containsObjectionalWord) { foreach (string word in objectionalWords) { containsObjectionalWord |= Regex.IsMatch(E.Origin.Name.ToLower(), word, RegexOptions.IgnoreCase); } } if (containsObjectionalWord) { E.Origin.Kick(Settings.Configuration().ProfanityKickMessage, Utilities.IW4MAdminClient(E.Owner)); } ; } if (E.Type == GameEvent.EventType.Disconnect) { if (!ProfanityCounts.TryRemove(E.Origin.ClientId, out Tracking old)) { S.Logger.WriteWarning("Could not remove client from profanity tracking"); } } if (E.Type == GameEvent.EventType.Say) { var objectionalWords = Settings.Configuration().OffensiveWords; bool containsObjectionalWord = false; foreach (string word in objectionalWords) { containsObjectionalWord |= Regex.IsMatch(E.Data.ToLower(), word, RegexOptions.IgnoreCase); // break out early because there's at least one objectional word if (containsObjectionalWord) { break; } } if (containsObjectionalWord) { var clientProfanity = ProfanityCounts[E.Origin.ClientId]; if (clientProfanity.Infringements >= Settings.Configuration().KickAfterInfringementCount) { clientProfanity.Client.Kick(Settings.Configuration().ProfanityKickMessage, Utilities.IW4MAdminClient(E.Owner)); } else if (clientProfanity.Infringements < Settings.Configuration().KickAfterInfringementCount) { clientProfanity.Infringements++; clientProfanity.Client.Warn(Settings.Configuration().ProfanityWarningMessage, Utilities.IW4MAdminClient(E.Owner)); } } } return(Task.CompletedTask); }
/// <summary> /// Configures the dependency injection services /// </summary> private static IServiceCollection ConfigureServices(string[] args) { var appConfigHandler = new BaseConfigurationHandler <ApplicationConfiguration>("IW4MAdminSettings"); var appConfig = appConfigHandler.Configuration(); var defaultLogger = new Logger("IW4MAdmin-Manager"); var masterUri = Utilities.IsDevelopment ? new Uri("http://127.0.0.1:8080") : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl; var apiClient = RestClient.For <IMasterApi>(masterUri); var pluginImporter = new PluginImporter(defaultLogger, appConfig, apiClient, new RemoteAssemblyHandler(defaultLogger, appConfig)); var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton <IServiceCollection>(_serviceProvider => serviceCollection) .AddSingleton(appConfigHandler as IConfigurationHandler <ApplicationConfiguration>) .AddSingleton(new BaseConfigurationHandler <CommandConfiguration>("CommandConfiguration") as IConfigurationHandler <CommandConfiguration>) .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService <IConfigurationHandler <ApplicationConfiguration> >().Configuration() ?? new ApplicationConfiguration()) .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService <IConfigurationHandler <CommandConfiguration> >().Configuration() ?? new CommandConfiguration()) .AddSingleton <ILogger>(_serviceProvider => defaultLogger) .AddSingleton <IPluginImporter, PluginImporter>() .AddSingleton <IMiddlewareActionHandler, MiddlewareActionHandler>() .AddSingleton <IRConConnectionFactory, RConConnectionFactory>() .AddSingleton <IGameServerInstanceFactory, GameServerInstanceFactory>() .AddSingleton <IConfigurationHandlerFactory, ConfigurationHandlerFactory>() .AddSingleton <IParserRegexFactory, ParserRegexFactory>() .AddSingleton <IDatabaseContextFactory, DatabaseContextFactory>() .AddSingleton <IGameLogReaderFactory, GameLogReaderFactory>() .AddSingleton <IScriptCommandFactory, ScriptCommandFactory>() .AddSingleton <IAuditInformationRepository, AuditInformationRepository>() .AddSingleton <IEntityService <EFClient>, ClientService>() .AddSingleton <IMetaService, MetaService>() .AddSingleton <IMetaRegistration, MetaRegistration>() .AddSingleton <IScriptPluginServiceResolver, ScriptPluginServiceResolver>() .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, ReceivedPenaltyResponse>, ReceivedPenaltyResourceQueryHelper>() .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, AdministeredPenaltyResponse>, AdministeredPenaltyResourceQueryHelper>() .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, UpdatedAliasResponse>, UpdatedAliasResourceQueryHelper>() .AddSingleton <IResourceQueryHelper <ChatSearchQuery, MessageResponse>, ChatResourceQueryHelper>() .AddTransient <IParserPatternMatcher, ParserPatternMatcher>() .AddSingleton <IRemoteAssemblyHandler, RemoteAssemblyHandler>() .AddSingleton <IMasterCommunication, MasterCommunication>() .AddSingleton <IManager, ApplicationManager>() .AddSingleton(apiClient) .AddSingleton(_serviceProvider => { var config = _serviceProvider.GetRequiredService <IConfigurationHandler <ApplicationConfiguration> >().Configuration(); return(Localization.Configure.Initialize(useLocalTranslation: config?.UseLocalTranslations ?? false, apiInstance: _serviceProvider.GetRequiredService <IMasterApi>(), customLocale: config?.EnableCustomLocale ?? false ? (config.CustomLocale ?? "en-US") : "en-US")); }); if (args.Contains("serialevents")) { serviceCollection.AddSingleton <IEventHandler, SerialGameEventHandler>(); } else { serviceCollection.AddSingleton <IEventHandler, GameEventHandler>(); } // register the native commands foreach (var commandType in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes() .Where(_command => _command.BaseType == typeof(Command))) { defaultLogger.WriteInfo($"Registered native command type {commandType.Name}"); serviceCollection.AddSingleton(typeof(IManagerCommand), commandType); } // register the plugin implementations var pluginImplementations = pluginImporter.DiscoverAssemblyPluginImplementations(); foreach (var pluginType in pluginImplementations.Item1) { defaultLogger.WriteInfo($"Registered plugin type {pluginType.FullName}"); serviceCollection.AddSingleton(typeof(IPlugin), pluginType); } // register the plugin commands foreach (var commandType in pluginImplementations.Item2) { defaultLogger.WriteInfo($"Registered plugin command type {commandType.FullName}"); serviceCollection.AddSingleton(typeof(IManagerCommand), commandType); } // register any script plugins foreach (var scriptPlugin in pluginImporter.DiscoverScriptPlugins()) { serviceCollection.AddSingleton(scriptPlugin); } // register any eventable types foreach (var assemblyType in typeof(Program).Assembly.GetTypes() .Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType)) .Union(pluginImplementations .Item1.SelectMany(_asm => _asm.Assembly.GetTypes()) .Distinct() .Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType)))) { var instance = Activator.CreateInstance(assemblyType) as IRegisterEvent; serviceCollection.AddSingleton(instance); } return(serviceCollection); }
/// <summary> /// Configures the dependency injection services /// </summary> private static IServiceCollection ConfigureServices(string[] args) { // setup the static resources (config/master api/translations) var serviceCollection = new ServiceCollection(); var appConfigHandler = new BaseConfigurationHandler <ApplicationConfiguration>("IW4MAdminSettings"); var defaultConfigHandler = new BaseConfigurationHandler <DefaultSettings>("DefaultSettings"); var defaultConfig = defaultConfigHandler.Configuration(); var appConfig = appConfigHandler.Configuration(); var masterUri = Utilities.IsDevelopment ? new Uri("http://127.0.0.1:8080") : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl; var httpClient = new HttpClient { BaseAddress = masterUri, Timeout = TimeSpan.FromSeconds(15) }; var masterRestClient = RestClient.For <IMasterApi>(httpClient); var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig); if (appConfig == null) { appConfig = (ApplicationConfiguration) new ApplicationConfiguration().Generate(); appConfigHandler.Set(appConfig); appConfigHandler.Save(); } // register override level names foreach (var(key, value) in appConfig.OverridePermissionLevelNames) { if (!Utilities.PermissionLevelOverrides.ContainsKey(key)) { Utilities.PermissionLevelOverrides.Add(key, value); } } // build the dependency list HandlePluginRegistration(appConfig, serviceCollection, masterRestClient); serviceCollection .AddBaseLogger(appConfig) .AddSingleton(defaultConfig) .AddSingleton <IServiceCollection>(_serviceProvider => serviceCollection) .AddSingleton <IConfigurationHandler <DefaultSettings>, BaseConfigurationHandler <DefaultSettings> >() .AddSingleton((IConfigurationHandler <ApplicationConfiguration>)appConfigHandler) .AddSingleton( new BaseConfigurationHandler <CommandConfiguration>("CommandConfiguration") as IConfigurationHandler <CommandConfiguration>) .AddSingleton(appConfig) .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService <IConfigurationHandler <CommandConfiguration> >() .Configuration() ?? new CommandConfiguration()) .AddSingleton <IPluginImporter, PluginImporter>() .AddSingleton <IMiddlewareActionHandler, MiddlewareActionHandler>() .AddSingleton <IRConConnectionFactory, RConConnectionFactory>() .AddSingleton <IGameServerInstanceFactory, GameServerInstanceFactory>() .AddSingleton <IConfigurationHandlerFactory, ConfigurationHandlerFactory>() .AddSingleton <IParserRegexFactory, ParserRegexFactory>() .AddSingleton <IDatabaseContextFactory, DatabaseContextFactory>() .AddSingleton <IGameLogReaderFactory, GameLogReaderFactory>() .AddSingleton <IScriptCommandFactory, ScriptCommandFactory>() .AddSingleton <IAuditInformationRepository, AuditInformationRepository>() .AddSingleton <IEntityService <EFClient>, ClientService>() .AddSingleton <IMetaService, MetaService>() .AddSingleton <ClientService>() .AddSingleton <PenaltyService>() .AddSingleton <ChangeHistoryService>() .AddSingleton <IMetaRegistration, MetaRegistration>() .AddSingleton <IScriptPluginServiceResolver, ScriptPluginServiceResolver>() .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, ReceivedPenaltyResponse>, ReceivedPenaltyResourceQueryHelper>() .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, AdministeredPenaltyResponse>, AdministeredPenaltyResourceQueryHelper>() .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, UpdatedAliasResponse>, UpdatedAliasResourceQueryHelper>() .AddSingleton <IResourceQueryHelper <ChatSearchQuery, MessageResponse>, ChatResourceQueryHelper>() .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, ConnectionHistoryResponse>, ConnectionsResourceQueryHelper>() .AddTransient <IParserPatternMatcher, ParserPatternMatcher>() .AddSingleton <IRemoteAssemblyHandler, RemoteAssemblyHandler>() .AddSingleton <IMasterCommunication, MasterCommunication>() .AddSingleton <IManager, ApplicationManager>() .AddSingleton <SharedLibraryCore.Interfaces.ILogger, Logger>() .AddSingleton <IClientNoticeMessageFormatter, ClientNoticeMessageFormatter>() .AddSingleton <IClientStatisticCalculator, HitCalculator>() .AddSingleton <IServerDistributionCalculator, ServerDistributionCalculator>() .AddSingleton <IWeaponNameParser, WeaponNameParser>() .AddSingleton <IHitInfoBuilder, HitInfoBuilder>() .AddSingleton(typeof(ILookupCache <>), typeof(LookupCache <>)) .AddSingleton(typeof(IDataValueCache <,>), typeof(DataValueCache <,>)) .AddSingleton <IServerDataViewer, ServerDataViewer>() .AddSingleton <IServerDataCollector, ServerDataCollector>() .AddSingleton <IEventPublisher, EventPublisher>() .AddSingleton(translationLookup) .AddDatabaseContextOptions(appConfig); if (args.Contains("serialevents")) { serviceCollection.AddSingleton <IEventHandler, SerialGameEventHandler>(); } else { serviceCollection.AddSingleton <IEventHandler, GameEventHandler>(); } serviceCollection.AddSource(); return(serviceCollection); }