Skip to content

Instantly share code, notes, and snippets.

@Vexs
Created July 12, 2017 02:34
Show Gist options
  • Save Vexs/e97f19ade750e042c9eefa44e0bab785 to your computer and use it in GitHub Desktop.
Save Vexs/e97f19ade750e042c9eefa44e0bab785 to your computer and use it in GitHub Desktop.
An caching avatar logger for discord.py
import discord
from discord.ext import commands
import aiohttp
from PIL import Image
import io
import asyncio
from itertools import zip_longest
async def build_avatar_cache(self):
with aiohttp.ClientSession() as session:
members = list(self.bot.get_all_members())
# splits up members into chunks of 10 members at once for building up asyncio.groups
for count, member_list in enumerate(list(zip_longest(*[iter(members)] * 10, fillvalue=None))):
print(count * 10)
async def task(session, member):
url = 'https://cdn.discordapp.com/avatars/{0.id}/{0.avatar}.jpeg?size=64'.format(member)
async with session.get(url) as resp:
return member.id, await resp.read()
task_list = []
for member in member_list:
if member and member.avatar_url:
task_list.append(task(session, member))
responses = await asyncio.gather(*task_list, loop=self.bot.loop)
for member_id, response in responses:
self.avatars[member_id] = response
print('done loading avatars! Loaded {} avatars!'.format(len(self.avatars.keys())))
self.cache_ready = True
def format_avatar_change(before, after):
with Image.open(io.BytesIO(before)).convert('RGBA') as before, Image.open(io.BytesIO(after)).convert(
'RGBA') as after:
output_image = Image.new('RGBA', (132, 64))
output_image.paste(before, (0, 0))
output_image.paste(after, (69, 0))
image_file_object = io.BytesIO()
output_image.save(image_file_object, format='PNG')
image_file_object.seek(0)
return image_file_object
class AvatarLogger:
""""""
def __init__(self, bot):
self.bot = bot
self.avatars = {}
self.bot.loop.create_task(build_avatar_cache(self))
self.session = aiohttp.ClientSession()
with open('default_avatar.png', 'rb') as f:
self.default_avatar = f.read()
self.cache_ready = False
async def update_member_avatar(self, member):
url = 'https://cdn.discordapp.com/avatars/{0.id}/{0.avatar}.jpeg?size=64'.format(member)
async with self.session.get(url) as resp:
self.avatars[member.id] = await resp.read()
#@commands.command(pass_context=True)
#async def test_add(self, ctx, member: discord.Member):
# with aiohttp.ClientSession() as session:
# url = 'https://cdn.discordapp.com/avatars/{0.id}/{0.avatar}.jpeg?size=64'.format(member)
# async with session.get(url) as resp:
# self.avatars[member.id] = await resp.read()
# await self.bot.say('added {} to the avatar list'.format(member.display_name))
#
#@commands.command(pass_context=True)
#async def test_image(self, ctx):
# with Image.open(io.BytesIO(self.avatars[ctx.message.author.id])).convert('RGBA') as avatar:
# imagefileobject = io.BytesIO()
# avatar.save('avatar.png', format='PNG')
# avatar.save(imagefileobject, format='PNG')
# imagefileobject.seek(0)
# await self.bot.send_file(ctx.message.channel, fp=imagefileobject, filename='avatar.png')
#
#@commands.command(pass_context=True)
#async def test_update(self, ctx, member: discord.Member):
# url = 'https://cdn.discordapp.com/avatars/{0.id}/{0.avatar}.jpeg?size=64'.format(member)
# async with self.session.get(url) as resp:
# after_avatar = await resp.read()
# image_file_object = await self.bot.loop.run_in_executor(None, format_avatar_change, self.avatars[member.id],
# after_avatar)
# await self.bot.send_file(ctx.message.channel, fp=image_file_object, filename='avatar.png')
async def on_member_update(self, before, after):
if not self.cache_ready:
return
if before.avatar == after.avatar:
return
if not before.avatar_url or before.id not in self.avatars.keys():
before_avatar = self.default_avatar
else:
before_avatar = self.avatars[before.id]
if not after.avatar_url:
after_avatar = self.default_avatar
else:
url = 'https://cdn.discordapp.com/avatars/{0.id}/{0.avatar}.jpeg?size=64'.format(after)
async with self.session.get(url) as resp:
after_avatar = await resp.read()
image_file_object = await self.bot.loop.run_in_executor(None, format_avatar_change, before_avatar, after_avatar)
await self.bot.send_file(discord.Object(id='273199762872991744'), fp=image_file_object,
filename='avatar_change.png',
content='{} ID: {} updated their avatar!'.format(before.display_name, before.id))
await self.update_member_avatar(after)
async def on_member_join(self, member):
await self.update_member_avatar(member)
async def on_member_remove(self, member):
self.avatars.pop(member.id)
def __unload(self):
self.session.close()
self.default_avatar.close()
def setup(bot):
bot.add_cog(AvatarLogger(bot))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment