using System; using System.Collections.Generic; using System.Linq; using System.Text; using Data.Models; using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Application.Misc { /// /// implementation of IClientNoticeMessageFormatter /// public class ClientNoticeMessageFormatter : IClientNoticeMessageFormatter { private readonly ITranslationLookup _transLookup; private readonly ApplicationConfiguration _appConfig; public ClientNoticeMessageFormatter(ITranslationLookup transLookup, ApplicationConfiguration appConfig) { _transLookup = transLookup; _appConfig = appConfig; } public string BuildFormattedMessage(IRConParserConfiguration config, EFPenalty currentPenalty, EFPenalty originalPenalty = null) { var isNewLineSeparator = config.NoticeLineSeparator == Environment.NewLine; var penalty = originalPenalty ?? currentPenalty; var builder = new StringBuilder(); // build the top level header var header = _transLookup[$"SERVER_{penalty.Type.ToString().ToUpper()}_TEXT"]; builder.Append(header); builder.Append(config.NoticeLineSeparator); // build the reason var reason = _transLookup["GAME_MESSAGE_PENALTY_REASON"].FormatExt(penalty.Offense.FormatMessageForEngine(config)); if (isNewLineSeparator) { foreach (var splitReason in SplitOverMaxLength(reason, config.NoticeMaxCharactersPerLine)) { builder.Append(splitReason); builder.Append(config.NoticeLineSeparator); } } else { builder.Append(reason); builder.Append(config.NoticeLineSeparator); } if (penalty.Type == EFPenalty.PenaltyType.TempBan) { // build the time remaining if temporary var timeRemainingValue = penalty.Expires.HasValue ? (penalty.Expires - DateTime.UtcNow).Value.HumanizeForCurrentCulture() : "--"; var timeRemaining = _transLookup["GAME_MESSAGE_PENALTY_TIME_REMAINING"].FormatExt(timeRemainingValue); if (isNewLineSeparator) { foreach (var splitReason in SplitOverMaxLength(timeRemaining, config.NoticeMaxCharactersPerLine)) { builder.Append(splitReason); builder.Append(config.NoticeLineSeparator); } } else { builder.Append(timeRemaining); } } if (penalty.Type == EFPenalty.PenaltyType.Ban) { // provide a place to appeal the ban (should always be specified but including a placeholder just incase) builder.Append(_transLookup["GAME_MESSAGE_PENALTY_APPEAL"].FormatExt(_appConfig.ContactUri ?? "--")); } // final format looks something like: /* * You are permanently banned * Reason - toxic behavior * Visit example.com to appeal */ return builder.ToString(); } private static IEnumerable SplitOverMaxLength(string source, int maxCharactersPerLine) { if (source.Length <= maxCharactersPerLine) { return new[] {source}; } var segments = new List(); var currentLocation = 0; while (currentLocation < source.Length) { var nextLocation = currentLocation + maxCharactersPerLine; // there's probably a more efficient way to do this but this is readable segments.Add(string.Concat( source .Skip(currentLocation) .Take(Math.Min(maxCharactersPerLine, source.Length - currentLocation)))); currentLocation = nextLocation; } if (currentLocation < source.Length) { segments.Add(source.Substring(currentLocation, source.Length - currentLocation)); } return segments; } } }