Skip to content

Commit 6738a5c

Browse files
authored
Merge pull request #3 from N4GR/main
/orange add-item and asynchronous /profile
2 parents 29764bd + 9dd48f9 commit 6738a5c

File tree

4 files changed

+124
-8
lines changed

4 files changed

+124
-8
lines changed

rinbot/config/database/schema.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ CREATE TABLE IF NOT EXISTS "store" (
2828
"id" INTEGER,
2929
"name" TEXT,
3030
"price" INTEGER,
31-
"type" INTEGER
31+
"type" INTEGER,
32+
"data" BLOB
3233
);
3334
CREATE TABLE IF NOT EXISTS "history_guilds" (
3435
"guild_id" INTEGER,

rinbot/config/localization/en.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,14 @@
393393
"ECONOMY_TRANSFER_EMBED": "Transfered `{value}` to `{receiver}`, current_balance: {wallet}",
394394
"ECONOMY_TRANSFER_SAME_USER": " ❌ You can't transfer to yourself :p",
395395
"ECONOMY_ALREADY_HAS_ITEM": " ❌ You already have this item!",
396+
"ECONOMY_ADD_ITEM_NAME": "add-item",
397+
"ECONOMY_ADD_ITEM_DESC": "An admin only command that's used to add items to the guild store.",
398+
"ECONOMY_ADD_ITEM_CHOICE": "badge",
399+
"ECONOMY_ADD_ITEM_ERROR_SQUARE": ["The image must be a square, your image is", "px wide and", "px tall."],
400+
"ECONOMY_ADD_ITEM_SUCCESS": "✅ Badge Added Successfully",
401+
"ECONOMY_ADD_ITEM_EMBED_BADGE_NAME": "Badge Name",
402+
"ECONOMY_ADD_ITEM_EMBED_PRICE_NAME": "Price",
403+
"ECONOMY_ADD_ITEM_EMBED_LINK_USED_NAME": "Link Used",
396404

397405
"FUN_PET_NAME": "pet",
398406
"FUN_PET_DESC": ":3",

rinbot/extensions/economy.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from rinbot.base import log_exception, is_hex, hex_to_int
1818
from rinbot.base import DBTable
19+
from rinbot.base import DBColumns
1920
from rinbot.base import respond
2021
from rinbot.base import RinBot
2122
from rinbot.base import Colour
@@ -25,6 +26,11 @@
2526
from rinbot.base import is_admin
2627
from rinbot.base import not_blacklisted
2728

29+
# Store packages
30+
from PIL import Image
31+
from io import BytesIO
32+
import aiohttp
33+
2834
class Economy(Cog, name='economy'):
2935
def __init__(self, bot: RinBot) -> None:
3036
self.bot = bot
@@ -284,6 +290,103 @@ async def __remove_currency(self, interaction: Interaction, member: discord.Memb
284290
except Exception as e:
285291
log_exception(e)
286292

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+
287390
# SETUP
288391
async def setup(bot: RinBot):
289392
await bot.add_cog(Economy(bot))

rinbot/extensions/general.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@
3535

3636
# profile packages
3737
from PIL import Image, ImageDraw, ImageFont
38-
import requests
3938
from io import BytesIO
4039
import unicodedata
40+
import aiohttp
4141

4242
class General(Cog, name='general'):
4343
def __init__(self, bot: RinBot) -> None:
@@ -197,8 +197,10 @@ async def _profile(self, interaction: discord.Interaction, visibility: app_comma
197197

198198
avatar_url = interaction.user.avatar.url or interaction.user.default_avatar.url
199199

200-
response = requests.get(avatar_url)
201-
response.raise_for_status()
200+
async with aiohttp.ClientSession() as session:
201+
async with session.get(avatar_url) as response:
202+
if response.status == 200:
203+
response = await response.read()
202204

203205
# Initial images to layer on top of
204206
image = Image.open("rinbot/assets/images/profile/background.jpg").convert("RGBA")
@@ -207,7 +209,7 @@ async def _profile(self, interaction: discord.Interaction, visibility: app_comma
207209
image.paste(overlay, (0, 0), overlay)
208210

209211
# Avatar image handling
210-
avatar = Image.open(BytesIO(response.content)).convert("RGBA").resize((125, 125), Image.Resampling.LANCZOS)
212+
avatar = Image.open(BytesIO(response)).convert("RGBA").resize((125, 125), Image.Resampling.LANCZOS)
211213

212214
width, height = avatar.size
213215
x = (width - height) // 2
@@ -230,10 +232,12 @@ async def _profile(self, interaction: discord.Interaction, visibility: app_comma
230232

231233
emoji_name = unicodedata.name(currency_emoji).lower().replace(" ", "_")
232234

233-
response = requests.get(f"https://emojiapi.dev/api/v1/{emoji_name}/32.png")
234-
response.raise_for_status()
235+
async with aiohttp.ClientSession() as session:
236+
async with session.get(f"https://emojiapi.dev/api/v1/{emoji_name}/32.png") as response:
237+
if response.status == 200:
238+
response = await response.read()
235239

236-
emoji = Image.open(BytesIO(response.content)).convert("RGBA")
240+
emoji = Image.open(BytesIO(response)).convert("RGBA")
237241

238242
image.paste(emoji, (260, 40), emoji)
239243

0 commit comments

Comments
 (0)