import discord from discord.ext import commands from PIL import Image from PIL import ImageOps from PIL import ImageDraw from PIL import ImageFont import asyncio, aiohttp, io, time, imghdr, os, json, textwrap, re class Profile: """ Profile card setup and display """ def __init__(self, client, config): self.client = client self.config = config @commands.group(pass_context=True) async def profile(self, ctx): """Profile command ( see 'sudo help profile' for more info )""" if ctx.invoked_subcommand is None: await ctx.send('Invalid profile command passed... Send `sudo help profile` for assistance.') @profile.command(pass_context=True) async def get(self, ctx, user : discord.Member = None): """Get a user profile card. Passing no arguments returns requesters card""" if user == None: user = ctx.message.author name = user.name userid = user.id avatar = user.avatar_url def_avatar = user.default_avatar_url created = user.created_at nick = user.display_name discr = user.discriminator roles = user.roles roleImages = {} for x, role in enumerate(roles): try: roleImages[role.name] = Image.open('data/images/roles/small/{}.png'.format(role.name.lower())) except Exception as e: next if avatar == '': async with aiohttp.ClientSession() as session: async with session.get(def_avatar) as r: image = await r.content.read() else: async with aiohttp.ClientSession() as session: async with session.get(avatar) as r: image = await r.content.read() with open('data/users/avatars/{}.png'.format(user.id), 'wb') as f: f.write(image) checked = False while checked == False: checks = 0 isImage = imghdr.what('data/users/avatars/{}.png'.format(user.id)) if checks > 4: checked = True if isImage != 'None': checked = True else: checks += 1 av = Image.open('data/users/avatars/{}.png'.format(user.id)) userAvatar = av.resize((128,128), resample=Image.BILINEAR).convert('RGBA') maxsize = ( 800, 500 ) try: bg = Image.open('data/users/backgrounds/{0}.png'.format(user.id)) bg_width, bg_height = bg.size bg = ImageOps.fit(bg,maxsize) except: bg = Image.open('data/images/background_default.png') fontFace = 'data/fonts/{}'.format(self.config['fonts']['normal']) fontFace_bold = 'data/fonts/{}'.format(self.config['fonts']['bold']) fontSize = 18 descSize = 12 headerSize = 32 header_font = ImageFont.truetype(fontFace_bold, headerSize) font = ImageFont.truetype(fontFace, fontSize) desc_font = ImageFont.truetype(fontFace, descSize) font_bold = font = ImageFont.truetype(fontFace_bold, fontSize) cardbg = Image.new('RGBA', (800, 500), (255,255,255,255)) d = ImageDraw.Draw(cardbg) d.rectangle([(0,0), 800,500], fill=(255,255,255,255)) cardbg.paste(bg, (0,0)) cardfg = Image.new('RGBA', (800, 500), (255,255,255,0)) dd = ImageDraw.Draw(cardfg) # Info Box Top dd.rectangle([(200,60),(740,191)], fill=(255,255,255,224)); dd.rectangle([(200,60),(740,134)], fill=(255,255,255,255)); # Avatar box dd.rectangle([(60,60),(191,191)], fill=(80,80,80, 255)); cardfg.paste(userAvatar, (62,62)); # Profile Information dd.text((210, 64), nick, fill=(74, 144, 226, 255), font=header_font); dd.text((210, 106), '@' + name + '#' + discr, fill=(74, 144, 226, 255), font=font); # Roles for idy, ii in enumerate(roleImages): startx = int((270 - (30 * len(roleImages))) / 2); cardfg.paste(roleImages[ii], (337 + startx + (30 * idy),152), roleImages[ii]); #Info Box Bottom dd.rectangle([(60,200),(740,450)], fill=(255,255,255,224)); answers = None; questions = self.config["profile_questions"]; try: with open('data/users/profiles/{}.dat'.format(userid)) as f: answers = json.load(f); except Exception as e: pass if (answers != None): for key, quest in zip(sorted(answers),questions): if(int(key) < 5): dd.text((80, 260 + ((int(key)-1) * 48)), textwrap.fill(quest,50) + "\n" + textwrap.fill(answers[key],50), fill=(74, 144, 226, 255), font=desc_font); else: dd.text((410, 260 + ((int(key)-6) * 48)), textwrap.fill(quest,50) + "\n" + textwrap.fill(answers[key],50), fill=(74, 144, 226, 255), font=desc_font); card = Image.new('RGBA', (800, 500), (255,255,255,255)); card = Image.alpha_composite(card,cardbg); card = Image.alpha_composite(card,cardfg); s = 'data/users/cards/{0}.png'.format(user.id); card.save(s, 'png'); with open('data/users/cards/{0}.png'.format(user.id), 'rb') as g: return await ctx.message.channel.send(file=discord.File(g)); @profile.command(pass_context=True) async def setup(self, ctx): """Set your user profile card.""" await ctx.send('Sending a PM to setup profile card.') questions = self.config["profile_questions"] answers = {} recipient = ctx.message.author await recipient.send("Hello! I'm here to help you set up your profile. I will ask you a few questions that you may answer. If you don't want to answer the question, you may reply with 'skip' to move on.") for x, question in enumerate(questions): await recipient.send(question) def check(m): try: return m.channel.recipient.id == recipient.id and m.author.id == recipient.id except: return False answer = await self.client.wait_for('message', check=check) if answer.content.lower() == 'skip': answers[x] = 'N/A' else: answers[x] = answer.content with open('data/users/profiles/{}.dat'.format(recipient.id), 'w', encoding='utf8') as f: json.dump(answers, f) return await recipient.send('You have completed your profile setup') @profile.command(pass_context=True) async def wallpaper(self, ctx, *, url=""): """Set a profile card background image. Can either be a link to an image or an attachment.""" try: background = ctx.message.attachments[0].url except: background = url if (background == ""): return await ctx.send('```Image or URL not found.```') user = ctx.message.author async with aiohttp.ClientSession() as session: async with session.get(background) as r: image = await r.content.read() with open('data/users/backgrounds/{0}.png'.format(user.id),'wb') as f: f.write(image) isImage = imghdr.what('data/users/backgrounds/{0}.png'.format(user.id)) if(isImage == 'png' or isImage == 'jpeg' or isImage == 'jpg' or isImage == 'gif'): f.close() return await ctx.send('```Successfully set profile wallpaper```') else: f.close() os.remove('data/users/backgrounds/{0}.png'.format(user.id)) return await ctx.send('```Something went wrong when setting your wallpaper. Perhaps the file you sent wasn\'t an image?```') def setup(client): client.add_cog(Profile(client, client.config))