示例#1
0
        protected virtual void HandleQuoteUserCommand(CommandMatch cmd, IUserMessageEventArgs msg)
        {
            Action <string> postReply;
            string          location;
            QuoteRating     rating;
            bool            addMyRating;

            GetReplyActionAndLocationForMessage(msg, out postReply, out location);
            if (!FlagsToQuoteFilter(cmd, out rating, out addMyRating))
            {
                // invalid flags
                return;
            }

            var    nick          = (string)cmd.Arguments[0];
            string lowercaseNick = nick.ToLowerInvariant();

            using (var ctx = GetNewContext())
            {
                IQueryable <Quote> quotesWithVotes = ctx.Quotes
                                                     .Include(q => q.Votes)
                                                     .Where(q => q.Author.ToLower() == lowercaseNick);

                PostRandomQuote(msg.SenderNickname, location, quotesWithVotes, rating, addMyRating, postReply);
            }
        }
示例#2
0
        protected virtual void HandleNextQuoteCommand(CommandMatch cmd, IUserMessageEventArgs msg)
        {
            Action <string> postReply;
            string          location;
            QuoteRating     rating;
            bool            addMyRating;

            GetReplyActionAndLocationForMessage(msg, out postReply, out location);
            if (!FlagsToQuoteFilter(cmd, out rating, out addMyRating))
            {
                // invalid flags
                return;
            }

            using (var ctx = GetNewContext())
            {
                Quote quote = null;
                switch (rating)
                {
                case QuoteRating.Any:
                    if (ShuffledAnyQuotes == null)
                    {
                        ShuffledAnyQuotes = GetFilteredQuotes(ctx.Quotes.Include(q => q.Votes), QuoteRating.Any)
                                            .ToShuffledList();
                        ShuffledAnyQuotesIndex = 0;
                    }
                    quote = ShuffledAnyQuotes[ShuffledAnyQuotesIndex++];
                    ShuffledAnyQuotesIndex %= ShuffledAnyQuotes.Count;
                    break;

                case QuoteRating.High:
                    if (ShuffledGoodQuotes == null)
                    {
                        ShuffledGoodQuotes = GetFilteredQuotes(ctx.Quotes.Include(q => q.Votes), QuoteRating.High)
                                             .ToShuffledList();
                        ShuffledGoodQuotesIndex = 0;
                    }
                    quote = ShuffledGoodQuotes[ShuffledGoodQuotesIndex++];
                    ShuffledGoodQuotesIndex %= ShuffledGoodQuotes.Count;
                    break;

                case QuoteRating.Low:
                    if (ShuffledBadQuotes == null)
                    {
                        ShuffledBadQuotes = GetFilteredQuotes(ctx.Quotes.Include(q => q.Votes), QuoteRating.Low)
                                            .ToShuffledList();
                        ShuffledBadQuotesIndex = 0;
                    }
                    quote = ShuffledBadQuotes[ShuffledBadQuotesIndex++];
                    ShuffledBadQuotesIndex %= ShuffledBadQuotes.Count;
                    break;

                default:
                    Debug.Fail("unexpected quote rating");
                    break;
                }

                PostQuote(quote, msg.SenderNickname, location, addMyRating, postReply);
            }
        }
示例#3
0
        protected virtual void ActuallyHandleChannelOrQueryAka([NotNull] CommandMatch cmd,
                                                               [NotNull] IUserMessageEventArgs e, [NotNull] Action <string> respond)
        {
            string nickToSearch = (string)cmd.Arguments[0];

            if (!NickToMostRecentHost.ContainsKey(nickToSearch))
            {
                respond($"I don\u2019t remember {nickToSearch}.");
                return;
            }

            var identifier      = NickToMostRecentHost[nickToSearch];
            var identifierParts = identifier.Parts;

            ImmutableList <HashSet <string> > matches;
            int matchDepth = HostToNicks.GetBestMatches(identifierParts, out matches);

            if (matchDepth == -1)
            {
                respond($"I don\u2019t remember any other nickname from {identifier} than {nickToSearch}.");
                return;
            }

            ImmutableList <HashSet <string> > fuzzyMatches = null;
            int fuzzyMatchDepth = -1;

            if (matchDepth == identifierParts.Count)
            {
                // do a fuzzy match too
                // replace the last item in identifierParts with the empty string
                var fuzzyIdentifierParts = identifierParts.SetItem(identifierParts.Count - 1, "");
                fuzzyMatchDepth = HostToNicks.GetBestMatches(fuzzyIdentifierParts, out fuzzyMatches);
            }

            var otherNicks      = new SortedSet <string>(matches.SelectMany(x => x));
            var fuzzyOtherNicks = (fuzzyMatches == null)
                ? null
                : new SortedSet <string>(fuzzyMatches.SelectMany(x => x));

            fuzzyOtherNicks?.ExceptWith(otherNicks);

            if (matchDepth == identifierParts.Count)
            {
                if (fuzzyOtherNicks != null && fuzzyOtherNicks.Count > 0)
                {
                    respond($"{identifier}: {otherNicks.StringJoin(", ")}; fuzzy match ({fuzzyMatchDepth}/{identifierParts.Count}) also: {fuzzyOtherNicks.StringJoin(", ")}");
                }
                else
                {
                    respond($"{identifier}: {otherNicks.StringJoin(", ")}");
                }
            }
            else
            {
                respond($"{identifier} fuzzy match ({matchDepth}/{identifierParts.Count}): {otherNicks.StringJoin(", ")}");
            }
        }
示例#4
0
        protected virtual void HandleDownquoteCommand(CommandMatch cmd, IUserMessageEventArgs msg)
        {
            string normalizedSender = ConnectionManager.RegisteredNameForNick(msg.SenderNickname) ?? msg.SenderNickname;

            Action <string> postReply;
            string          location;

            GetReplyActionAndLocationForMessage(msg, out postReply, out location);

            if (!LastQuoteIDs.ContainsKey(location))
            {
                postReply("You'll have to get a quote first...");
            }
            UpsertVote(normalizedSender, LastQuoteIDs[location], -1);
        }
示例#5
0
        protected void GetReplyActionAndLocationForMessage(IUserMessageEventArgs msg, out Action <string> replyAction,
                                                           out string location)
        {
            var channelMsg = msg as IChannelMessageEventArgs;

            if (channelMsg != null)
            {
                replyAction = (body) => ConnectionManager.SendChannelMessage(channelMsg.Channel, body);
                location    = channelMsg.Channel;
            }
            else
            {
                Debug.Assert(msg is IPrivateMessageEventArgs);
                replyAction = (body) => ConnectionManager.SendQueryMessage(msg.SenderNickname, body);
                location    = msg.SenderNickname;
            }
        }
示例#6
0
        protected virtual void HandleSmileysCommand(CommandMatch cmd, IUserMessageEventArgs e)
        {
            foreach (var smiley in Config.Smileys)
            {
                var smileyLine = new StringBuilder(smiley);
                if (smiley.Length > 1)
                {
                    // escape smiley by adding ZWNBSP in between first and second character

                    smileyLine.Append(" = ");
                    smileyLine.Append(smiley[0]);
                    smileyLine.Append('\uFEFF');
                    smileyLine.Append(smiley, 1, smiley.Length - 1);
                }
                ConnectionManager.SendQueryMessage(e.SenderNickname, smileyLine.ToString());
            }
        }
示例#7
0
        protected void Output(Action <string> respond, IUserMessageEventArgs message, string command,
                              ResponseManager responseManager, string targetNick)
        {
            var channelMessage = message as IChannelMessageEventArgs;

            string targetBody = responseManager.NextResponse(RNG);

            if (targetBody == null)
            {
                return;
            }

            Logger.LogDebug("{Sender} triggered {Command} in {Location}", message.SenderNickname, command, channelMessage?.Channel ?? "private message");
            var response = targetBody.Replace("{{NICKNAME}}", targetNick);

            foreach (var line in response.Split('\n').Where(l => l.Length > 0))
            {
                respond(line);
            }
        }
示例#8
0
        protected string VerifyIdentity(IUserMessageEventArgs message)
        {
            var username = message.SenderNickname;

            if (Config.UseIrcServices)
            {
                username = ConnectionManager.RegisteredNameForNick(username);
                if (username == null)
                {
                    Logger.LogInformation("{Nickname} is not logged in; ignoring", message.SenderNickname);
                    return(null);
                }
            }

            if (!Config.Puppeteers.Contains(username))
            {
                Logger.LogInformation("{Username} is not a puppeteer; ignoring", username);
                return(null);
            }

            return(username);
        }
示例#9
0
        protected virtual bool ApplyGlobalCallbacks(CommandMatch match, IUserMessageEventArgs msg)
        {
            bool callbackSaidNo = false;

            foreach (GlobalCommandCallback callback in GlobalCommandCallbacks)
            {
                try
                {
                    if (!callback.Invoke(match, msg))
                    {
                        callbackSaidNo = true;
                    }
                }
                catch (Exception exc)
                {
                    Logger.LogError(
                        "error when global callback {GlobalCommandCallback} was processing command {Command}: {Exception}",
                        callback, match.CommandName, exc
                        );
                }
            }
            return(!callbackSaidNo);
        }
示例#10
0
        protected virtual void HandleQuoteCommand(CommandMatch cmd, IUserMessageEventArgs msg)
        {
            Action <string> postReply;
            string          location;
            QuoteRating     rating;
            bool            addMyRating;

            GetReplyActionAndLocationForMessage(msg, out postReply, out location);
            if (!FlagsToQuoteFilter(cmd, out rating, out addMyRating))
            {
                // invalid flags
                return;
            }

            string subject = ((string)cmd.Arguments[0]);

            if (subject.StartsWith(" "))
            {
                subject = subject.Substring(1);
            }
            if (subject.Trim().Length == 0)
            {
                subject = null;
            }

            var lowercaseSubject = subject?.ToLowerInvariant();

            using (var ctx = GetNewContext())
            {
                IQueryable <Quote> quotes = (lowercaseSubject != null)
                    ? ctx.Quotes.Where(q => q.Body.ToLower().Contains(lowercaseSubject))
                    : ctx.Quotes;
                IQueryable <Quote> quotesWithVotes = quotes.Include(q => q.Votes);

                PostRandomQuote(msg.SenderNickname, location, quotesWithVotes, rating, addMyRating, postReply);
            }
        }
        protected virtual bool LimiterCallback(CommandMatch commandMatch, IUserMessageEventArgs msg)
        {
            // is it a fun command?
            if (!commandMatch.Command.Tags.Any(tag => Config.CommandTags.Contains(tag)))
            {
                // no => don't protest
                return(true);
            }

            // how soon is then?
            DateTimeOffset cutoff = DateTimeOffset.Now.AddMinutes(-Config.TimeSpanMinutes);

            // find the keys
            string channelKey;

            if (Config.PerChannel)
            {
                var chanMsg = msg as IChannelMessageEventArgs;
                if (chanMsg != null)
                {
                    if (!Config.Channels.Contains(chanMsg.Channel))
                    {
                        // we're not policing this channel
                        return(true);
                    }

                    channelKey = chanMsg.Channel;
                }
                else
                {
                    // private message
                    if (!Config.CountPrivateMessages)
                    {
                        // we don't bother with those
                        return(true);
                    }

                    channelKey = PrivateMessageChannelKey;
                }
            }
            else
            {
                if (msg is IPrivateMessageEventArgs && !Config.CountPrivateMessages)
                {
                    // we don't bother with private messages
                    return(true);
                }

                channelKey = GlobalChannelKey;
            }

            string userKey = Config.PerUser
                ? (Connection.RegisteredNameForNick(msg.SenderNickname) ?? msg.SenderNickname)
                : GlobalUserKey;

            // obtain the timestamps
            List <DateTimeOffset> timestamps = ObtainTimeStampsForChannelAndUserKeys(channelKey, userKey);

            // clear out the old ones
            timestamps.RemoveAll(ts => ts < cutoff);

            if (timestamps.Count > Config.MaxCountPerTime)
            {
                // too many

                if (Config.CountLimitedAttempts)
                {
                    // count this one even though it failed >;-)
                    timestamps.Add(DateTimeOffset.Now);
                }

                return(false);
            }

            // count this one but allow it
            timestamps.Add(DateTimeOffset.Now);
            return(true);
        }
示例#12
0
        protected void ActuallyHandleMessage(Action <string> respond, IUserMessageEventArgs args, MessageFlags flags)
        {
            if (flags.HasFlag(MessageFlags.UserBanned))
            {
                return;
            }

            if (args.SenderNickname == ConnectionManager.MyNickname)
            {
                return;
            }

            var lowerBody = args.Message.ToLowerInvariant();

            ResponseManager commandResponseManager;

            if (CommandsResponses.TryGetValue(lowerBody, out commandResponseManager))
            {
                Output(respond, args, lowerBody, commandResponseManager, args.SenderNickname);
                return;
            }

            var channelNicks   = new HashSet <string>();
            var channelMessage = args as IChannelMessageEventArgs;

            if (channelMessage != null)
            {
                var nicknamesInChannel = ConnectionManager.NicknamesInChannel(channelMessage.Channel);
                if (nicknamesInChannel != null)
                {
                    channelNicks.UnionWith(nicknamesInChannel);
                }
            }

            foreach (var nickCommandResponse in NicknamableCommandsResponses)
            {
                if (!lowerBody.StartsWith(nickCommandResponse.Key))
                {
                    // not this command
                    continue;
                }

                if (lowerBody.TrimEnd() == nickCommandResponse.Key)
                {
                    // command on its own; trigger for self
                    Output(respond, args, nickCommandResponse.Key, nickCommandResponse.Value, args.SenderNickname);
                    return;
                }

                // trigger for someone else?
                string targetedNickCased = args.Message.Substring(nickCommandResponse.Key.Length).Trim();
                string targetedNick      = lowerBody.Substring(nickCommandResponse.Key.Length).Trim();

                if (targetedNickCased == "-r" || targetedNickCased == "--random")
                {
                    // random pick, biased towards active users
                    if (channelNicks.Count == 0)
                    {
                        // emergency trick: target the sender
                        Output(respond, args, nickCommandResponse.Key, nickCommandResponse.Value, args.SenderNickname);
                        return;
                    }

                    Debug.Assert(channelMessage != null);

                    // each message in the last n messages leads to an entry in the pick list
                    // this increases the chances of being picked
                    var pickList = new List <string>();
                    LinkedList <string> lastMessageAuthors;
                    if (ChannelsToLastMessageAuthors.TryGetValue(channelMessage.Channel, out lastMessageAuthors))
                    {
                        foreach (string author in lastMessageAuthors)
                        {
                            if (channelNicks.Contains(author))
                            {
                                pickList.Add(author);
                            }
                        }
                    }
                    pickList.AddRange(channelNicks);

                    int    index  = RNG.Next(channelNicks.Count);
                    string target = pickList[index];
                    Output(respond, args, nickCommandResponse.Key, nickCommandResponse.Value, target);
                    return;
                }
                else if (targetedNickCased == "-R" || targetedNickCased == "--really-random")
                {
                    // random pick of any user in the channel
                    if (channelNicks.Count == 0)
                    {
                        // emergency trick: target the sender
                        Output(respond, args, nickCommandResponse.Key, nickCommandResponse.Value, args.SenderNickname);
                        return;
                    }

                    Debug.Assert(channelMessage != null);

                    int    index  = RNG.Next(channelNicks.Count);
                    string target = channelNicks.ElementAt(index);
                    Output(respond, args, nickCommandResponse.Key, nickCommandResponse.Value, target);
                    return;
                }

                foreach (string channelNick in channelNicks)
                {
                    if (channelNick.ToLowerInvariant() == targetedNick)
                    {
                        // nickname directly from user list
                        Output(respond, args, nickCommandResponse.Key, nickCommandResponse.Value, channelNick);
                        return;
                    }
                }

                // registered nickname?
                var registeredTargetNick = ConnectionManager.RegisteredNameForNick(targetedNick);
                if (registeredTargetNick == null)
                {
                    // nope, targeted nick is not registered
                    return;
                }

                foreach (string channelNick in channelNicks)
                {
                    var registeredChannelNick = ConnectionManager.RegisteredNameForNick(channelNick);
                    if (registeredChannelNick == null)
                    {
                        // this channel nickname is not registered
                        continue;
                    }

                    if (registeredTargetNick == registeredChannelNick)
                    {
                        // registered nicknames match
                        Output(respond, args, nickCommandResponse.Key, nickCommandResponse.Value, channelNick);
                        return;
                    }
                }
            }
        }