/// <summary> /// Adds new post or updates the existing post in the raid post array. /// Matches existing posts with the following logic: /// - Message in the same original channel /// - Pokemon name matches (first priority) /// - User already in thread (second priority) /// </summary> /// <param name="post"></param> /// <returns>Returns either the new post or the one it matched with.</returns> public PokemonRaidPost AddPost(PokemonRaidPost post, MessageParser parser, IChatMessage message, bool add = true, bool force = false) { var guildConfig = Config.GetServerConfig(post.GuildId, ChatTypes.Discord); var channelPosts = guildConfig.Posts.Where(x => x.ChannelMessages.Keys.Where(xx => post.ChannelMessages.Keys.Contains(xx)).Count() > 0); PokemonRaidPost existing = null; if (!force) { //Check if user in existing post is mentioned, get latest post associated with user foreach (var mentionedUser in message.MentionedUsers) { existing = channelPosts.OrderByDescending(x => x.Responses.Max(xx => xx.MessageDate)) .FirstOrDefault(x => x.ChannelMessages.Keys.Contains(message.Channel.Id) && (x.Responses.Where(xx => xx.UserId == mentionedUser.Id).Count() > 0 || x.JoinedUsers.Where(xx => xx.Id == mentionedUser.Id).Count() > 0) && x.PokemonId == (post.PokemonId == 0 ? x.PokemonId : post.PokemonId) && (string.IsNullOrWhiteSpace(x.Location) || string.IsNullOrWhiteSpace(post.Location) || parser.CompareLocationStrings(x.Location, post.Location))); if (existing != null) { break; } } //if location matches, must be same. if (existing == null) { existing = channelPosts.FirstOrDefault(x => x.PokemonId == (post.PokemonId > 0 ? post.PokemonId : x.PokemonId) && parser.CompareLocationStrings(x.Location, post.Location)); } //Lat long comparison, within 30 meters is treated as same //if(existing == null && post.LatLong != null && post.LatLong.HasValue && channelPosts.Where(x => x.LatLong != null && x.LatLong.HasValue).Count() > 0) // existing = channelPosts.Where(x => x.LatLong != null && x.LatLong.HasValue && x.PokemonId == (post.PokemonId > 0 ? post.PokemonId : x.PokemonId)) // .FirstOrDefault(x => parser.CompareLocationLatLong(x.LatLong, post.LatLong)); //Seeing if location and pokemon matches another channel's if (existing == null && !string.IsNullOrEmpty(post.Location)) { existing = guildConfig.Posts.FirstOrDefault(x => x.PokemonId == post.PokemonId && (parser.CompareLocationStrings(x.Location, post.Location) /* || parser.CompareLocationLatLong(x.LatLong, post.LatLong)*/)); } //Final fall through, gets latest post in channel either matching pokemon name or user was involved with if (existing == null && string.IsNullOrEmpty(post.Location))//if location exists and doesn't match, not a match { existing = channelPosts .Where(x => string.IsNullOrWhiteSpace(post.Location) || x.UserId == post.UserId) .OrderByDescending(x => x.PostDate) .OrderBy(x => x.PokemonId == post.PokemonId ? 0 : 1)//pokemon name match takes priority if the user responded to multiple raids in the channel .FirstOrDefault(x => x.ChannelMessages.Keys.Intersect(post.ChannelMessages.Keys).Count() > 0 &&//Posted in the same channel ((post.PokemonId != default(int) && x.PokemonId == post.PokemonId) ||//Either pokemon matches OR (post.PokemonId == default(int) && (x.Responses.Where(xx => xx.UserId == post.UserId).Count() > 0) || post.PokemonId == default(int) && x.JoinedUsers.Where(xx => xx.Id == post.UserId).Count() > 0))//User already in the thread ); } } if (existing != null) { if (add) { existing = MergePosts(existing, post); } existing.IsValid = existing.IsExisting = true; return(existing); } else if (add && post.IsValid) { post.JoinedUsersChanged += JoinCount_Changed; guildConfig.Posts.Add(post); } return(post); }