Add Images command

Clean up Animals command
This commit is contained in:
Michał Gdula 2023-09-08 21:53:33 +01:00
parent 68d638c7ee
commit 4e685393de
12 changed files with 283 additions and 27 deletions

View file

@ -3,19 +3,18 @@ import asyncio
import discord import discord
from discord.ext import commands from discord.ext import commands
from lynxie.config import DISCORD_TOKEN, LYNXIE_PREFIX, LYNXIE_DB from lynxie.config import DISCORD_TOKEN, LYNXIE_PREFIX
from lynxie.commands import Help, Ping, Hello, Music, Animals from lynxie.commands import Help, Ping, Hello, Music, Animals, Img
from lynxie.database import CommandHistory, Database from lynxie.database import CommandHistory, Database
db = Database()
lynxie = commands.Bot( lynxie = commands.Bot(
intents=discord.Intents.all(), intents=discord.Intents.all(),
command_prefix=LYNXIE_PREFIX, command_prefix=LYNXIE_PREFIX,
help_command=None, help_command=None,
) )
db = Database()
@lynxie.event @lynxie.event
async def on_ready(): async def on_ready():
@ -56,8 +55,6 @@ async def on_message_edit(before, after):
f'"{before.content}" --> "{after.content}"' f'"{before.content}" --> "{after.content}"'
) )
# await lynxie.process_commands(after)
async def run(): async def run():
async with lynxie: async with lynxie:
@ -66,6 +63,7 @@ async def run():
await lynxie.add_cog(Hello(lynxie)) await lynxie.add_cog(Hello(lynxie))
await lynxie.add_cog(Music(lynxie)) await lynxie.add_cog(Music(lynxie))
await lynxie.add_cog(Animals(lynxie)) await lynxie.add_cog(Animals(lynxie))
await lynxie.add_cog(Img(lynxie))
await lynxie.start(DISCORD_TOKEN) await lynxie.start(DISCORD_TOKEN)

BIN
lynxie/assets/bubble.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 B

BIN
lynxie/assets/gang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View file

@ -3,6 +3,7 @@ from .ping import Ping
from .hello import Hello from .hello import Hello
from .music import Music from .music import Music
from .animals import Animals from .animals import Animals
from .image import Img
__all__ = [ __all__ = [
"Help", "Help",
@ -10,4 +11,5 @@ __all__ = [
"Hello", "Hello",
"Music", "Music",
"Animals", "Animals",
"Img",
] ]

View file

@ -15,7 +15,6 @@ class Animals(commands.Cog):
@commands.command() @commands.command()
async def animal(self, ctx, animal): async def animal(self, ctx, animal):
animal = animal.lower().strip() or "racc" animal = animal.lower().strip() or "racc"
animal_filename = f"{animal}.png"
if animal not in TINYFOX_ANIMALS: if animal not in TINYFOX_ANIMALS:
await ctx.reply( await ctx.reply(
@ -27,17 +26,16 @@ class Animals(commands.Cog):
return return
async with ctx.typing(): async with ctx.typing():
animal_image_request = requests.get( request = requests.get(f"https://api.tinyfox.dev/img?animal={animal}&json")
f"https://api.tinyfox.dev/img?animal={animal}" animal_image = BytesIO(request.content)
).content
animal_image = BytesIO(animal_image_request)
animal_image.seek(0) animal_image.seek(0)
animal_file = discord.File(animal_image, filename=animal_filename) animal_file = discord.File(animal_image, filename="image.png")
embed = discord.Embed( embed = discord.Embed(
title="Animal", title=animal.capitalize(),
description=f"Here's a random {animal}!",
colour=discord.Colour.orange(), colour=discord.Colour.orange(),
).set_image(url="attachment://" + animal_filename) ).set_image(
url="attachment://image.png"
)
await ctx.reply(embed=embed, file=animal_file, mention_author=False) await ctx.reply(embed=embed, file=animal_file, mention_author=False)

View file

@ -13,7 +13,8 @@ class Help(commands.Cog):
"join": "Join the voice channel you're in", "join": "Join the voice channel you're in",
"play <url>": "Play a song from YouTube, SoundCloud, etc.", "play <url>": "Play a song from YouTube, SoundCloud, etc.",
"stop": "Stop the current song and leave the voice channel", "stop": "Stop the current song and leave the voice channel",
"e621": "Search e621.net", "animal <animal>": "Get a random image of an animal!",
"overlay <style>": "Overlay an image with a style, e.g. `bubble`",
} }
@commands.command() @commands.command()

110
lynxie/commands/image.py Normal file
View file

@ -0,0 +1,110 @@
import os
import requests
from io import BytesIO
import datetime
from PIL import Image
import discord
from discord.ext import commands
from lynxie.config import IMAGE_EXTENSIONS, IMAGE_OVERLAYS, ASSETS_PATH
from lynxie.utils import error_message
class Img(commands.Cog):
def __init__(self, bot):
self.bot = bot
self._overlays = {
"bubble": Image.open(os.path.join(ASSETS_PATH, "bubble.png")).convert("RGBA"),
"gang": Image.open(os.path.join(ASSETS_PATH, "gang.png")).convert("RGBA"),
}
@commands.command()
async def overlay(self, ctx, style: str = None):
start_time = datetime.datetime.now()
style = style.lower().strip() if style else None
# Check if image should be processed
async with ctx.typing():
if not style or style not in IMAGE_OVERLAYS:
error = "That is not a valid option! Valid options are:\n" \
f"`{', '.join(IMAGE_OVERLAYS)}`"
await ctx.reply(embed=error_message(error))
return
if not ctx.message.attachments:
error = "You need to attach an image to use this command!"
await ctx.reply(embed=error_message(error))
return
# Extracts file extension from filename
if not ctx.message.attachments[0].filename.split(".")[-1].lower() in IMAGE_EXTENSIONS:
error = "Unsupported file type! Supported file types are:\n" \
f"`{', '.join(IMAGE_EXTENSIONS)}`"
await ctx.reply(embed=error_message(error))
return
if ctx.message.attachments[0].size > 8_000_000:
error = "That image is too big! Please use an image that is less than 8MB."
await ctx.reply(embed=error_message(error))
return
if (
not 0 < ctx.message.attachments[0].width <= 3500 or
not 0 < ctx.message.attachments[0].height <= 3500
):
error = "Image must be at least 1x1 and under 3500x3500!"
await ctx.reply(embed=error_message(error))
return
# Process image
async with ctx.typing():
response = requests.get(ctx.message.attachments[0].url)
message_attachment = Image.open(BytesIO(response.content))
if message_attachment.width < message_attachment.height:
message_attachment.thumbnail((200, message_attachment.height))
else:
message_attachment.thumbnail((message_attachment.width, 200))
if style == "bubble":
# The bubble is resized twice as for some reason .copy() doesn't work
message_attachment.paste(
self._overlays["bubble"].resize(
(
message_attachment.width,
self._overlays["bubble"].height
)
),
(0, 0),
self._overlays["bubble"].resize(
(
message_attachment.width,
self._overlays["bubble"].height
)
),
)
elif style == "gang":
message_attachment.paste(
self._overlays["gang"],
(
((message_attachment.width - self._overlays["gang"].width) // 2),
(message_attachment.height - self._overlays["gang"].height)
),
self._overlays["gang"]
)
message_file = BytesIO()
message_attachment.save(message_file, format="PNG")
message_file.seek(0)
message_file = discord.File(message_file, filename="image.png")
time_taken = datetime.datetime.now() - start_time
embed = discord.Embed(title=style.capitalize(), colour=discord.Colour.orange())\
.set_image(url="attachment://image.png")\
.set_footer(text=f"{message_attachment.width}x{message_attachment.height}, "
f"{time_taken.microseconds / 1000}ms")
await ctx.reply(embed=embed, file=message_file, mention_author=False)

View file

@ -2,14 +2,18 @@ import os
from discord import Object from discord import Object
from lynxie.utils import get_env_or_error from lynxie.utils import get_env_or_error
DATA_PATH = "data"
LYNXIE_PREFIX = "~"
LYNXIE_DB = f"sqlite:///" + os.path.join(DATA_PATH, "lynxie.db")
DISCORD_GUILD_ID = Object(id=1040757387033849976)
DISCORD_TOKEN = get_env_or_error("DISCORD_TOKEN") DISCORD_TOKEN = get_env_or_error("DISCORD_TOKEN")
DISCORD_GUILD_ID = Object(id=1040757387033849976)
LYNXIE_PREFIX = "~"
DATA_PATH = "data"
ASSETS_PATH = "assets"
DATABASE_URI = f"sqlite:///" + os.path.join(DATA_PATH, "lynxie.db")
# https://tinyfox.dev/docs/
# TODO: Get list from API instead of hardcoding
# https://api.tinyfox.dev/img?animal=animal&json
TINYFOX_ANIMALS = [ TINYFOX_ANIMALS = [
"chi", "chi",
"bear", "bear",
@ -42,3 +46,12 @@ TINYFOX_ANIMALS = [
"tig", "tig",
"woof", "woof",
] ]
IMAGE_EXTENSIONS = [
"png", "jpg", "jpeg", "webp"
]
IMAGE_OVERLAYS = [
"bubble",
"gang",
]

View file

@ -1,6 +1,6 @@
from sqlalchemy import create_engine, Column, Integer, String, DateTime from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.orm import declarative_base, sessionmaker from sqlalchemy.orm import declarative_base, sessionmaker
from lynxie.config import LYNXIE_DB from lynxie.config import DATABASE_URI
Base = declarative_base() Base = declarative_base()
@ -19,7 +19,7 @@ class CommandHistory(Base):
class Database: class Database:
def __init__(self): def __init__(self):
self.engine = create_engine(LYNXIE_DB) self.engine = create_engine(DATABASE_URI)
self.session = sessionmaker(bind=self.engine) self.session = sessionmaker(bind=self.engine)
self.session = self.session() self.session = self.session()

View file

@ -7,8 +7,8 @@ def error_message(error: str) -> discord.Embed:
print("Error: " + error) print("Error: " + error)
embed = discord.Embed( embed = discord.Embed(
title="Error", title="Error :(",
description=f"`{error}`", description=error,
colour=discord.Colour.red(), colour=discord.Colour.red(),
) )
embed.set_footer(text="For more information, use the help command.") embed.set_footer(text="For more information, use the help command.")

134
poetry.lock generated
View file

@ -1010,6 +1010,68 @@ files = [
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
] ]
[[package]]
name = "numpy"
version = "1.25.2"
description = "Fundamental package for array computing in Python"
category = "main"
optional = false
python-versions = ">=3.9"
files = [
{file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"},
{file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"},
{file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"},
{file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"},
{file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"},
{file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"},
{file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"},
{file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"},
{file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"},
{file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"},
{file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"},
{file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"},
{file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"},
{file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"},
{file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"},
{file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"},
{file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"},
{file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"},
{file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"},
{file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"},
{file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"},
{file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"},
{file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"},
{file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"},
{file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"},
]
[[package]]
name = "opencv-python"
version = "4.8.0.76"
description = "Wrapper package for OpenCV python bindings."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "opencv-python-4.8.0.76.tar.gz", hash = "sha256:56d84c43ce800938b9b1ec74b33942b2edbcef3f70c2754eb9bfe5dff1ee3ace"},
{file = "opencv_python-4.8.0.76-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:67bce4b9aad307c98a9a07c6afb7de3a4e823c1f4991d6d8e88e229e7dfeee59"},
{file = "opencv_python-4.8.0.76-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:48eb3121d809a873086d6677565e3ac963e6946110d13cd115533fa70e2aa2eb"},
{file = "opencv_python-4.8.0.76-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93871871b1c9d6b125cddd45b0638a2fa01ee9fd37f5e428823f750e404f2f15"},
{file = "opencv_python-4.8.0.76-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bcb4944211acf13742dbfd9d3a11dc4e36353ffa1746f2c7dcd6a01c32d1376"},
{file = "opencv_python-4.8.0.76-cp37-abi3-win32.whl", hash = "sha256:b2349dc9f97ed6c9ba163d0a7a24bcef9695a3e216cd143e92f1b9659c5d9a49"},
{file = "opencv_python-4.8.0.76-cp37-abi3-win_amd64.whl", hash = "sha256:ba32cfa75a806abd68249699d34420737d27b5678553387fc5768747a6492147"},
]
[package.dependencies]
numpy = [
{version = ">=1.21.2", markers = "python_version >= \"3.10\""},
{version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\""},
{version = ">=1.23.5", markers = "python_version >= \"3.11\""},
{version = ">=1.19.3", markers = "python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\" or python_version >= \"3.9\""},
{version = ">=1.17.0", markers = "python_version >= \"3.7\""},
{version = ">=1.17.3", markers = "python_version >= \"3.8\""},
]
[[package]] [[package]]
name = "outcome" name = "outcome"
version = "1.2.0" version = "1.2.0"
@ -1049,6 +1111,76 @@ files = [
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
] ]
[[package]]
name = "pillow"
version = "10.0.0"
description = "Python Imaging Library (Fork)"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"},
{file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"},
{file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"},
{file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"},
{file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"},
{file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"},
{file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"},
{file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"},
{file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"},
{file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"},
{file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"},
{file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"},
{file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"},
{file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"},
{file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"},
{file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"},
{file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"},
{file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"},
{file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"},
{file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"},
{file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"},
{file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"},
{file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"},
{file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"},
{file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"},
{file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"},
{file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"},
{file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"},
{file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"},
{file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"},
{file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"},
{file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"},
{file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"},
{file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"},
{file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"},
{file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"},
{file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"},
{file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"},
{file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"},
{file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"},
{file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"},
{file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"},
{file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"},
{file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"},
{file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"},
{file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"},
{file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"},
{file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"},
{file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"},
{file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"},
{file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"},
{file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"},
{file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"},
{file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"},
{file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"},
{file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"},
]
[package.extras]
docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "3.10.0" version = "3.10.0"
@ -1640,4 +1772,4 @@ websockets = "*"
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.11" python-versions = "^3.11"
content-hash = "480f46b4d99fbc6001bb3d475ebfbcf1c00259cf16a34058b13819d352598b6f" content-hash = "0cbaf735a961a32de4d9d9c1e6e3b0664ab0bdfb438744cecc1fb817ac36e879"

View file

@ -18,6 +18,8 @@ selenium = "^4.12.0"
webdriver-manager = "^4.0.0" webdriver-manager = "^4.0.0"
flask = "^2.3.3" flask = "^2.3.3"
yt-dlp = "^2023.7.6" yt-dlp = "^2023.7.6"
pillow = "^10.0.0"
opencv-python = "^4.8.0.76"
[build-system] [build-system]