|
16 | 16 |
|
17 | 17 | from rinbot.base import log_exception, is_hex, hex_to_int
|
18 | 18 | from rinbot.base import DBTable
|
| 19 | +from rinbot.base import DBColumns |
19 | 20 | from rinbot.base import respond
|
20 | 21 | from rinbot.base import RinBot
|
21 | 22 | from rinbot.base import Colour
|
|
25 | 26 | from rinbot.base import is_admin
|
26 | 27 | from rinbot.base import not_blacklisted
|
27 | 28 |
|
| 29 | +# Store packages |
| 30 | +from PIL import Image |
| 31 | +from io import BytesIO |
| 32 | +import aiohttp |
| 33 | + |
28 | 34 | class Economy(Cog, name='economy'):
|
29 | 35 | def __init__(self, bot: RinBot) -> None:
|
30 | 36 | self.bot = bot
|
@@ -284,6 +290,103 @@ async def __remove_currency(self, interaction: Interaction, member: discord.Memb
|
284 | 290 | except Exception as e:
|
285 | 291 | log_exception(e)
|
286 | 292 |
|
| 293 | + @orange.command( |
| 294 | + name = text["ECONOMY_ADD_ITEM_NAME"], |
| 295 | + description = text["ECONOMY_ADD_ITEM_DESC"]) |
| 296 | + @app_commands.choices(type = [ |
| 297 | + app_commands.Choice(name = text["ECONOMY_ADD_ITEM_CHOICE"], value = 0), |
| 298 | + ]) |
| 299 | + @not_blacklisted() |
| 300 | + @is_admin() |
| 301 | + # @is_owner() |
| 302 | + async def _add_item(self, interaction: Interaction, type: app_commands.Choice[int], name: str, price: int, link: str) -> None: |
| 303 | + await interaction.response.defer(thinking = True) |
| 304 | + |
| 305 | + async def fail_embed(desc): |
| 306 | + embed = discord.Embed( |
| 307 | + description = f"❌ {desc}", |
| 308 | + color = Colour.RED |
| 309 | + ) |
| 310 | + |
| 311 | + await interaction.followup.send(embed = embed, ephemeral = True) |
| 312 | + |
| 313 | + async def fetch_content(url): |
| 314 | + async with aiohttp.ClientSession() as session: |
| 315 | + async with session.get(url) as response: |
| 316 | + if response.status == 200: |
| 317 | + return await response.read() |
| 318 | + else: |
| 319 | + return False |
| 320 | + |
| 321 | + async def is_image_bytes(content): |
| 322 | + try: |
| 323 | + with Image.open(BytesIO(content)) as img: |
| 324 | + img.verify() # Verify that it is an image |
| 325 | + return True |
| 326 | + except (IOError, SyntaxError) as e: |
| 327 | + return False |
| 328 | + |
| 329 | + content = await fetch_content(link) |
| 330 | + |
| 331 | + # Checks if there's a response |
| 332 | + if content is False: |
| 333 | + await fail_embed(f"The link you sent isn't valid!\n\nYou sent:\n{link}") |
| 334 | + return |
| 335 | + # Checks if the response contains an image |
| 336 | + elif await is_image_bytes(content) is False: |
| 337 | + await fail_embed(f"You didn't send a direct image!\n\nYou sent:\n{link}") |
| 338 | + return |
| 339 | + |
| 340 | + # Opens the badge image in Pillow |
| 341 | + badge = Image.open(BytesIO(content)).convert("RGBA") |
| 342 | + |
| 343 | + # Checks if the image is a square |
| 344 | + if badge.width != badge.height: |
| 345 | + await fail_embed(f"{text['ECONOMY_ADD_ITEM_ERROR_SQUARE'][0]} {badge.width}{text['ECONOMY_ADD_ITEM_ERROR_SQUARE'][1]} {badge.height}{text['ECONOMY_ADD_ITEM_ERROR_SQUARE'][2]}") |
| 346 | + return |
| 347 | + |
| 348 | + # Resizes the image to a 64x64 |
| 349 | + badge = badge.resize((64, 64), resample = Image.Resampling.LANCZOS) |
| 350 | + |
| 351 | + # Getting image blob object |
| 352 | + with BytesIO() as buffer: |
| 353 | + badge.save(buffer, format = "PNG") |
| 354 | + imagebytes = buffer.getvalue() |
| 355 | + |
| 356 | + guild_badge_vault = self.bot.db.get(DBTable.STORE, f"{DBColumns.store.GUILD_ID.value} = {interaction.guild.id}") |
| 357 | + |
| 358 | + # Counts how many items are in the store to set as ID and checks if the blob is already there or not. |
| 359 | + counter = 0 |
| 360 | + for id in await guild_badge_vault: |
| 361 | + counter =+ 1 |
| 362 | + if imagebytes == id[5]: |
| 363 | + await fail_embed(f"The image you requested to add is already in the guild store!") |
| 364 | + return |
| 365 | + |
| 366 | + # Adds the badge to the guild store with the id set to max id number + 1 |
| 367 | + await self.bot.db.put(DBTable.STORE, { |
| 368 | + "guild_id": interaction.guild.id, |
| 369 | + "id": counter + 1, |
| 370 | + "name": name, |
| 371 | + "price": price, |
| 372 | + "type": type.value, |
| 373 | + "data": imagebytes |
| 374 | + }) |
| 375 | + |
| 376 | + # Success message |
| 377 | + embed = discord.Embed( |
| 378 | + title = text["ECONOMY_ADD_ITEM_SUCCESS"], |
| 379 | + color = Colour.GREEN |
| 380 | + ) |
| 381 | + |
| 382 | + embed.add_field(name = text["ECONOMY_ADD_ITEM_EMBED_BADGE_NAME"], value = name, inline = True) |
| 383 | + embed.add_field(name = text["ECONOMY_ADD_ITEM_EMBED_PRICE_NAME"], value = str(price), inline = True) |
| 384 | + embed.add_field(name = text["ECONOMY_ADD_ITEM_EMBED_LINK_USED_NAME"], value = link, inline = False) |
| 385 | + embed.set_image(url = link) |
| 386 | + embed.set_footer(text = f"{interaction.guild.name.upper()} | {interaction.guild.id}") |
| 387 | + |
| 388 | + await interaction.followup.send(embed = embed, ephemeral = True) |
| 389 | + |
287 | 390 | # SETUP
|
288 | 391 | async def setup(bot: RinBot):
|
289 | 392 | await bot.add_cog(Economy(bot))
|
0 commit comments