def test_say_no_repeat_protection(bot): # five is fine bot.say('hello', '#sopel') bot.say('hello', '#sopel') bot.say('hello', '#sopel') bot.say('hello', '#sopel') bot.say('hello', '#sopel') assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', ) # six: replaced by '...' bot.say('hello', '#sopel') assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', # the extra hello is replaced by '...' 'PRIVMSG #sopel :...', ) # these one will add more '...' bot.say('hello', '#sopel') bot.say('hello', '#sopel') assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :...', # the new ones are also replaced by '...' 'PRIVMSG #sopel :...', 'PRIVMSG #sopel :...', ) # but at some point it just stops talking bot.say('hello', '#sopel') assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', 'PRIVMSG #sopel :hello', # three time, then stop 'PRIVMSG #sopel :...', 'PRIVMSG #sopel :...', 'PRIVMSG #sopel :...', )
def test_call_rule_rate_limited_user(mockbot): items = [] # setup def testrule(bot, trigger): bot.say('hi') items.append(1) return "Return Value" rule_hello = rules.Rule( [re.compile(r'(hi|hello|hey|sup)')], plugin='testplugin', label='testrule', handler=testrule, rate_limit=100, threaded=False, ) # trigger line = ':[email protected] PRIVMSG #channel :hello' pretrigger = trigger.PreTrigger(mockbot.nick, line) # match matches = list(rule_hello.match(mockbot, pretrigger)) match = matches[0] # trigger and wrapper rule_trigger = trigger.Trigger(mockbot.settings, pretrigger, match, account=None) wrapper = bot.SopelWrapper(mockbot, rule_trigger) # call rule mockbot.call_rule(rule_hello, wrapper, rule_trigger) # assert the rule has been executed assert mockbot.backend.message_sent == rawlist('PRIVMSG #channel :hi') assert items == [1] # assert the rule is now rate limited assert rule_hello.is_rate_limited(Identifier('Test')) assert not rule_hello.is_channel_rate_limited('#channel') assert not rule_hello.is_global_rate_limited() # call rule again mockbot.call_rule(rule_hello, wrapper, rule_trigger) # assert no new message assert mockbot.backend.message_sent == rawlist( 'PRIVMSG #channel :hi'), 'There must not be any new message sent' assert items == [1], 'There must not be any new item'
def test_require_bot_privilege(configfactory, botfactory, triggerfactory, ircfactory): settings = configfactory('default.cfg', TMP_CONFIG) mockbot = botfactory.preloaded(settings) mockserver = ircfactory(mockbot) bot = triggerfactory.wrapper(mockbot, BAN_MESSAGE) mockserver.channel_joined('#chan') mockserver.join('Foo', '#chan') mockserver.mode_set('#chan', '+vo', ['Foo', bot.nick]) @plugin.command('ban') @plugin.require_bot_privilege(plugin.VOICE) def mock(bot, trigger): return True assert mock(bot, bot._trigger) is True, ( 'Bot must meet the requirement when having a higher privilege level.') @plugin.command('ban') @plugin.require_bot_privilege(plugin.OP) def mock(bot, trigger): return True assert mock(bot, bot._trigger) is True @plugin.command('ban') @plugin.require_bot_privilege(plugin.OWNER) def mock(bot, trigger): return True assert mock(bot, bot._trigger) is not True assert not bot.backend.message_sent @plugin.command('ban') @plugin.require_bot_privilege(plugin.OWNER, message='Nope') def mock(bot, trigger): return True assert mock(bot, bot._trigger) is not True assert bot.backend.message_sent == rawlist('PRIVMSG #chan :Nope') @plugin.command('ban') @plugin.require_bot_privilege(plugin.OWNER, message='Nope', reply=True) def mock(bot, trigger): return True assert mock(bot, bot._trigger) is not True assert bot.backend.message_sent[1:] == rawlist('PRIVMSG #chan :Foo: Nope')
def test_help_command_unknown(irc, userfactory): user = userfactory('Exirel') irc.pm(user, '.help doesnotexist') assert irc.bot.backend.message_sent == rawlist( "PRIVMSG Exirel :Unknown command \"doesnotexist\"", )
def test_bot_mixed_mode_types(mockbot, ircfactory): """Ensure mixed argument-required and -not-required modes are handled. Sopel 6.6.6 and older did not behave well. .. seealso:: GitHub issue #1575 (https://github.com/sopel-irc/sopel/pull/1575). """ irc = ircfactory(mockbot) irc.channel_joined( '#test', ['Uvoice', 'Uop', 'Uadmin', 'Uvoice2', 'Uop2', 'Uadmin2']) irc.mode_set('#test', '+amov', ['Uadmin', 'Uop', 'Uvoice']) assert mockbot.channels["#test"].privileges[Identifier("Uadmin")] == ADMIN assert mockbot.channels["#test"].privileges[Identifier("Uop")] == OP assert mockbot.channels["#test"].privileges[Identifier("Uvoice")] == VOICE irc.mode_set('#test', '+abov', ['Uadmin2', 'x!y@z', 'Uop2', 'Uvoice2']) assert mockbot.channels["#test"].privileges[Identifier("Uadmin2")] == 0 assert mockbot.channels["#test"].privileges[Identifier("Uop2")] == 0 assert mockbot.channels["#test"].privileges[Identifier("Uvoice2")] == 0 assert mockbot.backend.message_sent == rawlist('WHO #test'), ( 'Upon finding an unexpected nick, the bot must send a WHO request.')
def test_help_command_too_long(mockbot, triggerfactory): provider = providers.Base() provider.setup(mockbot) wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :.help test') mockbot.doc['test'] = ([ 'The command test docstring.', 'Second line of docstring.', 'Third line of docstring.', 'Fourth line of docstring.', ], [ '.test', '.test arg', '.test else', ] ) provider.help_command(wrapper, wrapper._trigger, 'test') assert mockbot.backend.message_sent == rawlist( "PRIVMSG #channel :Test: The help for command test is too long; " "I'm sending it to you in a private message.", "PRIVMSG Test :The command test docstring.", "PRIVMSG Test :Second line of docstring.", "PRIVMSG Test :Third line of docstring.", "PRIVMSG Test :Fourth line of docstring.", "PRIVMSG Test :e.g. .test, .test arg or .test else", )
def test_wrapper_action_override_destination(mockbot, triggerfactory): wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :test message') wrapper.action('Hi!', destination='#different') assert mockbot.backend.message_sent == rawlist( 'PRIVMSG #different :\x01ACTION Hi!\x01')
def test_wrapper_reply_override_destination_reply_to(mockbot, triggerfactory): wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :test message') wrapper.reply('Hi!', destination='#another', reply_to='Admin') assert mockbot.backend.message_sent == rawlist( 'PRIVMSG #another :Admin: Hi!')
def test_wrapper_reply(mockbot, triggerfactory): wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :test message') wrapper.reply('Hi!') assert mockbot.backend.message_sent == rawlist( 'PRIVMSG #channel :Test: Hi!')
def test_ignore_replay_servertime(mockbot): """Test ignoring messages sent before bot joined a channel.""" @plugin.rule("$nickname!") @plugin.thread(False) def ping(bot, trigger): bot.say(trigger.nick + "!") ping.plugin_name = "testplugin" mockbot.register_callables([ping]) test_channel = Identifier("#test") mockbot.channels[test_channel] = target.Channel(test_channel) mockbot.channels[test_channel].join_time = datetime(2021, 6, 1, 12, 0, 0, 15000, tzinfo=timezone.utc) # replay mockbot.on_message( "@time=2021-06-01T12:00:00.010Z :user!user@user PRIVMSG #test :TestBot!" ) assert mockbot.backend.message_sent == [] # new message mockbot.on_message( "@time=2021-06-01T12:00:00.020Z :user2!user2@user PRIVMSG #test :TestBot!" ) assert mockbot.backend.message_sent == rawlist("PRIVMSG #test :user2!")
def test_help_command_too_long_settings(mockbot, triggerfactory): """Test settings can override message length in lines for command help.""" mockbot.settings.help.line_threshold = 5 provider = providers.Base() provider.setup(mockbot) wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :.help test') mockbot.doc['test'] = ([ 'The command test docstring.', 'Second line of docstring.', 'Third line of docstring.', 'Fourth line of docstring.', ], [ '.test', '.test arg', '.test else', ] ) provider.help_command(wrapper, wrapper._trigger, 'test') assert mockbot.backend.message_sent == rawlist( "PRIVMSG #channel :Test: The command test docstring.", "PRIVMSG #channel :Second line of docstring.", "PRIVMSG #channel :Third line of docstring.", "PRIVMSG #channel :Fourth line of docstring.", "PRIVMSG #channel :e.g. .test, .test arg or .test else", )
def test_wrapper_kick_override_destination_message(mockbot, triggerfactory): wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :test message') wrapper.kick('SpamUser', channel='#another', message='Test reason') assert mockbot.backend.message_sent == rawlist( 'KICK #another SpamUser :Test reason')
def test_help(irc, userfactory): user = userfactory('Exirel') irc.pm(user, '.help') assert irc.bot.backend.message_sent[0] == rawlist( "PRIVMSG Exirel :Here is my list of commands:", )[0] assert len(irc.bot.backend.message_sent) > 1, 'More than one line expected'
def test_say_long_truncation_extra(bot): """Test optional truncation indicator with message that is too long.""" text = 'a' * (512 - prefix_length(bot) - len('PRIVMSG #sopel :\r\n') - 3) bot.say(text + 'ttt' + 'b', '#sopel', truncation='...') assert bot.backend.message_sent == rawlist( # 'b' is truncated; 'ttt' is replaced by `truncation` 'PRIVMSG #sopel :%s' % text + '...', )
def test_say_long_extra(bot): """Test a long message that doesn't fit into the 512 bytes limit.""" text = 'a' * (512 - len('PRIVMSG #sopel :\r\n')) bot.say(text + 'b', '#sopel') assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :%s' % text, # the 'b' is truncated out )
def test_on_connect(bot): bot.on_connect() assert bot.backend.message_sent == rawlist( 'CAP LS 302', 'NICK Sopel', 'USER sopel 0 * :Sopel (https://sopel.chat)' )
def test_wrapper_kick(mockbot, triggerfactory): wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :test message') wrapper.kick('SpamUser') assert mockbot.backend.message_sent == rawlist( 'KICK #channel SpamUser' )
def test_wrapper_notice(mockbot, triggerfactory): wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :test message') wrapper.notice('Hi!') assert mockbot.backend.message_sent == rawlist( 'NOTICE #channel :Hi!' )
def test_on_connect_server_auth_password(bot): bot.settings.core.server_auth_method = 'server' bot.settings.core.server_auth_password = '******' bot.on_connect() assert bot.backend.message_sent == rawlist( 'CAP LS 302', 'PASS server_secret', 'NICK Sopel', 'USER sopel 0 * :Sopel (https://sopel.chat)')
def test_say_trailing(bot): """Test optional trailing string.""" text = '"This is a test quote.' bot.say(text, '#sopel', trailing='"') assert bot.backend.message_sent == rawlist( # combined 'PRIVMSG #sopel :%s' % text + '"')
def test_write_args_many(bot): bot.write(['NICK', 'Sopel']) bot.write(['JOIN', '#sopel']) assert bot.backend.message_sent == rawlist( 'NICK Sopel', 'JOIN #sopel', )
def test_write_text_many(bot): bot.write(['NICK', 'Sopel']) bot.write(['HELP'], '?') assert bot.backend.message_sent == rawlist( 'NICK Sopel', 'HELP :?', )
def test_wrapper_notice_override_destination(mockbot, triggerfactory): wrapper = triggerfactory.wrapper( mockbot, ':[email protected] PRIVMSG #channel :test message') wrapper.notice('Hi!', destination='#different') assert mockbot.backend.message_sent == rawlist( 'NOTICE #different :Hi!' )
def test_help_command_channel(irc, userfactory): user = userfactory('Exirel') irc.say(user, '#sopel', '.help help') assert irc.bot.backend.message_sent == rawlist( "PRIVMSG #sopel :Exirel: Generate help for Sopel's commands.", "PRIVMSG #sopel :e.g. .help help or .help", )
def test_say_long_fit(bot): """Test a long message that fits into the 512 bytes limit.""" text = 'a' * (512 - len('PRIVMSG #sopel :\r\n')) bot.say(text, '#sopel') assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :%s' % text, )
def test_say_long_extra_multi_message(bot): """Test a long message that doesn't fit, with split allowed.""" text = 'a' * (512 - prefix_length(bot) - len('PRIVMSG #sopel :\r\n')) bot.say(text + 'b', '#sopel', max_messages=2) assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :%s' % text, # the 'b' is split from message 'PRIVMSG #sopel :b', )
def test_say_long_truncation_fit(bot): """Test optional truncation indicator with message that fits in one line.""" text = 'a' * (512 - prefix_length(bot) - len('PRIVMSG #sopel :\r\n') - 3) bot.say(text + 'ttt', '#sopel', truncation='...') assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel :%s' % text + 'ttt', # nothing is truncated or replaced )
def test_get_reply_method_default_private(mockbot, triggerfactory): provider = providers.Base() wrapped = triggerfactory.wrapper(mockbot, QUERY_LINE) reply, recipient = provider.get_reply_method(wrapped, wrapped._trigger) reply('Test message.', recipient) assert wrapped.backend.message_sent == rawlist( "PRIVMSG Test :Test message.", )
def test_isupinsecure_command(irc, bot, user, requests_mock): """Test working URL.""" requests_mock.head('https://example.com', ) irc.pm(user, '.isupinsecure https://example.com') assert len(bot.backend.message_sent) == 1, ( '.isupinsecure command should output exactly one line') assert bot.backend.message_sent == rawlist( 'PRIVMSG User :[isup] https://example.com looks fine to me.')
def test_say_long_extra_multi_message_multibyte_recipient(bot): """Test a split-allowed message sent to recipient with multi-byte char.""" text = 'a' * (512 - prefix_length(bot) - len('PRIVMSG #sopel² :\r\n'.encode('utf-8'))) bot.say(text + 'b', '#sopel²', max_messages=2) assert bot.backend.message_sent == rawlist( 'PRIVMSG #sopel² :%s' % text, # the 'b' is split from message 'PRIVMSG #sopel² :b', )