public void HandleDelayedCommand(string clientUniqueId, string command, List <string> parameters, Action <string> messageCallback) { TimerInfos.Remove(clientUniqueId); Client invoker = Parent.Client.GetClientByUniqueId(clientUniqueId); if (invoker == null) { string lastSeenName = Parent.Settings.LastSeenUsernames[clientUniqueId]; messageCallback.Invoke(ColorCoder.ErrorBright($"Delayed command for {FormatCommandString(command, parameters)} was not executed as invoker {ColorCoder.Username(lastSeenName)} is no longer online")); return; } string commandMessage = FormatCommandStringRaw(command, parameters); NotifyTextMessageEvent evt = new NotifyTextMessageEvent() { InvokerId = invoker.Id, InvokerName = invoker.Nickname, InvokerUniqueId = invoker.UniqueId, Message = commandMessage, }; messageCallback.Invoke($"Invoking command {FormatCommandString(command, parameters)} for {ColorCoder.Username(invoker.Nickname)}"); Parent.CommandHandler.HandleTextMessage(evt, messageCallback); }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { CooldownManager.ThrowIfCooldown(evt.InvokerUniqueId, "command:daily"); int currentBalance = EconomyManager.GetBalanceForUser(evt.InvokerUniqueId); if (currentBalance + Settings.DailyReward > Settings.EcoSoftBalanceLimit) { messageCallback.Invoke(ColorCoder.ErrorBright($"You would have more than {ColorCoder.Currency(Settings.EcoSoftBalanceLimit, Settings.EcoPointUnitName)}, {ColorCoder.Username(evt.InvokerName)}. Your balance: {ColorCoder.Currency(currentBalance, Settings.EcoPointUnitName)} | Daily reward: {ColorCoder.Currency(Settings.DailyReward, Settings.EcoPointUnitName)}")); return; } DateTime cooldownDue = DateTime.Today.AddDays(1).AddHours(7); DateTime todayCheck = DateTime.Today.AddHours(7); if (todayCheck > DateTime.Now) { cooldownDue = todayCheck; } CooldownManager.SetCooldown(evt.InvokerUniqueId, "command:daily", cooldownDue); EconomyManager.ChangeBalanceForUser(evt.InvokerUniqueId, Settings.DailyReward); messageCallback.Invoke(ColorCoder.SuccessDim($"{ColorCoder.Currency(Settings.DailyReward, Settings.EcoPointUnitName)} have been added to your balance as daily reward, {ColorCoder.Username(evt.InvokerName)}")); }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { if (parameters.Count == 0) { string toPrint = $"All commands are listed below ({ChatCommandHandler.ChatCommands.Count}):"; foreach (ChatCommand cmd in ChatCommandHandler.ChatCommands.OrderBy((cmd) => cmd.CommandPrefix)) { string commandHelp = $"\n{ColorCoder.Bold($"{Settings.ChatCommandPrefix}{cmd.CommandPrefix}")}:\t-\t{cmd.GetUsageDescription(cmd.CommandPrefix, parameters)}"; if (!cmd.CanExecute(evt.InvokerUniqueId, cmd.CommandPrefix, parameters)) { commandHelp = ColorCoder.ColorText(Color.LightRed, commandHelp); } toPrint += commandHelp; } messageCallback.Invoke(toPrint); } else { string requestedCommand = parameters[0]; parameters = parameters.Skip(1).ToList(); foreach (ChatCommand cmd in ChatCommandHandler.ChatCommands) { if (cmd.CommandPrefix == requestedCommand || cmd.CommandAliases.Contains(requestedCommand)) { ChatCommand chatCommand = (ChatCommand)Activator.CreateInstance(cmd.GetType()); chatCommand.Parent = Parent; chatCommand.Settings = Settings; try { if (!chatCommand.CanExecute(evt.InvokerUniqueId, requestedCommand, parameters)) { messageCallback.Invoke(ColorCoder.ErrorBright($"You don't have access to view the help of this command")); break; } if (!chatCommand.IsValidCommandSyntax(requestedCommand, parameters)) { //parameters = new List<string>(); } } catch (CommandParameterInvalidFormatException) {} string helpUsage = Settings.ChatCommandPrefix + chatCommand.GetUsageSyntax(requestedCommand, parameters); string helpDescription = chatCommand.GetUsageDescription(requestedCommand, parameters); string aliases = string.Join(", ", chatCommand.CommandAliases); aliases = string.IsNullOrEmpty(aliases) ? "<None>" : aliases; messageCallback.Invoke($"Help for command {ColorCoder.Bold($"'{chatCommand.CommandPrefix}'")}:\n\t{ColorCoder.Bold("Aliases:")} {aliases}\n\t{ColorCoder.Bold("Usage:")} {helpUsage}\n\t{ColorCoder.Bold("Description:")} {helpDescription}"); break; } } } }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { string action = parameters[0]; string targetUser = parameters[1]; Client target = Parent.Client.GetClientByNamePart(targetUser); Group group = null; if (action == "add" || action == "remove") { group = AccessManager.GetGroupByName(parameters[2]); if (group == null) { messageCallback.Invoke(ColorCoder.ErrorBright($"The group named '{ColorCoder.Bold(parameters[2])}' was not found")); return; } } if (action == "add") { bool success = AccessManager.AddUserGroup(target.UniqueId, group); if (success) { messageCallback.Invoke(ColorCoder.Success($"{ColorCoder.Username(target.Nickname)} was added to the group '{ColorCoder.Bold(group.DisplayName)}'")); } else { messageCallback.Invoke(ColorCoder.ErrorBright($"{ColorCoder.Username(target.Nickname)} is already in the group '{ColorCoder.Bold(group.DisplayName)}'")); } } else if (action == "remove") { bool success = AccessManager.RemoveUserGroup(target.UniqueId, group); if (success) { messageCallback.Invoke(ColorCoder.Success($"{ColorCoder.Username(target.Nickname)} was removed from the group '{ColorCoder.Bold(group.DisplayName)}'")); } else { messageCallback.Invoke(ColorCoder.ErrorBright($"{ColorCoder.Username(target.Nickname)} was not in the group '{ColorCoder.Bold(group.DisplayName)}'")); } } else if (action == "list") { List <Group> groups = AccessManager.GetUserGroups(target.UniqueId); string toPrint = $"{ColorCoder.Username(target.Nickname)} has the following groups:"; foreach (Group printGroup in groups) { toPrint += $"\n\t- {printGroup.DisplayName}"; } messageCallback.Invoke(toPrint); } }
public static void HandleStatsRequest(string nameSearch, int leaderboardId, Action <string> messageCallback) { AoeLeaderboardResponse response = GetLeaderboardResponse(leaderboardId, nameSearch, 2); if (response.Count == 0) { messageCallback.Invoke($"There were no players found on leaderboard '{leaderboardId}' with the name '{nameSearch}'"); return; } else if (response.Count > 1) { messageCallback.Invoke($"There were multiple players found on leaderboard '{leaderboardId}' with the name '{nameSearch}'"); return; } AoePlayer player = response.Leaderboard[0]; string clanAddition = player.Clan == null ? "" : $"[{player.Clan}]"; string leaderboardName = Leaderboards.First(kv => kv.Value == leaderboardId).Key; int ratingDiff = player.Rating.Value - player.PreviousRating.Value; string ratingDiffStr = ratingDiff < 0 ? ColorCoder.ErrorBright(ratingDiff) : ratingDiff > 0 ? ColorCoder.SuccessDim(ratingDiff) : $"{ratingDiff}"; double ratioPercent = (double)player.Wins.Value * 100 / player.Games.Value; string ratioPercentStr = $"{ratioPercent:0.##}%"; ratioPercentStr = ratioPercent < 50 ? ColorCoder.ErrorBright(ratioPercentStr) : ratioPercent > 50 ? ColorCoder.SuccessDim(ratioPercentStr) : $"{ratioPercentStr}"; string toPrint = $"{ColorCoder.Bold(leaderboardName.ToUpper())} stats for {ColorCoder.Bold(player.Name+clanAddition)}:"; toPrint += $"\n\tRating: {ColorCoder.Bold(player.Rating.Value)} ({ratingDiffStr}) (#{player.Rank})"; toPrint += $"\n\tPeak Rating: {player.HighestRating}"; toPrint += $"\n\tStreak: {player.Streak} | Lowest: {player.LowestStreak} | Highest: {player.HighestStreak}"; toPrint += $"\n\tGames: {player.Games} ({ColorCoder.SuccessDim(player.Wins.Value+"W")} - {ColorCoder.ErrorBright(player.Losses.Value+"L")} | {ratioPercentStr})"; toPrint += $"\n\tCountry: {player.Country}"; messageCallback.Invoke(toPrint); }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { // +----------------------+ // | Administrative Block | // +----------------------+ if (IsAdministrativeCommand) { if (AdminAction == "add-file") { AddPlaysound(AdminPlaysoundName, AdminPlaysoundPrice, AdminPlaysoundFileName, AdminPlaysoundSource, messageCallback); } else if (AdminAction == "add-yt") { } else if (AdminAction == "remove") { RemovePlaysound(AdminPlaysoundName, messageCallback); } else if (AdminAction == "add-modifier") { } else if (AdminAction == "list-devices") { string devices = string.Join("\n\t", AudioHelper.GetAudioDevices()); messageCallback.Invoke($"All audio devices:\n\t{devices}"); } else if (AdminAction == "stop-sounds") { int killed = 0; foreach (Process p in AllStartedSoundProcesses) { if (!p.HasExited) { p.Kill(); killed++; } } AllStartedSoundProcesses.Clear(); messageCallback.Invoke(ColorCoder.ErrorBright($"Killed {ColorCoder.Bold($"'{killed}'")} audio process(es)")); } return; } if (parameters.Count == 2 && parameters[0] == "price") { int price = CalculateYoutubePlaysoundCost(PriceLookupDuration); messageCallback.Invoke($"Cost for {ColorCoder.Bold($"'{PriceLookupDuration}'")} seconds of a youtube video: {ColorCoder.Currency(price)}"); return; } // +----------------------+ // | Pagination | // +----------------------+ if (HasRequestedPagination) { int entriesPerPage = Settings.PlaysoundsSoundsPerPage; int maxPage = (int)Math.Ceiling((double)Settings.PlaysoundsSavedSounds.Count / entriesPerPage); if (RequestedPage < 1 || RequestedPage > maxPage) { messageCallback.Invoke($"The page '{RequestedPage}' is not in the valid range of [1 to {maxPage}]!"); return; } int pageIndex = (int)RequestedPage - 1; int skipValues = pageIndex * entriesPerPage; List <Playsound> thisPage = Settings.PlaysoundsSavedSounds.OrderBy(ps => ps.BasePrice).ThenBy(ps => ps.Name).Skip(skipValues).Take(entriesPerPage).ToList(); string toPrint = ""; foreach (Playsound listSound in thisPage) { toPrint += $"\n'{listSound.Name}'\t({listSound.BasePrice} {Settings.EcoPointUnitName})"; } toPrint += $"\n\t\t\t{ColorCoder.Bold($"-\tPage ({RequestedPage}/{maxPage})\t-")}"; toPrint += $"\n\nTo switch pages write '{Settings.ChatCommandPrefix}{command} <1/2/3/...>'"; messageCallback.Invoke(toPrint); return; } if (evt.TargetMode != TSClient.Enums.MessageMode.Channel) { messageCallback.Invoke(ColorCoder.Error("Playsounds can only be used in channel chats!")); return; } Client myClient = Parent.Client.GetClientById(Parent.MyClientId); if (Parent.Client.IsClientOutputMuted(myClient)) { messageCallback.Invoke(ColorCoder.Error("This doesn't work right now...")); return; } if (Parent.Client.IsClientInputMuted(myClient)) { messageCallback.Invoke(ColorCoder.Error("Host is muted, playsound can still be played but others won't hear it (@Panther)")); } CooldownManager.ThrowIfCooldown(evt.InvokerUniqueId, "command:playsounds"); // +-------------------------+ // | Playback of local files | // +-------------------------+ if (!CheckValidModifiers(ManualModifiers, messageCallback)) { return; } double speed = 1.0, pitch = 1.0, volume = 1.0; if (SelectedModifier != null) { Dictionary <string, double> modifiers = Settings.PlaysoundsModifiers[SelectedModifier]; if (modifiers.ContainsKey(ModifierNameSpeed)) { speed = modifiers[ModifierNameSpeed]; } if (modifiers.ContainsKey(ModifierNamePitch)) { pitch = modifiers[ModifierNamePitch]; } if (modifiers.ContainsKey(ModifierNameVolume)) { volume = modifiers[ModifierNameVolume]; } } if (ManualModifiers != null) { if (ManualModifiers.ContainsKey(ModifierNameSpeed)) { speed = ManualModifiers[ModifierNameSpeed]; } if (ManualModifiers.ContainsKey(ModifierNamePitch)) { pitch = ManualModifiers[ModifierNamePitch]; } if (ManualModifiers.ContainsKey(ModifierNameVolume)) { volume = ManualModifiers[ModifierNameVolume]; } } Dictionary <string, double> actualModifiers = new Dictionary <string, double>() { [ModifierNameSpeed] = speed, [ModifierNamePitch] = pitch, [ModifierNameVolume] = volume, }; double priceFactor = GetPriceFactorForModifiers(actualModifiers); int basePrice; string filePath; double baseDuration; string playingSoundStr; if (SourceIsYoutube) { // +----------------------+ // | Youtube fetching | // +----------------------+ if (SoundSource.ToLower().StartsWith("[url]")) { SoundSource = Utils.RemoveTag(SoundSource, "url"); } string title = ""; string youtubeUrl = AudioHelper.IsYouTubeVideoUrl(SoundSource); if (youtubeUrl != null) { lock (YoutubeDownloadLock) { if (IsLoadingYoutubeAudio) { string loadingStr = LoadingPercentDone == -1 ? "download not yet started" : $"{LoadingPercentDone:0.##}%"; messageCallback.Invoke(ColorCoder.ErrorBright($"Chill, I'm still loading another clip... ({loadingStr})")); return; } IsLoadingYoutubeAudio = true; } string videoId = youtubeUrl.Substring(youtubeUrl.IndexOf($"v=") + 2, 11); try { (filePath, title) = AudioHelper.LoadYoutubeVideo(videoId, (int)YoutubeStartTime, (int)(YoutubeEndTime - YoutubeStartTime) + 1, new ProgressSaver()); Parent.UpdateYoutubeFolderSize(); } catch (ArgumentException ex) { messageCallback.Invoke(ColorCoder.ErrorBright($"Error with youtube video: {ex.Message}")); lock (YoutubeDownloadLock) { IsLoadingYoutubeAudio = false; LoadingPercentDone = -1; } return; } lock (YoutubeDownloadLock) { IsLoadingYoutubeAudio = false; LoadingPercentDone = -1; } } else { messageCallback.Invoke(ColorCoder.ErrorBright($"The URL is not a youtube link...")); return; } baseDuration = AudioHelper.GetAudioDurationInSeconds(filePath); if (double.IsNaN(baseDuration)) { messageCallback.Invoke(ColorCoder.ErrorBright($"Couldn't get audio duration from file '{filePath}'")); return; } basePrice = CalculateYoutubePlaysoundCost(baseDuration); if (baseDuration <= 60 && Settings.PlaysoundsYoutubeOnePointEvent) { basePrice = 1; } playingSoundStr = ColorCoder.SuccessDim($" Playing YouTube clip {ColorCoder.Bold($"'{title}'")} [{TimeSpan.FromSeconds((int)baseDuration)}]."); } else { Playsound sound; if (SoundSource == "random") { Random r = new Random(); sound = Settings.PlaysoundsSavedSounds.FindAll(ps => Math.Ceiling(ps.BasePrice * priceFactor) <= EconomyManager.GetBalanceForUser(evt.InvokerUniqueId)).OrderBy(ps => r.Next()).First(); } else { List <Playsound> sounds = Settings.PlaysoundsSavedSounds.FindAll(ps => ps.Name.ToLower().Contains(SoundSource.ToLower())); //Fix for matching the exact sound name Playsound exactSound = Settings.PlaysoundsSavedSounds.Find(ps => ps.Name == SoundSource); if (exactSound != null) { sounds.Clear(); sounds.Add(exactSound); } if (sounds.Count == 0) { messageCallback.Invoke(ColorCoder.Error($"A playsound with the name {ColorCoder.Bold($"'{SoundSource}'")} wasn't found!")); return; } else if (sounds.Count > 1) { string soundsJoined = string.Join(", ", sounds.Select(ps => ColorCoder.Bold($"'{ps.Name}'"))); messageCallback.Invoke(ColorCoder.Error($"Multiple sounds with {ColorCoder.Bold($"'{SoundSource}'")} in their name were found: ({soundsJoined})")); return; } else { sound = sounds[0]; } } basePrice = sound.BasePrice; filePath = Utils.GetProjectFilePath($"{SoundsFolder}\\{sound.FileName}"); baseDuration = AudioHelper.GetAudioDurationInSeconds(filePath); playingSoundStr = ColorCoder.SuccessDim($" Playing sound {ColorCoder.Bold($"'{sound.Name}'")}."); } int modifiedPrice = Math.Max(1, (int)Math.Round(basePrice * priceFactor)); double modifiedDuration = baseDuration / speed; int balanceAfter = EconomyManager.GetUserBalanceAfterPaying(evt.InvokerUniqueId, modifiedPrice); if (balanceAfter < 0) { messageCallback.Invoke(ColorCoder.Error($"You dont have enough cash for that sound, {ColorCoder.Username(evt.InvokerName)}. Price: {ColorCoder.Currency(modifiedPrice, Settings.EcoPointUnitName)}, Needed: {ColorCoder.Currency(-balanceAfter, Settings.EcoPointUnitName)}")); return; } CooldownManager.SetCooldown(evt.InvokerUniqueId, "command:playsounds", CalculateCooldown(modifiedDuration)); EconomyManager.ChangeBalanceForUser(evt.InvokerUniqueId, -modifiedPrice); string usernameStr = ColorCoder.Username(evt.InvokerName); string priceAdditionStr = priceFactor == 1 ? "" : $" x{priceFactor:0.##} = -{modifiedPrice}"; string balanceStr = $"Your balance: {EconomyManager.GetBalanceForUser(evt.InvokerUniqueId)} {Settings.EcoPointUnitName} {ColorCoder.ErrorBright($"(-{basePrice}{priceAdditionStr})")}"; messageCallback.Invoke($"{usernameStr} {playingSoundStr} {balanceStr}"); Process audioProcess = AudioHelper.PlayAudio(filePath, volume, speed, pitch, audioDevice: Settings.PlaysoundsSoundDevice); AllStartedSoundProcesses.Add(audioProcess); }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { Client target = null; if (TargetName != null) { target = Parent.Client.GetClientByNamePart(TargetName); } if (target == null) { target = Parent.Client.GetClientById(evt.InvokerId); } if (IsSendingBalance) { if (SendParam == "all") { SendAmount = (uint)Math.Max(0, EconomyManager.GetBalanceForUser(evt.InvokerUniqueId)); } else if (SendParam == "excess") { int tempB = EconomyManager.GetBalanceForUser(evt.InvokerUniqueId); if (tempB > Settings.EcoSoftBalanceLimit) { SendAmount = (uint)(tempB - Settings.EcoSoftBalanceLimit); } else { SendAmount = 0; } } if (SendAmount == 0) { messageCallback.Invoke(ColorCoder.ErrorBright($"Why would you want to send {ColorCoder.Currency(0)}? What are you, stupid {ColorCoder.Username(evt.InvokerName)}")); return; } else if (EconomyManager.GetUserBalanceAfterPaying(evt.InvokerUniqueId, (int)SendAmount) < 0) { messageCallback.Invoke(ColorCoder.ErrorBright($"You can't afford to send that much cash, {ColorCoder.Username(evt.InvokerName)}")); return; } else if (EconomyManager.GetUserBalanceAfterPaying(target.UniqueId, -1 * (int)SendAmount) > Settings.EcoSoftBalanceLimit) { messageCallback.Invoke(ColorCoder.ErrorBright($"You can't send that much cash because {ColorCoder.Username(target.Nickname)} would have more than '{ColorCoder.Currency(Settings.EcoSoftBalanceLimit)}'")); return; } EconomyManager.ChangeBalanceForUser(evt.InvokerUniqueId, (-1) * (int)SendAmount); EconomyManager.ChangeBalanceForUser(target.UniqueId, (int)SendAmount); messageCallback.Invoke(ColorCoder.SuccessDim($"Sent '{ColorCoder.Currency(SendAmount)}' to {ColorCoder.Username(target.Nickname)}")); } else if (command == "setbalance") { int setAmount = SetAmount; if (SetAmountIsRelative) { setAmount += EconomyManager.GetBalanceForUser(target.UniqueId); } EconomyManager.SetBalanceForUser(target.UniqueId, setAmount); int setTo = EconomyManager.GetBalanceForUser(target.UniqueId); messageCallback.Invoke(ColorCoder.Success($"Set balance for {ColorCoder.Username(target.Nickname)} to {ColorCoder.Bold($"{setTo} {Settings.EcoPointUnitName}")}")); } else { int max = Settings.EcoSoftBalanceLimit; int balance = EconomyManager.GetBalanceForUser(target.UniqueId); messageCallback.Invoke($"Balance of {ColorCoder.Username(target.Nickname)}: {ColorCoder.Bold(balance.ToString())} / {ColorCoder.Bold($"{max} {Settings.EcoPointUnitName}")}"); } }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { if (command != CommandPrefix) { if (!Settings.DynamicCommands.ContainsKey(command.ToLower())) { messageCallback.Invoke(ColorCoder.ErrorBright($"The command {command} was not found in the dynamic commands list (should never happen)")); } string parametersJoined = string.Join(" ", parameters); string toPrint = Settings.DynamicCommands[command.ToLower()]; toPrint = toPrint.Replace("{params}", parametersJoined); messageCallback.Invoke(toPrint); return; } string action = parameters[0]; string commandName = ""; string commandText = ""; if (action == "add") { commandName = parameters[1]; commandText = string.Join(" ", parameters.Skip(2)); } else if (action == "remove") { commandName = parameters[1]; } commandName = commandName.ToLower(); if (action == "add") { if (Settings.DynamicCommands.ContainsKey(commandName)) { messageCallback.Invoke(ColorCoder.ErrorBright($"The command {ColorCoder.Bold($"'{commandName}'")} already exists.")); return; } Settings.DynamicCommands.Add(commandName, commandText); messageCallback.Invoke(ColorCoder.Success($"Added command {ColorCoder.Bold($"'{commandName}'")}.")); Settings.DelayedSave(); } else if (action == "remove") { if (!Settings.DynamicCommands.ContainsKey(commandName)) { messageCallback.Invoke(ColorCoder.ErrorBright($"The command {ColorCoder.Bold($"'{commandName}'")} does not exists.")); return; } Settings.DynamicCommands.Remove(commandName); messageCallback.Invoke(ColorCoder.Success($"Removed command {ColorCoder.Bold($"'{commandName}'")}.")); Settings.DelayedSave(); } else if (action == "list") { if (Settings.DynamicCommands.Count == 0) { messageCallback.Invoke($"The dynamic commands list is currently empty."); return; } string toPrint = $"These are all registered commands ({Settings.DynamicCommands.Count}):"; foreach (string dynCommand in Settings.DynamicCommands.Keys.OrderBy(s => s)) { string dynCommandText = Settings.DynamicCommands[dynCommand]; toPrint += $"\n\t{ColorCoder.Bold($"'{dynCommand}'")}: {dynCommandText}"; } messageCallback.Invoke(toPrint); } }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { if (Action == "status") { if (TimerInfos.ContainsKey(evt.InvokerUniqueId)) { (Timer targetTimer, DateTime timeDue, string targetCommand, List <string> targetParameters) = TimerInfos[evt.InvokerUniqueId]; TimeSpan timeLeft = timeDue - DateTime.Now; timeLeft = TimeSpan.FromSeconds((int)timeLeft.TotalSeconds); messageCallback.Invoke($"{ColorCoder.Username(evt.InvokerName)}: Time left for {FormatCommandString(command, parameters)}: [{timeLeft}]"); } else { messageCallback.Invoke(ColorCoder.ErrorBright($"You don't have an active timed command, {ColorCoder.Username(evt.InvokerName)}")); } return; } else if (Action == "cancel") { if (TimerInfos.ContainsKey(evt.InvokerUniqueId)) { (Timer targetTimer, DateTime timeDue, string targetCommand, List <string> targetParameters) = TimerInfos[evt.InvokerUniqueId]; targetTimer.Dispose(); TimerInfos.Remove(evt.InvokerUniqueId); messageCallback.Invoke($"{ColorCoder.Username(evt.InvokerName)}: Your timer for {FormatCommandString(command, parameters)} was cancelled!"); } else { messageCallback.Invoke(ColorCoder.ErrorBright($"You don't have an active timed command, {ColorCoder.Username(evt.InvokerName)}")); } return; } if (TimerInfos.ContainsKey(evt.InvokerUniqueId)) { messageCallback.Invoke(ColorCoder.ErrorBright($"You already have an active timed command, {ColorCoder.Username(evt.InvokerName)}")); return; } TimeDelta = TimeDelta.Duration(); ChatCommand commandToExecute; try { commandToExecute = Parent.CommandHandler.GetCommandForMessage(TargetCommand, TargetParameters.AsEnumerable().ToList(), evt.InvokerUniqueId); } catch (Exception) { messageCallback.Invoke(ColorCoder.ErrorBright($"Could not parse the desired command. Make sure you have access to the command and the syntax is valid!")); return; } Timer timer = new Timer(new TimerCallback((state) => { HandleDelayedCommand(evt.InvokerUniqueId, TargetCommand, TargetParameters, messageCallback); }), null, TimeDelta, TimeSpan.FromMilliseconds(-1)); TimerInfos.Add(evt.InvokerUniqueId, Tuple.Create(timer, DateTime.Now + TimeDelta, TargetCommand, TargetParameters)); messageCallback.Invoke(ColorCoder.SuccessDim($"Invoking command {FormatCommandString(TargetCommand, TargetParameters)} in [{ColorCoder.Bold(TimeDelta)}], {ColorCoder.Username(evt.InvokerName)}")); }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { lock (LockObject) { if (IsBusy) { messageCallback.Invoke(ColorCoder.ErrorBright("The fetcher is busy, try again when the current request has completed...")); return; } IsBusy = true; } Elos = Parent.EloSettings; if (Elos.LastUpdated + Elos.UpdateFrequency < DateTime.Now) { messageCallback.Invoke($"Leaderboards were outdated (older than 1 month), started refreshing cache. This could take a few minutes..."); Parent.LogMessage("[*] Starting fetch AoE2DE leaderboards..."); foreach (string mode in LeaderboardIds.Keys) { FetchClientList(mode, messageCallback); Parent.LogMessage($"[*] {mode} done"); } Parent.LogMessage("[*] AoE2DE leaderboards fetch done"); //Implicitly saves the elos to the hard drive Elos.LastUpdated = DateTime.Now; } //HttpClient client = new HttpClient(); SelectedLeaderboard = SelectedLeaderboard ?? ModeTgName; int fromElo, toElo; if (!string.IsNullOrEmpty(SelectedLevel)) { (fromElo, toElo) = EloRanges[SelectedLeaderboard][SelectedLevel]; if (fromElo == -1) { fromElo = Elos.AllPlayersElos[SelectedLeaderboard].Last().Item1; } if (toElo == -1) { toElo = Elos.AllPlayersElos[SelectedLeaderboard].First().Item1; } } else if (InputFromElo != uint.MaxValue) { if (InputFromElo > InputToElo) { uint tempElo = InputFromElo; InputFromElo = InputToElo; InputToElo = tempElo; } fromElo = Math.Max((int)InputFromElo, Elos.AllPlayersElos[SelectedLeaderboard].Last().Item1); toElo = Math.Min((int)InputToElo, Elos.AllPlayersElos[SelectedLeaderboard].First().Item1); } else { fromElo = EloRanges[SelectedLeaderboard]["lel"].Item1; toElo = EloRanges[SelectedLeaderboard]["good"].Item2; } Random r = new Random(); int offset = r.Next(1, 10); int lowerRankIndex = int.MaxValue, upperRankIndex = int.MinValue; //indices inclusive bounds List <Tuple <int, string> > leaderboard = Elos.AllPlayersElos[SelectedLeaderboard]; for (int i = 0; i < leaderboard.Count; i++) { Tuple <int, string> position = leaderboard[i]; if (upperRankIndex == int.MinValue && position.Item1 <= toElo) { upperRankIndex = i; } if (lowerRankIndex == int.MaxValue && position.Item1 < fromElo) { lowerRankIndex = i - 1; } } bool hasFoundMatch = false; string downloadLink = ""; while (!hasFoundMatch) { int selectedIndex = r.Next(upperRankIndex, lowerRankIndex + 1); string steamId = Elos.AllPlayersElos[SelectedLeaderboard][selectedIndex].Item2; string fetchUrl = $"https://aoe2.net/api/player/matches?game=aoe2de&steam_id={steamId}&count=10&start=1"; HttpClient client = new HttpClient(); HttpResponseMessage response = client.GetAsync(fetchUrl).Result; string content = response.Content.ReadAsStringAsync().Result; JArray matches = JArray.Parse(content); JObject foundMatch = null; foreach (JToken matchToken in matches.Children()) { JObject match = (JObject)matchToken; bool isRanked = match.GetValue("ranked").ToObject <bool>(); int playerCount = match.GetValue("num_players").ToObject <int>(); if (!isRanked) { Parent.LogMessage("Game was not ranked, skipping..."); continue; } if ((SelectedLeaderboard == Mode1v1Name && playerCount == 2) || (SelectedLeaderboard == ModeTgName && playerCount > 2)) { foundMatch = match; } else { Parent.LogMessage($"Game was not of leaderboard '{SelectedLeaderboard}', skipping..."); } } if (foundMatch == null) { Parent.LogMessage($"Randomly selected player did not play a ranked '{SelectedLeaderboard}' game in the last 10 games"); continue; } string matchId = foundMatch.GetValue("match_id").ToObject <string>(); JArray players = foundMatch.GetValue("players").ToObject <JArray>(); JObject firstPlayer = (JObject)players[0]; long profileId = firstPlayer.GetValue("profile_id").ToObject <long>(); downloadLink = $"https://aoe.ms/replay/?gameId={matchId}&profileId={profileId}"; hasFoundMatch = true; } messageCallback.Invoke($"Here is your {ColorCoder.Bold(SelectedLeaderboard.ToUpper())} replay of elo range ({fromElo}-{toElo}): [url={downloadLink}]Download[/url]"); lock (LockObject) { IsBusy = false; } }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { messageCallback.Invoke(ColorCoder.ErrorBright("Plugin instance was killed!")); Messenger.Default.Send(new StopApplicationMessage()); }
public static void HandleLastMatchRequest(string nameSearch, int leaderboardId, Action <string> messageCallback) { AoeLeaderboardResponse response = GetLeaderboardResponse(leaderboardId, nameSearch, 2); AoePlayer player; if (response.Count == 0) { messageCallback.Invoke($"There were no players found on leaderboard '{leaderboardId}' with the name '{nameSearch}'"); return; } else if (response.Count > 1) { messageCallback.Invoke($"There were multiple players found on leaderboard '{leaderboardId}' with the name '{nameSearch}', taking the highest rated player..."); player = response.Leaderboard[0]; } else { player = response.Leaderboard[0]; } AoeLastMatchResponse lastMatchResponse = GetLastMatchResponse(player.SteamId); Match lastMatch = lastMatchResponse.LastMatch; Dictionary <int, List <List <AoePlayer> > > matchTeams = new Dictionary <int, List <List <AoePlayer> > >(); foreach (AoePlayer matchPlayer in lastMatch.Players) { if (!matchTeams.ContainsKey(matchPlayer.Team.Value)) { matchTeams.Add(matchPlayer.Team.Value, new List <List <AoePlayer> >()); } List <List <AoePlayer> > team = matchTeams[matchPlayer.Team.Value]; List <AoePlayer> playerInfo = new List <AoePlayer>(); playerInfo.Add(matchPlayer); if (matchPlayer.SteamId != player.SteamId) { AoeLeaderboardResponse lb = GetLeaderboardResponse(leaderboardId, matchPlayer.ProfileId.Value.ToString(), 2, isProfileId: true); if (lb.Leaderboard.Count == 0) { playerInfo.Add(null); } else { playerInfo.Add(lb.Leaderboard[0]); } } else { playerInfo.Add(player); } team.Add(playerInfo); } string toPrint = ""; toPrint += lastMatch.Finished.HasValue ? "Last Match (" + (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(lastMatch.Finished.Value).ToLocalTime()).ToString("dd.MM.yy HH:mm") + "):" : "Current Match:"; toPrint += lastMatch.Ranked.HasValue && lastMatch.Ranked.Value ? " Ranked" : " Unranked"; string mapName = GetAoeString("map_type", lastMatch.MapType.Value); toPrint += $" on {mapName}"; bool firstTeam = true; foreach (int teamPos in matchTeams.Keys) { List <List <AoePlayer> > team = matchTeams[teamPos]; string winStatusString; if (!team[0][0].Won.HasValue) { winStatusString = "◯"; } else if (team[0][0].Won.Value) { winStatusString = "👑"; } else { winStatusString = "☠"; } if (firstTeam) { firstTeam = false; } else { toPrint += "\n\t\tvs."; } foreach (List <AoePlayer> playerInfo in team) { string playerName = playerInfo[0].Name; string civ = GetAoeString("civ", playerInfo[0].Civ.Value); if (playerName.ToLower().Contains(nameSearch.ToLower())) { playerName = ColorCoder.Bold(playerName); } if (playerInfo[1] == null) //Player is not yet ranked in this leaderboard { string line = $"\n{winStatusString} [--] {playerName} (<placements>) on {civ}"; toPrint += line; } else { string country = playerInfo[1].Country; string rating = playerInfo[1].Rating.HasValue ? $"{playerInfo[1].Rating.Value}" : "<placement>"; int games = playerInfo[1].Games.Value; int wins = playerInfo[1].Wins.Value; double ratioPercent = Math.Round((double)wins * 100 / games); string ratioPercentStr = $"{ratioPercent}%"; ratioPercentStr = ratioPercent < 50 ? ColorCoder.ErrorBright(ratioPercentStr) : ratioPercent > 50 ? ColorCoder.SuccessDim(ratioPercentStr) : $"{ratioPercentStr}"; string line = $"\n{winStatusString} [{country}] {playerName} ({rating}, {games} G, {ratioPercentStr}) on {civ}"; toPrint += line; } } } messageCallback.Invoke(toPrint); }
public override void HandleCommand(NotifyTextMessageEvent evt, string command, List <string> parameters, Action <string> messageCallback) { int amountToGamble = 0; StatisticSettings stats = Parent.StatSettings; if (RequestedStats) { RouletteStatistics displayStats; string toPrint; if (RequestedStatsName != null && RequestedStatsName == "all") { displayStats = stats.Roulette; toPrint = "Global roulette stats:"; } else { string userUid = evt.InvokerUniqueId; string userName = evt.InvokerName; if (RequestedStatsName != null) { Client user = Parent.Client.GetClientByNamePart(RequestedStatsName); userUid = user.UniqueId; userName = user.Nickname; } CheckHasStatisticsEntry(userUid); displayStats = stats.RouletteIndividual[userUid]; toPrint = $"Roulette stats for {ColorCoder.Username(userName)}:"; } int won = displayStats.GamesWon; int lost = displayStats.GamesLost; double ratioPercent = (double)won * 100 / (lost + won); string ratioPercentStr; if (double.IsNaN(ratioPercent)) { ratioPercentStr = "-%"; } else { ratioPercentStr = ColorCoder.ColorPivotPercent(ratioPercent, 50); } toPrint += $"\n\tGames: {won + lost} ({ColorCoder.SuccessDim($"{won}W")}, {ColorCoder.ErrorBright($"{lost}L")} | {ratioPercentStr})"; int balanceWon = displayStats.PointsWon; int balanceLost = displayStats.PointsLost; int balanceDiff = balanceWon - balanceLost; string balanceDiffStr = ColorCoder.ColorPivot(balanceDiff, 0); toPrint += $"\n\tPoints: {balanceDiffStr} ({ColorCoder.SuccessDim($"+{balanceWon} won")}, {ColorCoder.ErrorBright($"-{balanceLost} lost")})"; int jackpots = displayStats.Jackpots; int jackpotPoints = displayStats.JackpotsPointsWon; toPrint += $"\n\tJackpots: {jackpots} ({ColorCoder.SuccessDim($"+{jackpotPoints} bonus")})"; double rolls = displayStats.Rolls; string rollsStr = (won + lost) == 0 ? "-" : $"{rolls / (won + lost):0.####}"; toPrint += $"\n\tAvg. Roll: {rollsStr}"; messageCallback.Invoke(toPrint); return; } if (!Settings.RouletteEnabled) { messageCallback.Invoke(ColorCoder.ErrorBright($"The casino is currently closed, sorry {ColorCoder.Username(evt.InvokerName)}!")); return; } CooldownManager.ThrowIfCooldown(evt.InvokerUniqueId, "command:roulette"); int currentBalance = EconomyManager.GetBalanceForUser(evt.InvokerUniqueId); if (currentBalance > Settings.EcoSoftBalanceLimit) { messageCallback.Invoke(ColorCoder.ErrorBright($"You can't gamble while being over {ColorCoder.Bold($"{Settings.EcoSoftBalanceLimit} {Settings.EcoPointUnitName}")}, {ColorCoder.Username(evt.InvokerName)}")); return; } if (IsAll) { amountToGamble = EconomyManager.GetBalanceForUser(evt.InvokerUniqueId); } else if (IsPercent) { if (Amount > 100) { messageCallback.Invoke(ColorCoder.ErrorBright($"You can't gamble away more than you own, {ColorCoder.Username(evt.InvokerName)}")); return; } amountToGamble = EconomyManager.GetBalanceForUser(evt.InvokerUniqueId); amountToGamble = (int)Math.Ceiling(amountToGamble * ((double)Amount / 100)); } else { int balanceAfterPay = EconomyManager.GetUserBalanceAfterPaying(evt.InvokerUniqueId, (int)Amount); if (balanceAfterPay < 0) { messageCallback.Invoke(ColorCoder.ErrorBright($"You don't have enough to gamble away '{ColorCoder.Bold($"{Amount} {Settings.EcoPointUnitName}")}', {ColorCoder.Username(evt.InvokerName)}")); return; } amountToGamble = (int)Amount; } if (amountToGamble <= 0) { messageCallback.Invoke(ColorCoder.ErrorBright($"You don't have any cash on you, get out of my casino!")); return; } CooldownManager.SetCooldown(evt.InvokerUniqueId, "command:roulette", Settings.RouletteCooldown); double winChancePercent = Settings.RouletteWinChancePercent; double jackpotChancePercent = Settings.RouletteJackpotChancePercent; if (amountToGamble == Settings.EcoSoftBalanceLimit) { winChancePercent += 1; } winChancePercent /= 100; jackpotChancePercent /= 100; Random r = new Random(); double chosenValue = r.NextDouble(); string resultLogMsg = $"({chosenValue:0.#####} | win {winChancePercent:0.#####} | jackpot {jackpotChancePercent:0.#####})"; Parent.LastRouletteResult = resultLogMsg; Parent.LogMessage($"Roulette result: {resultLogMsg}"); int changeBalanceAmount; string message; string ptsUnit = Settings.EcoPointUnitName; CheckHasStatisticsEntry(evt.InvokerUniqueId); RouletteStatistics indivStats = stats.RouletteIndividual[evt.InvokerUniqueId]; RouletteStatistics allStats = stats.Roulette; allStats.Rolls += chosenValue; indivStats.Rolls += chosenValue; if (chosenValue < winChancePercent) //User won the roulette { double yield = Settings.RouletteWinYieldMultiplier; changeBalanceAmount = (int)Math.Floor(amountToGamble * (yield - 1)); if (chosenValue < jackpotChancePercent) { allStats.Jackpots++; int jackpotPoints = (int)(changeBalanceAmount * Settings.RouletteJackpotMultiplier); allStats.JackpotsPointsWon += jackpotPoints - changeBalanceAmount; indivStats.JackpotsPointsWon += jackpotPoints - changeBalanceAmount; changeBalanceAmount = jackpotPoints; messageCallback.Invoke(ColorCoder.Success($"\t-\t JACKPOT! Your reward has just been tripled!\t-\t")); } allStats.GamesWon++; indivStats.GamesWon++; allStats.PointsWon += changeBalanceAmount; indivStats.PointsWon += changeBalanceAmount; message = ColorCoder.ColorText(Color.DarkGreen, ColorCoder.Username(evt.InvokerName) + $" won {ColorCoder.Bold(changeBalanceAmount.ToString())} {ptsUnit} in roulette and now has {ColorCoder.Bold((currentBalance + changeBalanceAmount).ToString())} {ptsUnit} forsenPls ({chosenValue:0.####})"); } else { changeBalanceAmount = -amountToGamble; allStats.GamesLost++; indivStats.GamesLost++; allStats.PointsLost += amountToGamble; indivStats.PointsLost += amountToGamble; message = ColorCoder.ErrorBright(ColorCoder.Username(evt.InvokerName) + $" lost {ColorCoder.Bold(amountToGamble.ToString())} {ptsUnit} in roulette and now has {ColorCoder.Bold((currentBalance + changeBalanceAmount).ToString())} {ptsUnit} FeelsBadMan ({chosenValue:0.####})"); } stats.DelayedSave(); EconomyManager.ChangeBalanceForUser(evt.InvokerUniqueId, changeBalanceAmount); messageCallback.Invoke(message); }
public bool HandleTextMessage(NotifyTextMessageEvent evt, Action <string> messageCallback) { if (!Settings.ChatCommandsEnabled || string.IsNullOrEmpty(evt.Message) || !evt.Message.StartsWith(Settings.ChatCommandPrefix)) { return(false); } Parent.LogMessage($"{evt.InvokerName} requested command: \"{evt.Message}\""); //Copy event as to not mess up other event handlers NotifyTextMessageEvent tempEvt = new NotifyTextMessageEvent(); evt.CopyProperties(tempEvt); evt = tempEvt; evt.Message = evt.Message.Substring(Settings.ChatCommandPrefix.Length); bool hasAdmin = Settings.AdminUniqueIds.Contains(evt.InvokerUniqueId); if (Parent.RateLimiter.CheckRateLimit("chat_command", evt.InvokerUniqueId, hasAdmin) == false) { messageCallback.Invoke(ColorCoder.ErrorBright("Slow down a little, you are sending too many commands!")); return(true); } string[] messageSplit = evt.Message.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); string command = messageSplit[0].ToLower(); List <string> parameters = messageSplit.Skip(1).ToList(); parameters = ParseParameterEscapes(parameters); ChatCommand commandToExecute = null; //Handle exceptions that occur during the parsing of the parameters try { commandToExecute = GetCommandForMessage(command, parameters, evt.InvokerUniqueId); } catch (ChatCommandNotFoundException) { messageCallback.Invoke(ColorCoder.ErrorBright("Command was not found")); return(true); } catch (ChatCommandInvalidSyntaxException ex) { messageCallback.Invoke(ColorCoder.ErrorBright($"Invalid syntax. Usage of command:\n{Settings.ChatCommandPrefix}{ex.Message}")); return(true); } catch (NoPermissionException) { messageCallback.Invoke(ColorCoder.ErrorBright($"You don't have access to this command, {ColorCoder.Username(evt.InvokerName)}")); return(true); } catch (CommandParameterInvalidFormatException ex) { messageCallback.Invoke(ColorCoder.ErrorBright($"The {ex.GetParameterPosition()} parameter's format was invalid ({ex.ParameterName} = '{ex.ParameterValue}'). It has to be {ColorCoder.Bold(ex.GetNeededType())}!\nUsage: {Settings.ChatCommandPrefix}{ex.UsageHelp}")); return(true); } catch (TimeStringParseException ex) { messageCallback.Invoke(ColorCoder.ErrorBright($"The provided time value '{ex.Input}' had invalid syntax: {ex.Message}")); return(true); } //Handle exceptions that occur during execution of the command try { commandToExecute.HandleCommand(evt, command, parameters, messageCallback); } catch (MultipleTargetsFoundException ex) { string joined = string.Join(", ", ex.AllFoundTargets.Select(client => ColorCoder.Bold($"'{client.Nickname}'"))); messageCallback.Invoke(ColorCoder.ErrorBright($"Too many targets were found with {ColorCoder.Bold($"'{ex.Message}'")} in their name ({joined})")); } catch (CooldownNotExpiredException ex) { messageCallback.Invoke(ColorCoder.ErrorBright($"That command is still on cooldown. ({ColorCoder.Bold($"{CooldownManager.FormatCooldownTime(ex.Duration)}")} cooldown)")); } catch (NoTargetsFoundException ex) { messageCallback.Invoke(ColorCoder.ErrorBright($"No targets were found with {ColorCoder.Bold($"'{ex.Message}'")} in their name...")); } catch (Exception ex) { Parent.LogMessage($"Encountered exception in command '{commandToExecute.GetType().Name}': {ex}"); } return(true); }