コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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());
            }
        }
コード例 #4
0
        /// <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();
        }
コード例 #5
0
        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();
                }
            }
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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;
        }
コード例 #8
0
        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);
        }
コード例 #9
0
 public IChatEmbed MakeResponseEmbed(PokemonRaidPost post, IBotServerConfiguration guildConfig, string header)
 {
     throw new NotImplementedException();
 }
コード例 #10
0
 public string MakePostHeader(PokemonRaidPost post)
 {
     throw new NotImplementedException();
 }
コード例 #11
0
        /// <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);
        }
コード例 #12
0
 public PokemonRaidPost MergePosts(PokemonRaidPost post1, PokemonRaidPost post2)
 {
     throw new NotImplementedException();
 }
コード例 #13
0
 public Task <List <IChatMessage> > MakePost(PokemonRaidPost post, MessageParser parser)
 {
     throw new NotImplementedException();
 }
コード例 #14
0
 public Task DoPost(PokemonRaidPost post, IChatMessage message, MessageParser parser, IChatChannel outputchannel, bool force = false)
 {
     throw new NotImplementedException();
 }
コード例 #15
0
 public Task <bool> DeletePost(PokemonRaidPost post, ulong userId, bool isAdmin, bool purge = true)
 {
     throw new NotImplementedException();
 }
コード例 #16
0
 public PokemonRaidPost AddPost(PokemonRaidPost post, MessageParser parser, IChatMessage message, bool add = true, bool force = false)
 {
     throw new NotImplementedException();
 }
コード例 #17
0
 public IChatEmbed MakeHeaderEmbed(PokemonRaidPost post, string text = null)
 {
     throw new NotImplementedException();
 }
コード例 #18
0
        /// <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);
        }
コード例 #19
0
 public void MakePostWithEmbed(PokemonRaidPost post, IBotServerConfiguration guildConfig, out IChatEmbed header, out IChatEmbed response, out string channel, out string mentions)
 {
     throw new NotImplementedException();
 }
コード例 #20
0
        /// <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);
        }
コード例 #21
0
        /// <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);
        }
コード例 #22
0
        /// <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);
        }