public IChatEmbed MakeResponseEmbed(PokemonRaidPost post, IBotServerConfiguration guildConfig, string header) { var embed = new DiscordChatEmbed(); embed.WithDescription(header); embed.WithColor(post.Color[0], post.Color[1], post.Color[2]); embed.WithUrl(string.Format(Language.Formats["pokemonInfoLink"], post.PokemonId)); embed.WithThumbnailUrl(string.Format(Language.Formats["imageUrlLargePokemon"], post.PokemonId.ToString().PadLeft(3, '0'))); foreach (var message in post.Responses.OrderBy(x => x.MessageDate).Skip(Math.Max(0, post.Responses.Count() - 10)))//max fields is 25 { embed.AddField(string.Format(Language.Formats["responseInfo"], message.MessageDate.AddHours(TimeOffset), message.ChannelName, message.Username), message.Content); } //var builder = new EmbedBuilder(); /* * builder.WithColor(post.Color[0], post.Color[1], post.Color[2]); * * builder.WithDescription(header); * builder.WithUrl(string.Format(Language.Formats["pokemonInfoLink"], post.PokemonId)); * * builder.WithThumbnailUrl(string.Format(Language.Formats["imageUrlLargePokemon"], post.PokemonId.ToString().PadLeft(3, '0'))); * * foreach (var message in post.Responses.OrderBy(x => x.MessageDate).Skip(Math.Max(0, post.Responses.Count() - 10)))//max fields is 25 * { * builder.AddField(string.Format(Language.Formats["responseInfo"], message.MessageDate.AddHours(TimeOffset), message.ChannelName, message.Username), message.Content); * } */ return(embed); }
public async Task <PokemonRaidPost> AddOrUpdatePost(PokemonRaidPost post) { var loc = Uri.UnescapeDataString(post.FullLocation); var locationEntity = await Locations.SingleOrDefaultAsync(x => x.ServerId == post.GuildId && x.Name == loc); if (locationEntity == null) { var newLoc = _mapper.Map <RaidPostLocationEntity>(post); locationEntity = Locations.Add(newLoc).Entity; await SaveChangesAsync(); } var bossEntity = await Pokemon.SingleOrDefaultAsync(x => x.Id == post.PokemonId); if (bossEntity == null) { var newBoss = _mapper.Map <PokemonEntity>(post); bossEntity = Pokemon.Add(newBoss).Entity; } var postEntity = new RaidPostEntity(); if (post.DbId != default(ulong)) { postEntity = await Posts.FirstOrDefaultAsync(x => x.Id == post.DbId); } _mapper.Map(post, postEntity); postEntity.Pokemon = bossEntity; postEntity.PokemonId = bossEntity.Id; postEntity.Location = locationEntity; postEntity.LocationId = locationEntity.Id; if (post.DbId == default(ulong)) { Add(postEntity); await SaveChangesAsync(); post.DbId = postEntity.Id; } foreach (var channelId in post.ChannelMessages.Keys.Where(x => ChannelPosts.Where(y => y.ChannelId == x && y.RaidPostId == post.DbId).Count() == 0)) { var channelPost = new RaidPostChannelEntity() { ChannelId = channelId, RaidPostId = post.DbId }; Add(channelPost); } await SaveChangesAsync(); post.DbLocationId = locationEntity.Id; return(post); }
private void JoinCount_Changed(object sender, JoinedCountChangedEventArgs e) { PokemonRaidPost post = null; IBotServerConfiguration guildConfig = null; PokemonRaidJoinedUser joinedUser = null; if (sender is PokemonRaidPost) { post = (PokemonRaidPost)sender; guildConfig = Config.GetServerConfig(post.GuildId, ChatTypes.Discord); } else if (sender is PokemonRaidJoinedUser) { joinedUser = (PokemonRaidJoinedUser)sender; guildConfig = Config.GetServerConfig(joinedUser.GuildId, ChatTypes.Discord); //var guild = bot.Guil post = guildConfig.Posts.FirstOrDefault(x => x.UniqueId == joinedUser.PostId); } if (post != null) { List <Task> tasks = new List <Task>(); var parser = GetParser(guildConfig); var joinstr = parser.Language.Strings["joining"]; if (e.ChangeType == JoinCountChangeType.Remove || (e.ChangeType == JoinCountChangeType.Change && e.Count < 0)) { joinstr = parser.Language.Strings["quitting"]; } string message = string.Format(parser.Language.Formats["directMessage"], e.Count, joinstr, post.PokemonName, e.ArriveTime.HasValue && !joinstr.Equals(parser.Language.Strings["quitting"]) ? string.Format(parser.Language.Formats["postjoinTime"], e.ArriveTime.Value.ToString("t")) : "", e.UserName); var usersToDM = new List <ulong>(); if (post.UserId != e.UserId) { usersToDM.Add(post.UserId); } usersToDM.AddRange(post.JoinedUsers.Where(x => x.Id != e.UserId && x.Id != post.UserId).Select(x => x.Id)); foreach (var id in usersToDM) { var user = bot.GetUser(id); if (user != default(SocketUser)) { tasks.Add(DirectMessageUser(new DiscordChatUser(user), $"{message}\n{parser.Language.Strings["dmStop"]}"));//TODO } } Task.WaitAll(tasks.ToArray()); } }
/// <summary> /// Performs the raid post behavior /// </summary> /// <param name="message"></param> /// <param name="parser"></param> /// <param name="outputchannel"></param> /// <param name="pin"></param> /// <returns></returns> public async Task DoPost(PokemonRaidPost post, IChatMessage message, MessageParser parser, IChatChannel outputchannel = null, bool force = false) { //var post = await parser.ParsePost(message, Config);//await DoResponse(message, parser);//returns null if if (post != null) { post.OutputChannelId = outputchannel?.Id ?? 0; post = AddPost(post, parser, message, true, force); if (post.IsValid) { IDisposable d = null; if (!post.IsExisting)//it's going to post something and google geocode can take a few secs so we can do the "typing" behavior { d = message.Channel.EnterTypingState(); } try { if ((post.LatLong == null || !post.LatLong.HasValue) && !string.IsNullOrWhiteSpace(post.Location)) { var guildConfig = Config.GetServerConfig(message.Channel.Server.Id, ChatTypes.Discord); if (guildConfig.Places.ContainsKey(post.Location.ToLower())) { post.LatLong = guildConfig.Places[post.Location.ToLower()]; } else { post.LatLong = await parser.GetLocationLatLong(post.FullLocation, message.Channel, Config); } } await MakePost(post, parser); Config.Save(); } catch (Exception e) { DoError(e); } finally { if (d != null) { d.Dispose(); } } } //else TODO maybe DM user to see if it's valid? Tricky because hard to hold on to post ID reference... } Config.Save(); }
public async Task MarkPostDeleted(PokemonRaidPost post) { if (post.DbId != default(ulong)) { var postEntity = await Posts.FirstOrDefaultAsync(x => x.Id == post.DbId); if (postEntity != null) { postEntity.Deleted = true; postEntity.EndDate = DateTime.Now; await SaveChangesAsync(); } } }
public IChatEmbed MakeHeaderEmbed(PokemonRaidPost post, string text = null) { if (string.IsNullOrEmpty(text)) { text = MakePostHeader(post); } var headerembed = new DiscordChatEmbed(); headerembed.WithColor(post.Color[0], post.Color[1], post.Color[2]); headerembed.WithUrl(string.Format(Language.Formats["pokemonInfoLink"], post.PokemonId)); headerembed.WithDescription(Language.RegularExpressions["discordChannel"].Replace(text, "").Replace(" in ", " ").Replace(" ", " ")); headerembed.WithThumbnailUrl(string.Format(Language.Formats["imageUrlSmallPokemon"], post.PokemonId.ToString().PadLeft(3, '0'))); return(headerembed); }
public void MakePostWithEmbed(PokemonRaidPost post, IBotServerConfiguration guildConfig, out IChatEmbed header, out IChatEmbed response, out string channel, out string mentions) { var headerstring = MakePostHeader(post); response = MakeResponseEmbed(post, guildConfig, headerstring); header = MakeHeaderEmbed(post, headerstring); var joinedUserIds = post.JoinedUsers.Select(x => x.Id); var mentionUserIds = post.Responses.Select(x => x.UserId.ToString()).Distinct().ToList(); mentionUserIds.AddRange(post.JoinedUsers.Select(x => x.Id.ToString()).Distinct()); channel = $"<#{string.Join(">, <#", post.ChannelMessages.Keys)}>"; //var users = mentionUserIds.Count() > 0 ? $",<@{string.Join(">,<@", mentionUserIds.Distinct())}>" : ""; mentions = post.MentionedRoleIds.Count() > 0 ? $"<@&{string.Join(">, <@&", post.MentionedRoleIds.Distinct())}>" : ""; //mentions = channel +/* users +*/ roles; }
public string MakePostHeader(PokemonRaidPost post) { var joinString = string.Join(", ", post.JoinedUsers.Where(x => x.PeopleCount > 0).Select(x => string.Format("@{0}(**{1}**{2})", x.Name, x.PeopleCount, x.ArriveTime.HasValue ? $" *@{x.ArriveTime.Value.ToString("t")}*" : ""))); var joinCount = post.JoinedUsers.Sum(x => x.PeopleCount); var location = post.Location; var groupStarts = string.Join(", ", post.RaidStartTimes.OrderBy(x => x.Value.Ticks).Select(x => x.Value.AddHours(TimeOffset).ToString("t"))); if (!string.IsNullOrEmpty(groupStarts)) { groupStarts = string.Format(Language.Formats["groupStartTimes"], post.RaidStartTimes.Count, groupStarts); } var mapLinkFormat = Language.Formats["googleMapLink"]; var old = CultureInfo.CurrentCulture.NumberFormat; CultureInfo.CurrentCulture.NumberFormat = new CultureInfo("en-us").NumberFormat; if (post.LatLong != null && post.LatLong.HasValue) { location = string.Format("[{0}]({1})", location, string.Format(mapLinkFormat, post.LatLong.Latitude, post.LatLong.Longitude)); } CultureInfo.CurrentCulture.NumberFormat = old; string response = string.Format(Language.Formats["postHeader"], post.UniqueId, string.Format("[{0}]({1})", post.PokemonName, string.Format(Language.Formats["pokemonInfoLink"], post.PokemonId)), !string.IsNullOrEmpty(location) ? string.Format(Language.Formats["postLocation"], location) : "", string.Format(!post.HasEndDate ? Language.Formats["postEndsUnsure"] : Language.Formats["postEnds"], post.EndDate.AddHours(TimeOffset).ToString("t")), groupStarts, joinCount > 0 ? string.Format(Language.Formats["postJoined"], joinCount, joinString) : Language.Strings["postNoneJoined"] ); return(response); }
public IChatEmbed MakeResponseEmbed(PokemonRaidPost post, IBotServerConfiguration guildConfig, string header) { throw new NotImplementedException(); }
public string MakePostHeader(PokemonRaidPost post) { throw new NotImplementedException(); }
/// <summary> /// Creates the text string and outputs the post message into the channel. /// If post.MessageId is populated, will delete and recreate the message. /// 403 Error is output to console if bot user doesn't have role access to manage messages. /// </summary> /// <param name="post"></param> /// <param name="parser"></param> public async Task <List <IChatMessage> > MakePost(PokemonRaidPost post, MessageParser parser) { var results = new List <IChatMessage>(); var output = new DiscordMessageOutput(parser.Lang, parser.TimeOffset); try { post = await dbContext.AddOrUpdatePost(post); } catch (Exception e) { DoError(e); } try { var newMessages = new Dictionary <ulong, ulong>(); var channelNum = 0; var outputChannel = GetChannel(post.OutputChannelId); //IUserMessage messageResult; IChatEmbed headerEmbed, responsesEmbed; string mentionString, channelString; var guildConfig = Config.GetServerConfig(post.GuildId, ChatTypes.Discord); output.MakePostWithEmbed(post, guildConfig, out headerEmbed, out responsesEmbed, out channelString, out mentionString); foreach (var channelMessage in post.ChannelMessages) { var fromChannel = GetChannel(channelMessage.Key); if (fromChannel != null && fromChannel is SocketGuildChannel) { if (!guildConfig.PinChannels.Contains(fromChannel.Id)) { continue; } var fromChannelMessage = headerEmbed.Description; if (channelMessage.Value.MessageId != default(ulong)) { var messageResult1 = (IUserMessage)await fromChannel.GetMessageAsync(channelMessage.Value.MessageId); if (messageResult1 != null) { results.Add(new DiscordChatMessage(messageResult1)); //only modify post if something changed if (!messageResult1.Embeds.FirstOrDefault()?.Description.Equals(fromChannelMessage, StringComparison.OrdinalIgnoreCase) ?? true) { await messageResult1.ModifyAsync(x => { x.Content = channelNum == 0 ? mentionString : " "; x.Embed = (Embed)headerEmbed.GetEmbed(); }); } } } else { var messageResult2 = await fromChannel.SendMessageAsync(channelNum == 0?mentionString : " ", false, (Embed)headerEmbed.GetEmbed()); results.Add(new DiscordChatMessage(messageResult2)); try { var options = new RequestOptions(); await messageResult2.PinAsync(); } catch (Exception e) { DoError(e); } newMessages[channelMessage.Key] = messageResult2.Id; } } channelNum++; } foreach (var newMessage in newMessages) { post.ChannelMessages[newMessage.Key].MessageId = newMessage.Value; } if (outputChannel != null) { if (post.OutputMessageId != default(ulong)) { var messageResult3 = (IUserMessage)await outputChannel.GetMessageAsync(post.OutputMessageId); if (messageResult3 != null) { results.Add(new DiscordChatMessage(messageResult3)); await messageResult3.ModifyAsync(x => { x.Embed = (Embed)responsesEmbed.GetEmbed(); x.Content = channelString; }); } } else { var messageResult4 = await outputChannel.SendMessageAsync(channelString, false, (Embed)responsesEmbed.GetEmbed()); results.Add(new DiscordChatMessage(messageResult4)); post.OutputMessageId = messageResult4.Id; } } } catch (Exception e) { DoError(e); } return(results); }
public PokemonRaidPost MergePosts(PokemonRaidPost post1, PokemonRaidPost post2) { throw new NotImplementedException(); }
public Task <List <IChatMessage> > MakePost(PokemonRaidPost post, MessageParser parser) { throw new NotImplementedException(); }
public Task DoPost(PokemonRaidPost post, IChatMessage message, MessageParser parser, IChatChannel outputchannel, bool force = false) { throw new NotImplementedException(); }
public Task <bool> DeletePost(PokemonRaidPost post, ulong userId, bool isAdmin, bool purge = true) { throw new NotImplementedException(); }
public PokemonRaidPost AddPost(PokemonRaidPost post, MessageParser parser, IChatMessage message, bool add = true, bool force = false) { throw new NotImplementedException(); }
public IChatEmbed MakeHeaderEmbed(PokemonRaidPost post, string text = null) { throw new NotImplementedException(); }
/// <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); }
public void MakePostWithEmbed(PokemonRaidPost post, IBotServerConfiguration guildConfig, out IChatEmbed header, out IChatEmbed response, out string channel, out string mentions) { throw new NotImplementedException(); }
/// <summary> /// Combines two posts into one. The second is should be the newer post. /// </summary> /// <param name="post1"></param> /// <param name="post2"></param> /// <returns></returns> public PokemonRaidPost MergePosts(PokemonRaidPost post1, PokemonRaidPost post2) { if (post2.HasEndDate && (!post1.HasEndDate || post2.UserId == post1.UserId)) { post1.HasEndDate = true; post1.EndDate = post2.EndDate; } if (string.IsNullOrEmpty(post1.Location) && !string.IsNullOrEmpty(post2.Location))//only merge location if first is blank and second has lat long { post1.Location = post2.Location; post1.FullLocation = post2.FullLocation; post1.LatLong = post2.LatLong; } post1.LastMessageDate = new DateTime(Math.Max(post1.LastMessageDate.Ticks, post2.LastMessageDate.Ticks)); //overwrite with new values foreach (var user in post2.JoinedUsers) { if (post1.JoinedUsers.FirstOrDefault(x => x.Id == user.Id) == null) { post1.JoinedUsers.Add(new PokemonRaidJoinedUser(user.Id, post1.GuildId, post1.UniqueId, user.Name, user.PeopleCount, false, false, user.ArriveTime)); } else if (post2.UserId == user.Id) { var postUser = post1.JoinedUsers.FirstOrDefault(x => x.Id == post2.UserId); if (postUser != null) { if (user.IsLess) { postUser.PeopleCount -= user.PeopleCount; } else if (user.IsMore) { postUser.PeopleCount += user.PeopleCount; } else if (user.PeopleCount > 0) { postUser.PeopleCount = user.PeopleCount; } if (user.ArriveTime.HasValue) { postUser.ArriveTime = user.ArriveTime; //always update arrive time if present } } } } post1.ChannelMessages = post1.ChannelMessages.Concat(post2.ChannelMessages.Where(x => !post1.ChannelMessages.ContainsKey(x.Key))).ToDictionary(x => x.Key, y => y.Value); //foreach (var key in post1.ChannelMessages.Keys.Where(x => post2.ChannelMessages.Keys.Contains(x))) //{ // post2.ChannelMessages.Remove(key); //} post1.Responses.AddRange(post2.Responses); post1.MentionedRoleIds.AddRange(post2.MentionedRoleIds.Where(x => !post1.MentionedRoleIds.Contains(x))); return(post1); }
/// <summary> /// Attempts to parse the necessary information out of a message to create a raid post. /// </summary> /// <param name="message"></param> /// <param name="config"></param> /// <returns>If return value is null, or property 'Pokemon' is null, raid post is invalid.</returns> public PokemonRaidPost ParsePost(IChatMessage message) { CultureInfo.CurrentCulture = Language.GetCultureInfo(); //var guild = ((SocketGuildChannel)message.Channel).Guild; //var guildConfig = config.GetServerConfig(message.Server.Id, message.ChatType, message.Server.Name); var result = new PokemonRaidPost() { GuildId = message.Server.Id, PostDate = DateTime.Now, UserId = message.User.Id, Color = GetRandomColorRGB(), LastMessageDate = DateTime.Now, ChannelMessages = new Dictionary <ulong, PokemonRaidPostOwner>(), EndDate = DateTime.Now + new TimeSpan(0, defaultRaidMinutes, 0), MentionedRoleIds = new List <ulong>() }; result.ChannelMessages[message.Channel.Id] = new PokemonRaidPostOwner(default(ulong), message.User.Id); var messageString = message.Content.Replace(" & ", $" {Language.Strings["and"]} ").Replace(" @ ", $" {Language.Strings["at"]} "); var words = messageString.Split(' '); var i = 0; var nopost = false; var unmatchedWords = new List <string>(); foreach (var word in words) { i++; var cleanedword = word; bool isMention = false; var roleReg = Language.RegularExpressions["discordRole"]; var userReg = Language.RegularExpressions["discordUser"]; var channelReg = Language.RegularExpressions["discordChannel"]; //clean up all role, user and channel mentions if (roleReg.IsMatch(word)) { var roleId = Convert.ToUInt64(roleReg.Match(word).Groups[1].Value); cleanedword = message.MentionedRoles.FirstOrDefault(x => x.Id == roleId)?.Name ?? cleanedword; messageString = messageString.Replace(word, "@" + cleanedword);//This must be done so mentions display properly in embed with android isMention = true; } else if (userReg.IsMatch(word)) { var userId = Convert.ToUInt64(userReg.Match(word).Groups[1].Value); var u = message.MentionedUsers.FirstOrDefault(x => x.Id == userId); cleanedword = u?.Nickname ?? u?.Name ?? cleanedword; messageString = messageString.Replace(word, "@" + cleanedword); isMention = true; } else if (channelReg.IsMatch(word)) { var channelId = Convert.ToUInt64(channelReg.Match(word).Groups[1].Value); cleanedword = message.MentionedChannels.FirstOrDefault(x => x.Id == channelId)?.Name ?? cleanedword; messageString = messageString.Replace(word, "#" + cleanedword); isMention = true; } var garbageRegex = Language.RegularExpressions["garbage"]; if (garbageRegex.IsMatch(cleanedword)) { unmatchedWords.Add(matchedWordReplacement); continue; } if (result.PokemonId == default(int)) { var pokemon = ParsePokemon(cleanedword); if (pokemon != null) { result.PokemonId = pokemon.Id; result.PokemonName = pokemon.Name; if (i > 1 && Language.RegularExpressions["pokemonInvalidators"].IsMatch(words[i - 2]))//if previous word invalidates -- ex "any Snorlax?" { nopost = true; } unmatchedWords.Add(matchedPokemonWordReplacement); continue; } } if (isMention) { cleanedword = matchedWordReplacement; } unmatchedWords.Add(cleanedword); } var unmatchedString = string.Join(" ", unmatchedWords.ToArray()); //post was invalidated if (nopost) { result.PokemonId = default(int); } //lat longs will break the timespan parser and are easy to identify, so get them first var latLong = ParseLatLong(ref unmatchedString); ParseTimespanFull(ref unmatchedString, out TimeSpan? raidTimeSpan, out TimeSpan? joinTimeSpan, out DateTime? raidTime, out DateTime? joinTime); if (joinTimeSpan.HasValue) { joinTime = DateTime.Now + joinTimeSpan.Value; } if (raidTime.HasValue) { result.EndDate = raidTime.Value; result.HasEndDate = true; } else if (raidTimeSpan.HasValue) { var resultTs = new TimeSpan(0, maxRaidMinutes, 0); if (raidTimeSpan.Value < resultTs) { resultTs = raidTimeSpan.Value; } result.EndDate = DateTime.Now + resultTs; result.HasEndDate = true; } bool isMore, isLess; var joinCount = ParseJoinedUsersCount(ref unmatchedString, out isMore, out isLess); if (!joinCount.HasValue && joinTime.HasValue) { joinCount = 1; } if (joinCount.HasValue) { result.JoinedUsers.Add(new PokemonRaidJoinedUser(message.User.Id, message.Server.Id, result.UniqueId, message.User.Name, joinCount.Value, isMore, isLess, joinTime)); } if (latLong.HasValue) { result.Location = latLong.ToString(); result.LatLong = latLong; } else { result.Location = ParseLocation(unmatchedString, serverConfig); if (!string.IsNullOrEmpty(result.Location)) { result.FullLocation = GetFullLocation(result.Location, serverConfig, message.Channel.Id); } } result.Responses.Add(new PokemonMessage(message.User.Id, message.User.Name, messageString, DateTime.Now, message.Channel.Name)); var mention = message.Server.Roles.FirstOrDefault(x => x.Name == result.PokemonName); //((SocketGuildChannel)message.Channel).Guild.Roles.FirstOrDefault(x => x.Name == result.PokemonName); if (mention != null && !message.MentionedRoles.ToList().Contains(mention) && !result.MentionedRoleIds.Contains(mention.Id)) //avoid double notification { result.MentionedRoleIds.Add(mention.Id); } if (Language.RegularExpressions["sponsored"].IsMatch(message.Content)) { mention = message.Server.Roles.FirstOrDefault(x => x.Name.ToLower() == Language.Strings["sponsored"].ToLower()); if (mention != null && !message.MentionedRoles.ToList().Contains(mention) && !result.MentionedRoleIds.Contains(mention.Id))//avoid double notification { result.MentionedRoleIds.Add(mention.Id); } } foreach (var role in message.Server.Roles.Where(x => !message.MentionedRoles.Contains(x) && !result.MentionedRoleIds.Contains(x.Id))) {//notify for roles that weren't actually mentions var reg = new Regex($@"\b{role.Name}\b", RegexOptions.IgnoreCase); if (reg.IsMatch(message.Content)) { result.MentionedRoleIds.Add(role.Id); } } result.IsValid = result.PokemonId != default(int) && (!string.IsNullOrWhiteSpace(result.Location)); return(result); }
/// <summary> /// Delete a post from both chat and the list. /// </summary> /// <param name="post"></param> public async Task <bool> DeletePost(PokemonRaidPost post, ulong userId, bool isAdmin, bool purge = true) { if (isAdmin) { post.EndDate = DateTime.MinValue; await dbContext.MarkPostDeleted(post); if (purge) { await PurgePosts(); } return(true); } var delChannels = new List <ulong>(); var delMessages = new List <IMessage>(); foreach (var channelMessage in post.ChannelMessages) { if (channelMessage.Value.UserId != userId) { continue; } var channel = bot.GetChannel(channelMessage.Key); if (channelMessage.Value.MessageId > 0 && channel != null && channel is ISocketMessageChannel) { var message = await((ISocketMessageChannel)channel).GetMessageAsync(channelMessage.Value.MessageId); delChannels.Add(channelMessage.Key); delMessages.Add(message); } } if (delChannels.Count() == post.ChannelMessages.Count())//poster was the only one posting, get rid of all { post.EndDate = DateTime.MinValue; await dbContext.MarkPostDeleted(post); if (purge) { await PurgePosts(); } return(true); } foreach (var channel in delChannels) { post.ChannelMessages.Remove(channel); } var tasks = new List <Task>(); foreach (var message in delMessages) { tasks.Add(message.DeleteAsync()); } Task.WaitAll(tasks.ToArray()); return(delChannels.Count() > 0); }