From a8b1ede9627736058ff3b7876d92ce447a0f86fd Mon Sep 17 00:00:00 2001 From: Klemek Date: Wed, 19 May 2021 15:11:29 +0200 Subject: [PATCH] spoiler filtering --- src/data_types/history.py | 26 +++++++++++++++++++++++--- src/scanners/first_scanner.py | 9 +++++++-- src/scanners/history_scanner.py | 9 ++++++++- src/scanners/last_scanner.py | 7 +++++-- src/scanners/random_scanner.py | 9 +++++++-- src/utils/utils.py | 19 +++++++++++++++++++ 6 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/data_types/history.py b/src/data_types/history.py index 5354bde..8a23925 100644 --- a/src/data_types/history.py +++ b/src/data_types/history.py @@ -3,16 +3,24 @@ import random # Custom libs -from utils import mention, from_now, str_datetime, message_link, SPLIT_TOKEN +from utils import ( + mention, + from_now, + str_datetime, + message_link, + SPLIT_TOKEN, + FilterLevel, + should_allow_spoiler, +) -MAX_RANDOM_TRIES = 10 +MAX_RANDOM_TRIES = 100 class History: def __init__(self): self.messages = [] - async def to_string_image(self, *, type: str) -> List[str]: + async def to_string_image(self, *, type: str, spoiler: FilterLevel) -> List[str]: if len(self.messages) == 0: return ["There was no messages matching your filters"] message = None @@ -24,6 +32,10 @@ class History: while real_message is None and index < len(self.messages): message = self.messages[index] real_message = await message.fetch() + if real_message is not None and not should_allow_spoiler( + real_message, spoiler + ): + real_message = None index += 1 intro = f"First image out of {len(self.messages):,}" elif type == "last": @@ -32,6 +44,10 @@ class History: while real_message is None and index < len(self.messages): message = self.messages[index] real_message = await message.fetch() + if real_message is not None and not should_allow_spoiler( + real_message, spoiler + ): + real_message = None index += 1 intro = f"Last image out of {len(self.messages):,}" elif type == "random": @@ -40,6 +56,10 @@ class History: while real_message is None and tries < MAX_RANDOM_TRIES: message = random.choice(self.messages) real_message = await message.fetch() + if real_message is not None and not should_allow_spoiler( + real_message, spoiler + ): + real_message = None tries += 1 if real_message is None: diff --git a/src/scanners/first_scanner.py b/src/scanners/first_scanner.py index a75f23c..ba7622b 100644 --- a/src/scanners/first_scanner.py +++ b/src/scanners/first_scanner.py @@ -12,7 +12,10 @@ class FirstScanner(HistoryScanner): return generate_help( "first", "Read first message (add text to filter like %find)", - args=["image - pull an image instead of a message"], + args=[ + "image - pull an image instead of a message", + "spoiler:allow/only - allow spoiler images", + ], ) def __init__(self): @@ -20,6 +23,8 @@ class FirstScanner(HistoryScanner): async def get_results(self, intro: str) -> List[str]: if self.images_only: - return await self.history.to_string_image(type="first") + return await self.history.to_string_image( + type="first", spoiler=self.spoiler + ) else: return self.history.to_string(type="first") diff --git a/src/scanners/history_scanner.py b/src/scanners/history_scanner.py index 52f2507..aecf5a5 100644 --- a/src/scanners/history_scanner.py +++ b/src/scanners/history_scanner.py @@ -8,13 +8,14 @@ import re from .scanner import Scanner from data_types import History from logs import ChannelLogs, MessageLog +from utils import FilterLevel class HistoryScanner(Scanner, ABC): def __init__(self, *, help: str): super().__init__( has_digit_args=True, - valid_args=["all", "everyone"], + valid_args=["all", "everyone", "spoiler", "spoiler:allow", "spoiler:only"], help=help, intro_context="", all_args=True, @@ -24,6 +25,12 @@ class HistoryScanner(Scanner, ABC): self.history = History() self.all_messages = "all" in args or "everyone" in args self.images_only = "image" in args + if "spoiler" in args or "spoiler:allow" in args: + self.spoiler = FilterLevel.ALLOW + elif "spoiler:only" in args: + self.spoiler = FilterLevel.ONLY + else: + self.spoiler = FilterLevel.NONE if not self.images_only: self.queries = [ ( diff --git a/src/scanners/last_scanner.py b/src/scanners/last_scanner.py index 718af8b..055217e 100644 --- a/src/scanners/last_scanner.py +++ b/src/scanners/last_scanner.py @@ -12,7 +12,10 @@ class LastScanner(HistoryScanner): return generate_help( "last", "Read last message (add text to filter like %find)", - args=["image - pull an image instead of a message"], + args=[ + "image - pull an image instead of a message", + "spoiler:allow/only - allow spoiler images", + ], ) def __init__(self): @@ -20,6 +23,6 @@ class LastScanner(HistoryScanner): async def get_results(self, intro: str) -> List[str]: if self.images_only: - return await self.history.to_string_image(type="last") + return await self.history.to_string_image(type="last", spoiler=self.spoiler) else: return self.history.to_string(type="last") diff --git a/src/scanners/random_scanner.py b/src/scanners/random_scanner.py index d761efe..42d4488 100644 --- a/src/scanners/random_scanner.py +++ b/src/scanners/random_scanner.py @@ -12,7 +12,10 @@ class RandomScanner(HistoryScanner): return generate_help( "rand", "Read a random message (add text to filter like %find)", - args=["image - pull an image instead of a message"], + args=[ + "image - pull an image instead of a message", + "spoiler:allow/only - allow spoiler images", + ], ) def __init__(self): @@ -20,6 +23,8 @@ class RandomScanner(HistoryScanner): async def get_results(self, intro: str) -> List[str]: if self.images_only: - return await self.history.to_string_image(type="random") + return await self.history.to_string_image( + type="random", spoiler=self.spoiler + ) else: return self.history.to_string(type="random") diff --git a/src/utils/utils.py b/src/utils/utils.py index 2fd7413..a2e7c40 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -100,6 +100,25 @@ class FakeMessage: self.id = id +def is_image_spoiler(message: discord.Message) -> bool: + if len(message.attachments) > 0: + return message.attachments[0].is_spoiler() + elif len(message.embeds) > 0: + return re.match(r"||[^|]*http[^|]||", message.content.lower()) is not None + else: + return False + + +def should_allow_spoiler(message: discord.Message, spoiler: FilterLevel) -> bool: + is_spoiler = is_image_spoiler(message) + return ( + not is_spoiler + and spoiler <= FilterLevel.ALLOW + or is_spoiler + and spoiler >= FilterLevel.ALLOW + ) + + # FILE