/// <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); }
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)); }
/// <summary> /// Combines two <see cref="MessageMatcher"/> instances and returns success if both match. /// 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 And(this MessageMatcher left, MessageMatcher right) => new AndMatcher(left, right);
/// <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);
/// <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);
/// <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);
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); }