Beispiel #1
0
    async def test_get_all_guilds(self, create_redis_cache):
        guilds = await FactoryBuilder.get_all_guilds_as_list(create_redis_cache)
        assert len(guilds) == 0

        await create_redis_cache.set_guild(Guild(1, Options()))
        guilds = await FactoryBuilder.get_all_guilds_as_list(create_redis_cache)
        assert len(guilds) == 1

        await create_redis_cache.set_guild(Guild(2, Options()))
        guilds = await FactoryBuilder.get_all_guilds_as_list(create_redis_cache)
        assert len(guilds) == 2
        assert guilds == [Guild(1, Options()), Guild(2, Options())]
Beispiel #2
0
    async def test_user_propagate_skip_guild(self, create_core):
        """Tests if the member gets skipped if not 'in guild'"""
        msg = MockedMessage(author_id=1, guild_id=1).to_mock()
        guild = Guild(1, Options)
        guild.members[1] = Member(1, 1, internal_is_in_guild=False)

        payload = await create_core.propagate(msg, guild)

        assert payload == CorePayload(
            member_status=
            "Bypassing message check since the member doesn't seem to be in a guild"
        )
Beispiel #3
0
    async def test_clean_cache_strict_guild(self, create_handler):
        """Tests clean_cache on guilds with strict mode"""
        await create_handler.cache.set_guild(Guild(1))
        assert bool(create_handler.cache.cache)

        await create_handler.clean_cache(strict=True)
        assert not bool(create_handler.cache.cache)

        await create_handler.cache.set_guild(Guild(1, Options(no_punish=True)))
        assert bool(create_handler.cache.cache)

        await create_handler.clean_cache(strict=True)
        assert bool(create_handler.cache.cache)
    async def test_set_get_guild_valid_interval(self,
                                                create_anti_spam_tracker):
        await create_anti_spam_tracker.anti_spam_handler.cache.set_guild(
            Guild(1, Options()))

        result = await create_anti_spam_tracker.anti_spam_handler.cache.get_guild(
            1)
        assert len(result.addons) == 0

        await create_anti_spam_tracker._set_guild_valid_interval(1, 15)
        result = await create_anti_spam_tracker.anti_spam_handler.cache.get_guild(
            1)
        assert len(result.addons) == 1

        get_result = await create_anti_spam_tracker._get_guild_valid_interval(1
                                                                              )
        assert get_result == 15

        # Code coverage to ensure it works within try
        await create_anti_spam_tracker._set_guild_valid_interval(1, 25)
        result = await create_anti_spam_tracker.anti_spam_handler.cache.get_guild(
            1)
        assert len(result.addons) == 1

        get_result = await create_anti_spam_tracker._get_guild_valid_interval(1
                                                                              )
        assert get_result == 25
    async def test_get_guild_data_fails_on_guild_addon(
            self, create_plugin_cache: PluginCache, create_handler):
        """Test the cache raises GuildAddonNotFound"""
        await create_handler.cache.set_guild(Guild(1, Options()))

        with pytest.raises(GuildAddonNotFound):
            await create_plugin_cache.get_guild_data(1)
Beispiel #6
0
    def test_remove_duplicate_count(self, create_core):
        guild = Guild(1)
        member = Member(1, 1)
        member.duplicate_counter = 5
        member.duplicate_channel_counter_dict = {15: 2}

        assert member.duplicate_counter == 5
        assert member.duplicate_channel_counter_dict == {15: 2}

        create_core._remove_duplicate_count(member, guild, 1)
        assert member.duplicate_counter == 4
        assert member.duplicate_channel_counter_dict == {15: 2}

        create_core._remove_duplicate_count(member, guild, 1, 2)
        assert member.duplicate_counter == 2
        assert member.duplicate_channel_counter_dict == {15: 2}

        guild.options.per_channel_spam = True

        create_core._remove_duplicate_count(member, guild, 15)
        assert member.duplicate_counter == 2
        assert member.duplicate_channel_counter_dict == {15: 1}

        create_core._remove_duplicate_count(member, guild, 1)
        assert member.duplicate_counter == 2
        assert member.duplicate_channel_counter_dict == {15: 1}
Beispiel #7
0
    async def test_propagate_warn_only(self, create_core):
        member = Member(1, 1)
        await create_core.cache.set_member(member)
        create_core._increment_duplicate_count(member, Guild(1), 1, 15)
        guild = await create_core.cache.get_guild(1)

        create_core.options.warn_only = True
        return_data = await create_core.propagate_user(
            MockedMessage(guild_id=1, author_id=1).to_mock(), guild)
        assert return_data == CorePayload(
            member_should_be_punished_this_message=True,
            member_status="Member was warned",
            member_was_warned=True,
            member_warn_count=1,
            member_duplicate_count=15,
        )

        # Test embed coverage
        create_core.options.guild_log_warn_message = {"title": "test"}
        return_data = await create_core.propagate_user(
            MockedMessage(guild_id=1, author_id=1, message_id=2).to_mock(),
            guild)
        assert return_data == CorePayload(
            member_should_be_punished_this_message=True,
            member_status="Member was warned",
            member_was_warned=True,
            member_warn_count=2,
            member_duplicate_count=16,
        )
Beispiel #8
0
    def test_calculate_ratio_edge_case(self, create_core):
        """Tests calculate ratios correctly marks an edge case as spam

        See:
        https://mystb.in/HarderTournamentsPrimary.properties

        Previously it would not mark all "Spam tho" as spam when it should have
        """
        member = Member(1, 1)
        member.messages = [
            Message(1, 1, 1, 1, "This is a test", datetime.datetime.now()),
            Message(2, 1, 1, 1, "Heres another message",
                    datetime.datetime.now()),
            Message(3, 1, 1, 1, "Spam tho", datetime.datetime.now()),
            Message(4, 1, 1, 1, "Spam tho", datetime.datetime.now()),
            Message(5, 1, 1, 1, "Spam tho", datetime.datetime.now()),
        ]
        message = Message(6, 1, 1, 1, "Spam tho", datetime.datetime.now())

        create_core._calculate_ratios(message, member, Guild(1))

        assert message.is_duplicate is True
        assert member.messages[0].is_duplicate is False
        assert member.messages[1].is_duplicate is False
        assert member.messages[2].is_duplicate is True
        assert member.messages[3].is_duplicate is True
        assert member.messages[4].is_duplicate is True
Beispiel #9
0
 def test_increment_duplicate_existing(self, create_core):
     """Tests the count increments even when already existing"""
     member = Member(1, 1, duplicate_channel_counter_dict={5: 1})
     g = Guild(1)
     g.options.per_channel_spam = True
     create_core._increment_duplicate_count(member, g, 5)
     assert member.duplicate_channel_counter_dict[5] == 2
Beispiel #10
0
    async def add_guild_log_channel(self, log_channel: int,
                                    guild_id: int) -> None:
        """
        Registers a log channel on a guild internally

        Parameters
        ----------
        log_channel : int
            The channel id you wish to use for logging
        guild_id : int
            The id of the guild to store this on

        Notes
        -----
        Not setting a log channel means it will
        not send any punishment messages
        """
        if not isinstance(log_channel, int):
            raise ValueError("Expected log_channel with correct type")

        try:
            guild = await self.cache.get_guild(guild_id=guild_id)
            guild.log_channel_id = log_channel
        except GuildNotFound:
            guild = Guild(
                id=guild_id,
                options=self.options,
                log_channel_id=log_channel,
            )
            await self.cache.set_guild(guild)
Beispiel #11
0
    def test_calculate_ratios_does_nothing(self, create_core):
        """Tests the loop does nothing on different messages"""
        member = Member(1,
                        1,
                        messages=[Message(1, 2, 3, 4, "Hello I am the world")])

        create_core._calculate_ratios(Message(2, 2, 3, 4, "My name is Ethan!"),
                                      member, Guild(1))
Beispiel #12
0
    async def set_guild(self, guild: Guild) -> None:
        log.debug("Attempting to set Guild(id=%s)", guild.id)
        # Store members separate
        for member in guild.members.values():
            await self.set_member(member)

        guild.members = [member.id for member in guild.members.values()]
        as_json = json.dumps(asdict(guild, recurse=True))
        await self.redis.set(f"GUILD:{guild.id}", as_json)
Beispiel #13
0
    async def test_get_member(self, create_memory_cache):
        await create_memory_cache.set_guild(Guild(1, Options()))
        with pytest.raises(MemberNotFound):
            await create_memory_cache.get_member(1, 1)

        create_memory_cache.cache[1].members[1] = 2

        val = await create_memory_cache.get_member(1, 1)
        assert val == 2
Beispiel #14
0
    async def test_save_to_dict(self, create_handler: AntiSpamHandler):
        await create_handler.save_to_dict()

        await create_handler.cache.set_guild(Guild(1, Options()))
        data = await create_handler.save_to_dict()
        with open("tests/raw.json", "r") as file:
            stored_data = json.load(file)

        assert data == stored_data
Beispiel #15
0
    async def set_guild(self, guild: Guild) -> None:
        log.debug("Attempting to set Guild(id=%s)", guild.id)
        # Since self.members exists
        members: List[Member] = list(guild.members.values())
        guild.members = {}

        iters = [self.set_member(m) for m in members]
        await asyncio.gather(*iters)
        await self.guilds.upsert({"id": guild.id}, asdict(guild, recurse=True))
Beispiel #16
0
    async def test_add_message_filled_guild(self, create_redis_cache):
        """Test with an existing guild"""
        await create_redis_cache.set_guild(Guild(3, Options()))
        await create_redis_cache.add_message(Message(1, 2, 3, 4, "Content"))

        r_1 = await create_redis_cache.get_member(4, 3)
        r_2 = await create_redis_cache.get_guild(3)
        assert len(r_2.members) == 1
        assert len(r_1.messages) == 1
Beispiel #17
0
    async def test_set_guild(self, create_mongo_cache):
        with pytest.raises(GuildNotFound):
            await create_mongo_cache.get_guild(2)

        set_guild = Guild(2, log_channel_id=12345)
        await create_mongo_cache.set_guild(set_guild)

        r_1 = await create_mongo_cache.get_guild(2)
        assert isinstance(r_1, Guild)
        assert r_1 == set_guild
Beispiel #18
0
    async def test_remove_guild_log_channel(self, create_handler: AntiSpamHandler):
        await create_handler.remove_guild_log_channel(1)  # shouldnt raise

        await create_handler.cache.set_guild(Guild(1, Options(), log_channel_id=1))
        result = await create_handler.cache.get_guild(1)
        assert result.log_channel_id == 1

        await create_handler.remove_guild_log_channel(1)
        result = await create_handler.cache.get_guild(1)
        assert result.log_channel_id is None
Beispiel #19
0
 async def test_punish_member(self, create_dpy_lib_handler):
     """Adds test coverage"""
     await create_dpy_lib_handler.punish_member(
         MockedMessage(author_id=1, guild_id=1).to_mock(),
         Member(1, 1),
         Guild(1, Options()),
         "test user",
         "test guild",
         True,
     )
Beispiel #20
0
    async def test_get_member(self, create_redis_cache):
        await create_redis_cache.set_guild(Guild(1, Options()))
        with pytest.raises(MemberNotFound):
            await create_redis_cache.get_member(1, 1)

        await create_redis_cache.set_member(Member(1, 1))

        val = await create_redis_cache.get_member(1, 1)
        assert val
        assert isinstance(val, Member)
Beispiel #21
0
    async def test_set_member(self, create_memory_cache):
        await create_memory_cache.set_member(Member(1, 1))
        await create_memory_cache.set_member(Member(2, 1))

        assert len(create_memory_cache.cache[1].members) == 2

        await create_memory_cache.set_guild(Guild(1, Options()))
        assert len(create_memory_cache.cache[1].members) == 0

        await create_memory_cache.set_member(Member(1, 1))
        assert len(create_memory_cache.cache[1].members) == 1
Beispiel #22
0
    def test_calculate_ratios_raises(self, create_core):
        member = Member(
            1,
            1,
            messages=[Message(1, 2, 3, 4, "One"),
                      Message(2, 2, 3, 4, "Two")])

        m = Message(1, 2, 3, 4, "One")
        m.creation_time = member.messages[0].creation_time
        with pytest.raises(DuplicateObject):
            create_core._calculate_ratios(m, member, Guild(1))
Beispiel #23
0
    async def test_get_guild(self, create_redis_cache):
        with pytest.raises(GuildNotFound):
            await create_redis_cache.get_guild(1)

        create_redis_cache.redis.cache["GUILD:1"] = json.dumps(
            asdict(Guild(1), recurse=True)
        )

        val = await create_redis_cache.get_guild(1)
        assert val
        assert isinstance(val, Guild)
Beispiel #24
0
    def create_guild_from_dict(guild_data: dict) -> Guild:
        guild: Guild = Guild(id=guild_data["id"],
                             options=Options(**guild_data["options"]))

        for member in guild_data["members"]:
            guild.members[
                member["id"]] = FactoryBuilder.create_member_from_dict(member)

        log.info("Created Guild(id=%s) from dict", guild.id)

        return guild
Beispiel #25
0
    async def test_basic_timeout_func(self, create_core):
        create_core.handler.lib_handler = Nextcord(create_core.handler)

        g = Guild(1, options=Options(use_timeouts=True))
        member = Member(1, 1, duplicate_counter=5)  # Force a punishment
        g.members[member.id] = member
        await create_core.cache.set_guild(g)

        r_1 = await create_core.propagate(
            MockedMessage(author_id=1, guild_id=1).to_mock(), g)
        assert r_1.member_was_timed_out is True
        assert r_1.member_should_be_punished_this_message is True
Beispiel #26
0
    async def test_punish_member_raises(self, create_dpy_lib_handler):
        with pytest.raises(MissingGuildPermissions):
            # Test kick has kick perms
            message = MockedMessage(author_id=1, guild_id=1).to_mock()
            message.guild.me.guild_permissions.kick_members = False
            await create_dpy_lib_handler.punish_member(
                message,
                Member(1, 1),
                Guild(1, Options()),
                "test user",
                "test guild",
                True,
            )

        with pytest.raises(MissingGuildPermissions):
            # Test ban has ban perms
            message = MockedMessage(author_id=1, guild_id=1).to_mock()
            message.guild.me.guild_permissions.ban_members = False
            await create_dpy_lib_handler.punish_member(
                message,
                Member(1, 1),
                Guild(1, Options()),
                "test user",
                "test guild",
                False,
            )

        with pytest.raises(MissingGuildPermissions):
            # Check errors on guild owner
            message = MockedMessage(author_id=1, guild_id=1).to_mock()
            message.guild.owner_id = 1

            await create_dpy_lib_handler.punish_member(
                message,
                Member(1, 1),
                Guild(1, Options()),
                "test user",
                "test guild",
                True,
            )
Beispiel #27
0
    async def test_delete_member(self, create_memory_cache):
        await create_memory_cache.delete_member(1, 2)
        await create_memory_cache.set_guild(Guild(2))
        await create_memory_cache.delete_member(1, 2)

        guild = await create_memory_cache.get_guild(2)
        guild.members[1] = Member(1, 2)
        await create_memory_cache.set_guild(guild)
        assert len(guild.members) == 1

        await create_memory_cache.delete_member(1, 2)
        g = await create_memory_cache.get_guild(2)
        assert len(g.members) == 0
Beispiel #28
0
    def test_calculate_ratios(self, create_core):
        member = Member(1, 1)
        member.messages = [
            Message(1, 1, 1, 1, "Hello world", datetime.datetime.now())
        ]
        message = Message(2, 1, 1, 1, "Hello world", datetime.datetime.now())

        assert member.duplicate_counter == 1

        create_core._calculate_ratios(message, member, Guild(1))

        assert member.duplicate_counter == 2
        assert message.is_duplicate is True
Beispiel #29
0
    def test_get_duplicate_count(self, create_core):
        guild = Guild(1)
        member = Member(1, 1)
        member.duplicate_counter = 5
        member.duplicate_channel_counter_dict = {15: 2}

        assert create_core._get_duplicate_count(member, guild, 1) == 5

        guild.options.per_channel_spam = True

        assert create_core._get_duplicate_count(member, guild) == 1
        assert create_core._get_duplicate_count(member, guild, 5) == 1
        assert create_core._get_duplicate_count(member, guild, 15) == 2
Beispiel #30
0
    async def add_guild_options(self, guild_id: int, options: Options) -> None:
        """
        Set a guild's options to a custom set, rather then the base level
        set used and defined in ASH initialization

        Warnings
        --------
        If using/modifying ``AntiSpamHandler.options`` to give to
        this method you will **also** be modifying the overall options.

        To get an options item you can modify freely call :py:meth:`antispam.AntiSpamHandler.get_options`
        this method will give you an instance of the current options you are
        free to modify however you like.

        Notes
        =====
        This will override any current settings, if you wish
        to continue using existing settings and merely change some
        I suggest using the ``get_options`` method first and then giving
        those values back to this method with the changed arguments
        """
        if not isinstance(options, Options):
            raise ValueError("Expected options of type Options")

        try:
            guild = await self.cache.get_guild(guild_id=guild_id)
        except GuildNotFound:
            log.warning(
                "I cannot ensure I have permissions to kick/ban ban people in Guild(id=%s)",
                guild_id,
            )
            guild = Guild(id=guild_id, options=options)
            await self.cache.set_guild(guild)
            log.info("Created Guild(id=%s)", guild.id)
        else:
            guild.options = options

        log.info("Set custom options for guild(%s)", guild_id)