diff --git a/lib/discordrb/bot.rb b/lib/discordrb/bot.rb index 72e4f02e6..ac402e1cb 100644 --- a/lib/discordrb/bot.rb +++ b/lib/discordrb/bot.rb @@ -1316,6 +1316,15 @@ def handle_dispatch(type, data) if message.mentions.any? { |user| user.id == @profile.id } event = MentionEvent.new(message, self) + event.role_mention = false + raise_event(event) + end + # Raises a MentionEvent for a bot's managed integration role: + # A managed role is auto-generated for any bots joined to a server with permissions > 0 + # For this to generate an event, set role_managed: true + if message.role_mentions.any? { |role| role.managed? == true && role.tags.bot_id == @profile.id } + event = MentionEvent.new(message, self) + event.role_mention = true raise_event(event) end diff --git a/lib/discordrb/container.rb b/lib/discordrb/container.rb index 5521437f9..82714fdd3 100644 --- a/lib/discordrb/container.rb +++ b/lib/discordrb/container.rb @@ -200,6 +200,7 @@ def playing(attributes = {}, &block) # @option attributes [Time] :after Matches a time after the time the message was sent at. # @option attributes [Time] :before Matches a time before the time the message was sent at. # @option attributes [Boolean] :private Matches whether or not the channel is private. + # @option attributes [Boolean] :allow_role_mention whether the event triggers on bot managed roleid mentions. # @yield The block is executed when the event is raised. # @yieldparam event [MentionEvent] The event that was raised. # @return [MentionEventHandler] the event handler that was registered. diff --git a/lib/discordrb/events/message.rb b/lib/discordrb/events/message.rb index f72446691..d0769659c 100644 --- a/lib/discordrb/events/message.rb +++ b/lib/discordrb/events/message.rb @@ -264,10 +264,92 @@ def after_call(event) end # @see Discordrb::EventContainer#mention - class MentionEvent < MessageEvent; end + class MentionEvent < MessageEvent + attr_accessor :role_mention + + def initialize(message, bot) + @bot = bot + @message = message + @channel = message.channel + @saved_message = '' + @file = nil + @filename = nil + @file_spoiler = nil + @role_mention = false + end + end # Event handler for {MentionEvent} - class MentionEventHandler < MessageEventHandler; end + class MentionEventHandler < MessageEventHandler + def matches?(event) + # Check for the proper event type + return false unless event.is_a? MentionEvent + # Ensure this is not a role mention, or if it is, then allow_role_mention == true + return false unless (!event.role_mention) || (@attributes[:allow_role_mention] && event.role_mention) + + [ + matches_all(@attributes[:starting_with] || @attributes[:start_with], event.content) do |a, e| + case a + when String + e.start_with? a + when Regexp + (e =~ a)&.zero? + end + end, + matches_all(@attributes[:ending_with] || @attributes[:end_with], event.content) do |a, e| + case a + when String + e.end_with? a + when Regexp + !(e =~ Regexp.new("#{a}$")).nil? + end + end, + matches_all(@attributes[:containing] || @attributes[:contains], event.content) do |a, e| + case a + when String + e.include? a + when Regexp + (e =~ a) + end + end, + matches_all(@attributes[:in], event.channel) do |a, e| + case a + when String + # Make sure to remove the "#" from channel names in case it was specified + a.delete('#') == e.name + when Integer + a == e.id + else + a == e + end + end, + matches_all(@attributes[:from], event.author) do |a, e| + case a + when String + a == e.name + when Integer + a == e.id + when :bot + e.current_bot? + else + a == e + end + end, + matches_all(@attributes[:with_text] || @attributes[:content] || @attributes[:exact_text], event.content) do |a, e| + case a + when String + e == a + when Regexp + match = a.match(e) + match ? (e == match[0]) : false + end + end, + matches_all(@attributes[:after], event.timestamp) { |a, e| a > e }, + matches_all(@attributes[:before], event.timestamp) { |a, e| a < e }, + matches_all(@attributes[:private], event.channel.private?) { |a, e| !e == !a } + ].reduce(true, &:&) + end + end # @see Discordrb::EventContainer#pm class PrivateMessageEvent < MessageEvent; end diff --git a/lib/discordrb/version.rb b/lib/discordrb/version.rb index 6f25f6dc2..0b619d931 100644 --- a/lib/discordrb/version.rb +++ b/lib/discordrb/version.rb @@ -3,5 +3,5 @@ # Discordrb and all its functionality, in this case only the version. module Discordrb # The current version of discordrb. - VERSION = '3.5.0' + VERSION = '3.5.1' end diff --git a/spec/bot_spec.rb b/spec/bot_spec.rb index cd7b05f7a..12198a0e3 100644 --- a/spec/bot_spec.rb +++ b/spec/bot_spec.rb @@ -151,7 +151,7 @@ let(:user_id) { instance_double(Integer, 'user_id') } let(:author) { instance_double(Discordrb::User, id: user_id) } let(:message_fixture) { { 'author' => { 'id' => user_id }, 'channel_id' => channel_id } } - let(:message) { instance_double(Discordrb::Message, channel: channel, from_bot?: false, mentions: []) } + let(:message) { instance_double(Discordrb::Message, channel: channel, from_bot?: false, mentions: [], role_mentions: []) } before do allow(bot).to receive(:channel).with(channel_id).and_return(channel)