From e5222d0f0c8f30f55e91b10299659f0c1a59cb36 Mon Sep 17 00:00:00 2001 From: versx Date: Sat, 26 Jun 2021 19:23:31 -0700 Subject: [PATCH] Add support for grouped multiple invasion reward subscription. (#167) --- migrations/11.sql | 2 + src/Commands/Notifications.cs | 202 +++++++++--------- .../Models/InvasionSubscription.cs | 11 +- src/Data/Subscriptions/SubscriptionManager.cs | 7 +- .../Subscriptions/SubscriptionProcessor.cs | 2 +- src/Extensions/GenericsExtensions.cs | 20 ++ 6 files changed, 134 insertions(+), 110 deletions(-) create mode 100644 migrations/11.sql diff --git a/migrations/11.sql b/migrations/11.sql new file mode 100644 index 00000000..c5b85d46 --- /dev/null +++ b/migrations/11.sql @@ -0,0 +1,2 @@ +ALTER TABLE `invasions` +MODIFY COLUMN `reward_pokemon_id` text DEFAULT NULL; \ No newline at end of file diff --git a/src/Commands/Notifications.cs b/src/Commands/Notifications.cs index 71c264a0..09e915bd 100644 --- a/src/Commands/Notifications.cs +++ b/src/Commands/Notifications.cs @@ -1072,42 +1072,40 @@ public async Task InvMeAsync(CommandContext ctx, return; } - foreach (var (pokemonId, form) in validation.Valid) + var valid = string.Join(",", validation.Valid.Keys.ToList()); + var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonIdString == valid); + if (subInvasion != null) { - var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonId == pokemonId); - if (subInvasion != null) + // Existing invasion subscription + // Loop all areas, check if the area is already in subs, if not add it + foreach (var area in areas) { - // Existing invasion subscription - // Loop all areas, check if the area is already in subs, if not add it - foreach (var area in areas) + if (!subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) { - if (!subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) - { - subInvasion.Areas.Add(area); - } + subInvasion.Areas.Add(area); } - // Save quest subscription and continue; - // REVIEW: Might not be needed - subInvasion.Save(); } - else + // Save quest subscription and continue; + // REVIEW: Might not be needed + subInvasion.Save(); + } + else + { + // New invasion subscription + subscription.Invasions.Add(new InvasionSubscription { - // New invasion subscription - subscription.Invasions.Add(new InvasionSubscription - { - GuildId = guildId, - UserId = ctx.User.Id, - RewardPokemonId = pokemonId, - Areas = areas - }); - } + GuildId = guildId, + UserId = ctx.User.Id, + RewardPokemonIdString = valid, + Areas = areas + }); } subscription.Save(); - var valid = validation.Valid.Keys.Select(x => MasterFile.GetPokemon(x, 0).Name); + var validPokemonNames = validation.Valid.Keys.Select(x => MasterFile.GetPokemon(x, 0).Name); await ctx.RespondEmbed(Translator.Instance.Translate("SUCCESS_INVASION_SUBSCRIPTIONS_SUBSCRIBE").FormatText( ctx.User.Username, - string.Compare(poke, Strings.All, true) == 0 ? Strings.All : string.Join(", ", valid), + string.Compare(poke, Strings.All, true) == 0 ? Strings.All : string.Join(", ", validPokemonNames), string.IsNullOrEmpty(city) ? Translator.Instance.Translate("SUBSCRIPTIONS_FROM_ALL_CITIES") : Translator.Instance.Translate("SUBSCRIPTIONS_FROM_CITY").FormatText(city)) @@ -1161,46 +1159,43 @@ await ctx.RespondEmbed(Translator.Instance.Translate("ERROR_NO_INVASION_SUBSCRIP } var areas = SubscriptionAreas.GetAreas(_dep.WhConfig.Servers[guildId], city); - foreach (var item in validation.Valid) - { - var pokemonId = item.Key; - var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonId == pokemonId); - // Check if subscribed - if (subInvasion == null) - return; + var valid = string.Join(",", validation.Valid.Keys.ToList()); + var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonIdString == valid); + // Check if subscribed + if (subInvasion == null) + return; - foreach (var area in areas) + foreach (var area in areas) + { + if (subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) { - if (subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) - { - var index = subInvasion.Areas.FindIndex(x => string.Compare(x, area, true) == 0); - subInvasion.Areas.RemoveAt(index); - } + var index = subInvasion.Areas.FindIndex(x => string.Compare(x, area, true) == 0); + subInvasion.Areas.RemoveAt(index); } + } - // Check if there are no more areas set for the invasion subscription - //if (subInvasion.Areas.Count == 0) - // If no city specified then remove the whole subscription - if (string.IsNullOrEmpty(city)) - { - // If no more areas set for the invasion subscription, delete it - if (!subInvasion.Id.Remove()) - { - _logger.Error($"Unable to remove invasion subscription for user id {subInvasion.UserId} from guild id {subInvasion.GuildId}"); - } - } - else + // Check if there are no more areas set for the invasion subscription + //if (subInvasion.Areas.Count == 0) + // If no city specified then remove the whole subscription + if (string.IsNullOrEmpty(city)) + { + // If no more areas set for the invasion subscription, delete it + if (!subInvasion.Id.Remove()) { - // Save/update invasion subscription if cities still assigned - subInvasion.Save(); + _logger.Error($"Unable to remove invasion subscription for user id {subInvasion.UserId} from guild id {subInvasion.GuildId}"); } } + else + { + // Save/update invasion subscription if cities still assigned + subInvasion.Save(); + } subscription.Save(); - var valid = validation.Valid.Keys.Select(x => MasterFile.GetPokemon(x, 0).Name); + var validPokemonNames = validation.Valid.Keys.Select(x => MasterFile.GetPokemon(x, 0).Name); await ctx.RespondEmbed(Translator.Instance.Translate("SUCCESS_INVASION_SUBSCRIPTIONS_UNSUBSCRIBE").FormatText( ctx.User.Username, - string.Compare(poke, Strings.All, true) == 0 ? Strings.All : string.Join(", ", valid), + string.Compare(poke, Strings.All, true) == 0 ? Strings.All : string.Join(", ", validPokemonNames), string.IsNullOrEmpty(city) ? Translator.Instance.Translate("SUBSCRIPTIONS_FROM_ALL_CITIES") : Translator.Instance.Translate("SUBSCRIPTIONS_FROM_CITY").FormatText(city)) @@ -1835,36 +1830,34 @@ await ctx.RespondEmbed(Translator.Instance.Translate("SUCCESS_QUEST_SUBSCRIPTION var invasionPokemon = await invasionInput.GetPokemonResult(_dep.WhConfig.MaxPokemonId); var invasionAreas = await invasionInput.GetAreasResult(guildId); + var valid = string.Join(",", invasionPokemon.Valid.ToList()); var validPokemonNames = string.Join(", ", invasionPokemon.Valid.Select(x => MasterFile.Instance.Pokedex[x.Key].Name)); - foreach (var (pokemonId, form) in invasionPokemon.Valid) + var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonIdString == valid); + if (subInvasion != null) { - var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonId == pokemonId); - if (subInvasion != null) + // Existing invasion subscription + // Loop all areas, check if the area is already in subs, if not add it + foreach (var area in invasionAreas) { - // Existing invasion subscription - // Loop all areas, check if the area is already in subs, if not add it - foreach (var area in invasionAreas) + if (!subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) { - if (!subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) - { - subInvasion.Areas.Add(area); - } + subInvasion.Areas.Add(area); } - // Save quest subscription and continue; - // REVIEW: Might not be needed - subInvasion.Save(); } - else + // Save quest subscription and continue; + // REVIEW: Might not be needed + subInvasion.Save(); + } + else + { + // New invasion subscription + subscription.Invasions.Add(new InvasionSubscription { - // New invasion subscription - subscription.Invasions.Add(new InvasionSubscription - { - GuildId = guildId, - UserId = ctx.User.Id, - RewardPokemonId = pokemonId, - Areas = invasionAreas - }); - } + GuildId = guildId, + UserId = ctx.User.Id, + RewardPokemonIdString = valid, + Areas = invasionAreas + }); } var result = subscription.Save(); if (!result) @@ -1872,7 +1865,6 @@ await ctx.RespondEmbed(Translator.Instance.Translate("SUCCESS_QUEST_SUBSCRIPTION } var isAll = string.Compare(Strings.All, validPokemonNames, true) == 0; - var valid = invasionPokemon.Valid.Keys.Select(x => MasterFile.GetPokemon(x, 0).Name); await ctx.RespondEmbed(Translator.Instance.Translate("SUCCESS_INVASION_SUBSCRIPTIONS_SUBSCRIBE").FormatText( ctx.User.Username, isAll ? Strings.All : validPokemonNames, @@ -2289,41 +2281,39 @@ await ctx.RespondEmbed(Translator.Instance.Translate("SUCCESS_QUEST_SUBSCRIPTION var invasionPokemonResult = await invasionInput.GetPokemonResult(_dep.WhConfig.MaxPokemonId); var invasionAreasResult = await invasionInput.GetAreasResult(guildId); - foreach (var item in invasionPokemonResult.Valid) - { - var pokemonId = item.Key; - var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonId == pokemonId); - // Check if subscribed - if (subInvasion == null) - return; + var valid = string.Join(",", invasionPokemonResult.Valid.Keys.ToList()); + var subInvasion = subscription.Invasions.FirstOrDefault(x => x.RewardPokemonIdString == valid); + // Check if subscribed + if (subInvasion == null) + return; - foreach (var area in invasionAreasResult) + foreach (var area in invasionAreasResult) + { + if (subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) { - if (subInvasion.Areas.Select(x => x.ToLower()).Contains(area.ToLower())) - { - var index = subInvasion.Areas.FindIndex(x => string.Compare(x, area, true) == 0); - subInvasion.Areas.RemoveAt(index); - } + var index = subInvasion.Areas.FindIndex(x => string.Compare(x, area, true) == 0); + subInvasion.Areas.RemoveAt(index); } + } - // Check if there are no more areas set for the invasion subscription - if (subInvasion.Areas.Count == 0) - { - // If no more areas set for the invasion subscription, delete it - if (!subInvasion.Id.Remove()) - { - _logger.Error($"Unable to remove invasion subscription for user id {subInvasion.UserId} from guild id {subInvasion.GuildId}"); - } - } - else + // Check if there are no more areas set for the invasion subscription + if (subInvasion.Areas.Count == 0) + { + // If no more areas set for the invasion subscription, delete it + if (!subInvasion.Id.Remove()) { - // Save/update invasion subscription if cities still assigned - subInvasion.Save(); + _logger.Error($"Unable to remove invasion subscription for user id {subInvasion.UserId} from guild id {subInvasion.GuildId}"); } } + else + { + // Save/update invasion subscription if cities still assigned + subInvasion.Save(); + } subscription.Save(); - var validPokemonNames = string.Join("**, **", invasionPokemonResult.Valid.Select(x => MasterFile.Instance.Pokedex[x.Key].Name)); + var validIds = valid.Split(',').Select(x => uint.Parse(x)); + var validPokemonNames = string.Join("**, **", validIds.Select(x => MasterFile.Instance.Pokedex[(int)x].Name)); var isAll = string.Compare(Strings.All, validPokemonNames, true) == 0; await ctx.RespondEmbed(Translator.Instance.Translate("SUCCESS_INVASION_SUBSCRIPTIONS_UNSUBSCRIBE").FormatText( ctx.User.Username, @@ -3113,13 +3103,13 @@ private List GetInvasionSubscriptionNames(ulong guildId, ulong userId) var list = new List(); var subscription = _dep.SubscriptionProcessor.Manager.GetUserSubscriptions(guildId, userId); var subscribedInvasions = subscription.Invasions; - subscribedInvasions.Sort((x, y) => string.Compare(MasterFile.GetPokemon(x.RewardPokemonId, 0).Name, MasterFile.GetPokemon(y.RewardPokemonId, 0).Name, true)); + subscribedInvasions.Sort((x, y) => string.Compare(string.Join(", ", x.RewardPokemonId.Select(a => MasterFile.GetPokemon((int)a, 0).Name)), string.Join(", ", y.RewardPokemonId.Select(b => MasterFile.GetPokemon((int)b, 0).Name)), true)); var cityRoles = _dep.WhConfig.Servers[guildId].Geofences.Select(x => x.Name.ToLower()); foreach (var invasion in subscribedInvasions) { var isAllCities = cityRoles.ScrambledEquals(invasion.Areas, StringComparer.Create(System.Globalization.CultureInfo.CurrentCulture, true)); - list.Add(Translator.Instance.Translate("NOTIFY_FROM").FormatText(MasterFile.GetPokemon(invasion.RewardPokemonId, 0).Name, isAllCities ? Translator.Instance.Translate("ALL_AREAS") : string.Join(", ", invasion.Areas))); + list.Add(Translator.Instance.Translate("NOTIFY_FROM").FormatText(string.Join(", ", invasion.RewardPokemonId.Select(x => MasterFile.GetPokemon((int)x, 0).Name)), isAllCities ? Translator.Instance.Translate("ALL_AREAS") : string.Join(", ", invasion.Areas))); } return list; diff --git a/src/Data/Subscriptions/Models/InvasionSubscription.cs b/src/Data/Subscriptions/Models/InvasionSubscription.cs index 509ee65e..278f75f8 100644 --- a/src/Data/Subscriptions/Models/InvasionSubscription.cs +++ b/src/Data/Subscriptions/Models/InvasionSubscription.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Linq; using InvasionCharacter = POGOProtos.Rpc.EnumWrapper.Types.InvasionCharacter; using Newtonsoft.Json; @@ -31,11 +32,19 @@ public class InvasionSubscription : SubscriptionItem ] public InvasionCharacter InvasionType { get; set; } + [ + JsonIgnore, + Ignore, + ] + public List RewardPokemonId => RewardPokemonIdString?.Split(',')? + .Select(x => uint.Parse(x)) + .ToList(); + [ JsonProperty("reward_pokemon_id"), Alias("reward_pokemon_id"), ] - public uint RewardPokemonId { get; set; } + public string RewardPokemonIdString { get; set; } [ JsonProperty("city"), diff --git a/src/Data/Subscriptions/SubscriptionManager.cs b/src/Data/Subscriptions/SubscriptionManager.cs index f32f0694..4de97978 100644 --- a/src/Data/Subscriptions/SubscriptionManager.cs +++ b/src/Data/Subscriptions/SubscriptionManager.cs @@ -11,6 +11,7 @@ using WhMgr.Configuration; using WhMgr.Data.Subscriptions.Models; using WhMgr.Diagnostics; + using WhMgr.Extensions; using WhMgr.Net.Models; /// @@ -192,8 +193,8 @@ public List GetUserSubscriptionsByInvasion(string pokestopNa return _subscriptions? .Where(x => x.IsEnabled(NotificationStatusType.Invasions) && x.Invasions != null && - x.Invasions.Exists(y => - encounterRewards.Contains(y.RewardPokemonId) || + x.Invasions.Exists(y => + y.RewardPokemonId.Intersects(encounterRewards) || gruntType == y.InvasionType || (y.PokestopName != null && (pokestopName.Contains(y.PokestopName) || string.Equals(pokestopName, y.PokestopName, StringComparison.OrdinalIgnoreCase))) ) @@ -201,6 +202,8 @@ public List GetUserSubscriptionsByInvasion(string pokestopNa .ToList(); } + + /// /// Gets user subscriptions from subscribed Pokestop lures /// diff --git a/src/Data/Subscriptions/SubscriptionProcessor.cs b/src/Data/Subscriptions/SubscriptionProcessor.cs index fdcf7843..011a3c94 100644 --- a/src/Data/Subscriptions/SubscriptionProcessor.cs +++ b/src/Data/Subscriptions/SubscriptionProcessor.cs @@ -752,7 +752,7 @@ GeofenceItem GetGeofence(ulong guildId) continue; } - var subInvasion = user.Invasions.FirstOrDefault(x => encounters.Contains(x.RewardPokemonId)); + var subInvasion = user.Invasions.FirstOrDefault(x => x.RewardPokemonId.Intersects(encounters)); // Not subscribed to invasion if (subInvasion == null) { diff --git a/src/Extensions/GenericsExtensions.cs b/src/Extensions/GenericsExtensions.cs index 96f02cd5..05ed7b32 100644 --- a/src/Extensions/GenericsExtensions.cs +++ b/src/Extensions/GenericsExtensions.cs @@ -119,5 +119,25 @@ public static string ToHumanReadableString(this Type type) return "Boolean"; return type.Name.ToString(); } + + public static bool Intersects(this List list1, List list2) + { + if (list1 is null) + { + throw new ArgumentNullException(nameof(list1)); + } + if (list2 is null) + { + throw new ArgumentNullException(nameof(list2)); + } + foreach (var item in list1) + { + if (list2.Contains(item)) + { + return true; + } + } + return false; + } } } \ No newline at end of file