Example #1
0
        /// <summary>
        /// Sets up a listener on the defined channelId types (see <paramref name="hubs"/>) that the bot is a member of. The <paramref name="handler"/>
        /// is executed when an incoming message matches the given <paramref name="match"/>.
        /// Messages in <see cref="HubType.Channel"/> and <see cref="HubType.Group"/> are expected to
        /// contain the name of the bot before the handler  will fire.
        /// </summary>
        /// <param name="match">Defines when to execute this handler</param>
        /// <param name="hubs">The Slack channels to listen on</param>
        /// <param name="modes">Configuration options</param>
        /// <param name="handler">Function to be run when a message matches</param>
        /// <returns></returns>
        public IWhenHandler When(MessageMatcher match, HubType hubs, Modes modes, Func <IConversation, Task> handler)
        {
            bool MessageAddressesBot(Message msg) =>
            (modes & Modes.ObserveAllMessages) == Modes.ObserveAllMessages ||
            msg.Text.Contains(this.state.BotUserId, StringComparison.OrdinalIgnoreCase) ||
            msg.Text.Contains(this.state.BotUsername, StringComparison.OrdinalIgnoreCase);

            var whenHandler = new WhenHandler(this,
                                              msg =>
            {
                if (msg.User != null && msg.User.Equals(this.state.BotUserId))
                {
                    return(MessageMatcher.NoMatch);
                }

                var messageHubType = this.state.GetHubById(msg.Channel).HubType;
                if ((hubs & messageHubType) != messageHubType)
                {
                    return(MessageMatcher.NoMatch);
                }

                if (messageHubType != HubType.DirectMessage)
                {
                    if (!MessageAddressesBot(msg))
                    {
                        return(MessageMatcher.NoMatch);
                    }
                }

                match.SetupLogger(this.config.LoggerFactory);

                return(match.GetMatches(msg));
            },
                                              async(msg, matches) =>
            {
                var modesCopy = modes;

                // Conversation being initiated from another thread? force threaded mode
                if (msg.RawThreadTimestamp != null)
                {
                    modesCopy |= Modes.StartThread;
                }

                using (var conversation = new Conversation(this, modesCopy, msg, matches))
                {
                    try
                    {
                        await handler(conversation);
                        return(true, null);
                    }
                    catch (Exception ex)
                    {
                        return(false, ex);
                    }
                }
            });

            this.whenHandlers.Enqueue(whenHandler);
            return(whenHandler);
        }
Example #2
0
        public async Task <IReply> WaitForReply(MessageMatcher match = null, Action <Message> onNotMatch = null)
        {
            if (this.tokenSource.IsCancellationRequested)
            {
                return(null);
            }

            // msg.User == this.rootMessage.User

            bool MessageRepliesToThread(Message msg) => this.IsThreaded && msg.RawThreadTimestamp != null && (msg.RawThreadTimestamp == this.rootMessage.ChannelTimestamp || msg.RawThreadTimestamp == this.rootMessage.RawThreadTimestamp);
            bool MessageRepliesInChannel(Message msg) => !this.IsThreaded && msg.User == this.rootMessage.User;

            Match[] matches = null;

            var reply = await this.bot.Linger <Message>(msg =>
            {
                bool preconditionsMatch = msg.Channel == this.rootMessage.Channel &&
                                          this.MessageAddressesBot(msg) &&
                                          (MessageRepliesToThread(msg) || MessageRepliesInChannel(msg));

                if (!preconditionsMatch)
                {
                    return(false);
                }

                if (match == null)
                {
                    return(true);
                }

                var(matchSuccess, results) = this.MessageMatches(msg, match).GetAwaiter().GetResult();
                matches = results;

                if (!matchSuccess)
                {
                    onNotMatch?.Invoke(msg);
                }

                return(matchSuccess);
            });

            if (this.tokenSource.IsCancellationRequested)
            {
                return(null);
            }

            // flip to threaded?
            if (!this.IsThreaded && reply.RawThreadTimestamp != null)
            {
                this.modes      |= Modes.StartThread;
                this.rootMessage = reply;
            }

            return(new Reply(
                       this.bot.State.GetUser(reply.User),
                       reply.Text,
                       matches));
        }
Example #3
0
 /// <summary>
 /// Combines two <see cref="MessageMatcher"/> instances and returns success if both match.
 /// The <c>&amp;&amp;</c> operator is the same as using this matcher.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <returns></returns>
 public static MessageMatcher And(this MessageMatcher left, MessageMatcher right)
 => new AndMatcher(left, right);
Example #4
0
 /// <summary>
 /// Combines two <see cref="MessageMatcher"/> instances and returns success if either one matches.
 /// The <c>||</c> operator is the same as using this matcher.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <returns></returns>
 public static MessageMatcher Or(this MessageMatcher left, MessageMatcher right)
 => new OrMatcher(left, right);
Example #5
0
 /// <summary>
 /// Sets up a listener on all Slack channels that the bot is a member of. The <paramref name="handler"/>
 /// is executed when an incoming message matches the given <paramref name="match"/>.
 /// Messages in <see cref="HubType.Channel"/> and <see cref="HubType.Group"/> are expected to
 /// contain the name of the bot before the handler  will fire.
 /// </summary>
 /// <param name="match">Defines when to execute this handler</param>
 /// <param name="modes">Configuration options</param>
 /// <param name="handler">Function to be run when a message matches</param>
 /// <returns></returns>
 public IWhenHandler When(MessageMatcher match, Modes modes, Func <IConversation, Task> handler)
 => this.When(match, HubType.All, modes, handler);
Example #6
0
 /// <summary>
 /// Sets up a listener on the defined channelId types (see <paramref name="hubs"/>) that the bot is a member of. The <paramref name="handler"/>
 /// is executed when an incoming message matches the given <paramref name="match"/>.
 /// Messages in <see cref="HubType.Channel"/> and <see cref="HubType.Group"/> are expected to
 /// contain the name of the bot before the handler  will fire.
 /// </summary>
 /// <param name="match">Defines when to execute this handler</param>
 /// <param name="hubs">The Slack channels to listen on</param>
 /// <param name="handler">Function to be run when a message matches</param>
 /// <returns></returns>
 public IWhenHandler When(MessageMatcher match, HubType hubs, Func <IConversation, Task> handler)
 => this.When(match, hubs, Modes.None, handler);
Example #7
0
        private async Task <(bool success, Match[] matches)> MessageMatches(Message msg, MessageMatcher matcher)
        {
            if (matcher == null)
            {
                return(true, null);
            }

            var matches = await matcher.GetMatches(msg);

            bool success = matches != null && matches.Sum(m => m.Score) >= 0;

            if (!success)
            {
                return(false, null);
            }

            return(true, matches);
        }