@@ -11,6 +11,7 @@ from utils import (
|
|||||||
SPLIT_TOKEN,
|
SPLIT_TOKEN,
|
||||||
FilterLevel,
|
FilterLevel,
|
||||||
should_allow_spoiler,
|
should_allow_spoiler,
|
||||||
|
is_image_gif,
|
||||||
)
|
)
|
||||||
|
|
||||||
MAX_RANDOM_TRIES = 100
|
MAX_RANDOM_TRIES = 100
|
||||||
@@ -20,7 +21,9 @@ class History:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.messages = []
|
self.messages = []
|
||||||
|
|
||||||
async def to_string_image(self, *, type: str, spoiler: FilterLevel) -> List[str]:
|
async def to_string_image(
|
||||||
|
self, *, type: str, spoiler: FilterLevel, gif_only: bool
|
||||||
|
) -> List[str]:
|
||||||
if len(self.messages) == 0:
|
if len(self.messages) == 0:
|
||||||
return ["There was no messages matching your filters"]
|
return ["There was no messages matching your filters"]
|
||||||
message = None
|
message = None
|
||||||
@@ -32,8 +35,9 @@ class History:
|
|||||||
while real_message is None and index < len(self.messages):
|
while real_message is None and index < len(self.messages):
|
||||||
message = self.messages[index]
|
message = self.messages[index]
|
||||||
real_message = await message.fetch()
|
real_message = await message.fetch()
|
||||||
if real_message is not None and not should_allow_spoiler(
|
if real_message is not None and (
|
||||||
real_message, spoiler
|
not should_allow_spoiler(real_message, spoiler)
|
||||||
|
or (gif_only and not is_image_gif(real_message))
|
||||||
):
|
):
|
||||||
real_message = None
|
real_message = None
|
||||||
index += 1
|
index += 1
|
||||||
@@ -44,8 +48,9 @@ class History:
|
|||||||
while real_message is None and index < len(self.messages):
|
while real_message is None and index < len(self.messages):
|
||||||
message = self.messages[index]
|
message = self.messages[index]
|
||||||
real_message = await message.fetch()
|
real_message = await message.fetch()
|
||||||
if real_message is not None and not should_allow_spoiler(
|
if real_message is not None and (
|
||||||
real_message, spoiler
|
not should_allow_spoiler(real_message, spoiler)
|
||||||
|
or (gif_only and not is_image_gif(real_message))
|
||||||
):
|
):
|
||||||
real_message = None
|
real_message = None
|
||||||
index += 1
|
index += 1
|
||||||
@@ -56,8 +61,9 @@ class History:
|
|||||||
while real_message is None and tries < MAX_RANDOM_TRIES:
|
while real_message is None and tries < MAX_RANDOM_TRIES:
|
||||||
message = random.choice(self.messages)
|
message = random.choice(self.messages)
|
||||||
real_message = await message.fetch()
|
real_message = await message.fetch()
|
||||||
if real_message is not None and not should_allow_spoiler(
|
if real_message is not None and (
|
||||||
real_message, spoiler
|
not should_allow_spoiler(real_message, spoiler)
|
||||||
|
or (gif_only and not is_image_gif(real_message))
|
||||||
):
|
):
|
||||||
real_message = None
|
real_message = None
|
||||||
tries += 1
|
tries += 1
|
||||||
|
|||||||
+5
-13
@@ -2,10 +2,10 @@ from typing import Optional, Union, Any
|
|||||||
import discord
|
import discord
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from utils import is_extension, serialize
|
from utils import (
|
||||||
|
serialize,
|
||||||
IMAGE_FORMAT = [".gif", ".gifv", ".png", ".jpg", ".jpeg", ".bmp"]
|
has_image,
|
||||||
EMBED_IMAGES = ["image", "gifv"]
|
)
|
||||||
|
|
||||||
|
|
||||||
class MessageLog:
|
class MessageLog:
|
||||||
@@ -36,15 +36,7 @@ class MessageLog:
|
|||||||
self.image = False
|
self.image = False
|
||||||
self.attachment = len(message.attachments) > 0
|
self.attachment = len(message.attachments) > 0
|
||||||
self.embed = len(message.embeds) > 0
|
self.embed = len(message.embeds) > 0
|
||||||
for attachment in message.attachments:
|
self.image = has_image(message)
|
||||||
if is_extension(attachment.filename, IMAGE_FORMAT):
|
|
||||||
self.image = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
for embed in message.embeds:
|
|
||||||
if embed.type in EMBED_IMAGES:
|
|
||||||
self.image = True
|
|
||||||
break
|
|
||||||
self.reactions = {}
|
self.reactions = {}
|
||||||
elif isinstance(message, dict):
|
elif isinstance(message, dict):
|
||||||
self.id = int(message["id"])
|
self.id = int(message["id"])
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ emojis.load_emojis()
|
|||||||
|
|
||||||
bot = Bot(
|
bot = Bot(
|
||||||
"Discord Analyst",
|
"Discord Analyst",
|
||||||
"1.15",
|
"1.15.1",
|
||||||
alias="%",
|
alias="%",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class FirstScanner(HistoryScanner):
|
|||||||
"first",
|
"first",
|
||||||
"Read first message (add text to filter like %find)",
|
"Read first message (add text to filter like %find)",
|
||||||
args=[
|
args=[
|
||||||
"image - pull an image instead of a message",
|
"image/gif - pull an image instead of a message",
|
||||||
"spoiler:allow/only - allow spoiler images",
|
"spoiler:allow/only - allow spoiler images",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -24,7 +24,7 @@ class FirstScanner(HistoryScanner):
|
|||||||
async def get_results(self, intro: str) -> List[str]:
|
async def get_results(self, intro: str) -> List[str]:
|
||||||
if self.images_only:
|
if self.images_only:
|
||||||
return await self.history.to_string_image(
|
return await self.history.to_string_image(
|
||||||
type="first", spoiler=self.spoiler
|
type="first", spoiler=self.spoiler, gif_only=self.gif_only
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return self.history.to_string(type="first")
|
return self.history.to_string(type="first")
|
||||||
|
|||||||
@@ -15,7 +15,16 @@ class HistoryScanner(Scanner, ABC):
|
|||||||
def __init__(self, *, help: str):
|
def __init__(self, *, help: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
has_digit_args=True,
|
has_digit_args=True,
|
||||||
valid_args=["all", "everyone", "spoiler", "spoiler:allow", "spoiler:only"],
|
valid_args=[
|
||||||
|
"all",
|
||||||
|
"everyone",
|
||||||
|
"spoiler",
|
||||||
|
"spoiler:allow",
|
||||||
|
"spoiler:only",
|
||||||
|
"image",
|
||||||
|
"img",
|
||||||
|
"gif",
|
||||||
|
],
|
||||||
help=help,
|
help=help,
|
||||||
intro_context="",
|
intro_context="",
|
||||||
all_args=True,
|
all_args=True,
|
||||||
@@ -24,7 +33,8 @@ class HistoryScanner(Scanner, ABC):
|
|||||||
async def init(self, message: discord.Message, *args: str) -> bool:
|
async def init(self, message: discord.Message, *args: str) -> bool:
|
||||||
self.history = History()
|
self.history = History()
|
||||||
self.all_messages = "all" in args or "everyone" in args
|
self.all_messages = "all" in args or "everyone" in args
|
||||||
self.images_only = "image" in args
|
self.images_only = "image" in args or "img" in args or "gif" in args
|
||||||
|
self.gif_only = "gif" in args
|
||||||
if "spoiler" in args or "spoiler:allow" in args:
|
if "spoiler" in args or "spoiler:allow" in args:
|
||||||
self.spoiler = FilterLevel.ALLOW
|
self.spoiler = FilterLevel.ALLOW
|
||||||
elif "spoiler:only" in args:
|
elif "spoiler:only" in args:
|
||||||
@@ -80,13 +90,14 @@ class HistoryScanner(Scanner, ABC):
|
|||||||
and (message.content or message.attachment)
|
and (message.content or message.attachment)
|
||||||
and (not images_only or message.image)
|
and (not images_only or message.image)
|
||||||
):
|
):
|
||||||
content = message.content.lower()
|
if not images_only:
|
||||||
for query in queries:
|
content = message.content.lower()
|
||||||
if query[1] is not None:
|
for query in queries:
|
||||||
if not re.match(query[1], message.content):
|
if query[1] is not None:
|
||||||
|
if not re.match(query[1], message.content):
|
||||||
|
return False
|
||||||
|
elif not query[0] in content:
|
||||||
return False
|
return False
|
||||||
elif not query[0] in content:
|
|
||||||
return False
|
|
||||||
impacted = True
|
impacted = True
|
||||||
history.messages += [message]
|
history.messages += [message]
|
||||||
return impacted
|
return impacted
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class LastScanner(HistoryScanner):
|
|||||||
"last",
|
"last",
|
||||||
"Read last message (add text to filter like %find)",
|
"Read last message (add text to filter like %find)",
|
||||||
args=[
|
args=[
|
||||||
"image - pull an image instead of a message",
|
"image/gif - pull an image instead of a message",
|
||||||
"spoiler:allow/only - allow spoiler images",
|
"spoiler:allow/only - allow spoiler images",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -23,6 +23,8 @@ class LastScanner(HistoryScanner):
|
|||||||
|
|
||||||
async def get_results(self, intro: str) -> List[str]:
|
async def get_results(self, intro: str) -> List[str]:
|
||||||
if self.images_only:
|
if self.images_only:
|
||||||
return await self.history.to_string_image(type="last", spoiler=self.spoiler)
|
return await self.history.to_string_image(
|
||||||
|
type="last", spoiler=self.spoiler, gif_only=self.gif_only
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return self.history.to_string(type="last")
|
return self.history.to_string(type="last")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class RandomScanner(HistoryScanner):
|
|||||||
"rand",
|
"rand",
|
||||||
"Read a random message (add text to filter like %find)",
|
"Read a random message (add text to filter like %find)",
|
||||||
args=[
|
args=[
|
||||||
"image - pull an image instead of a message",
|
"image/gif - pull an image instead of a message",
|
||||||
"spoiler:allow/only - allow spoiler images",
|
"spoiler:allow/only - allow spoiler images",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -24,7 +24,7 @@ class RandomScanner(HistoryScanner):
|
|||||||
async def get_results(self, intro: str) -> List[str]:
|
async def get_results(self, intro: str) -> List[str]:
|
||||||
if self.images_only:
|
if self.images_only:
|
||||||
return await self.history.to_string_image(
|
return await self.history.to_string_image(
|
||||||
type="random", spoiler=self.spoiler
|
type="random", spoiler=self.spoiler, gif_only=self.gif_only
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return self.history.to_string(type="random")
|
return self.history.to_string(type="random")
|
||||||
|
|||||||
+40
-15
@@ -60,6 +60,26 @@ class FilterLevel(IntEnum):
|
|||||||
SPLIT_TOKEN = 1152317803
|
SPLIT_TOKEN = 1152317803
|
||||||
|
|
||||||
|
|
||||||
|
# FILE
|
||||||
|
|
||||||
|
IMAGE_FORMAT = [".png", ".jpg", ".jpeg", ".bmp"]
|
||||||
|
EMBED_IMAGES = ["image"]
|
||||||
|
|
||||||
|
GIF_FORMAT = [".gif", ".gifv"]
|
||||||
|
EMBED_GIF = ["gifv"]
|
||||||
|
|
||||||
|
|
||||||
|
def is_extension(filepath: str, ext_list: List[str]) -> bool:
|
||||||
|
filename, file_extension = os.path.splitext(filepath.lower())
|
||||||
|
return file_extension in ext_list
|
||||||
|
|
||||||
|
|
||||||
|
def get_resource_path(filename: str) -> str:
|
||||||
|
return os.path.realpath(
|
||||||
|
os.path.join(os.path.dirname(__file__), "..", "resources", filename)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# DISCORD API
|
# DISCORD API
|
||||||
|
|
||||||
|
|
||||||
@@ -100,11 +120,30 @@ class FakeMessage:
|
|||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
|
|
||||||
|
def has_image(message: discord.Message) -> bool:
|
||||||
|
for attachment in message.attachments:
|
||||||
|
if is_extension(attachment.filename, GIF_FORMAT + IMAGE_FORMAT):
|
||||||
|
return True
|
||||||
|
for embed in message.embeds:
|
||||||
|
if embed.type in (EMBED_IMAGES + EMBED_GIF):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_image_spoiler(message: discord.Message) -> bool:
|
def is_image_spoiler(message: discord.Message) -> bool:
|
||||||
if len(message.attachments) > 0:
|
if len(message.attachments) > 0:
|
||||||
return message.attachments[0].is_spoiler()
|
return message.attachments[0].is_spoiler()
|
||||||
elif len(message.embeds) > 0:
|
elif len(message.embeds) > 0:
|
||||||
return re.match(r"||[^|]*http[^|]||", message.content.lower()) is not None
|
return re.match(r"\|\|[^|]*http[^|]\|\|", message.content.lower()) is not None
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_image_gif(message: discord.Message) -> bool:
|
||||||
|
if len(message.attachments) > 0:
|
||||||
|
return is_extension(message.attachments[0].filename, GIF_FORMAT)
|
||||||
|
elif len(message.embeds) > 0:
|
||||||
|
return message.embeds[0].type in EMBED_GIF
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -119,20 +158,6 @@ def should_allow_spoiler(message: discord.Message, spoiler: FilterLevel) -> bool
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# FILE
|
|
||||||
|
|
||||||
|
|
||||||
def is_extension(filepath: str, ext_list: List[str]) -> bool:
|
|
||||||
filename, file_extension = os.path.splitext(filepath.lower())
|
|
||||||
return file_extension in ext_list
|
|
||||||
|
|
||||||
|
|
||||||
def get_resource_path(filename: str) -> str:
|
|
||||||
return os.path.realpath(
|
|
||||||
os.path.join(os.path.dirname(__file__), "..", "resources", filename)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# LISTS
|
# LISTS
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user