import discord
import feedparser
import hashlib
+import io
import logging
+import math
import os
import pexpect
import random
import re
import sys
+from PIL import Image
dryrun = os.getenv('DRYRUN') is not None
return True
return False
+def delta_avatar(url):
+ # Get Delta images.
+ bg = Image.open('DELTA-BG.png')
+ fg = Image.open('DELTA-FURRYTEMPLATE.png')
+ if not bg or not fg:
+ log.warning("Can't open Delta foreground and/or background image!")
+ return None
+ cutoff = bg.width / 2
+
+ # Get provided image.
+ fd = open_url(url)
+ if fd is None:
+ log.debug('Failed to open URL {} for avatar creation'.format(url))
+ return None
+ try:
+ image = Image.open(fd)
+ except:
+ log.warning('Failed to get image from {}'.format(url))
+ return None
+ fd.close()
+ if image is None:
+ return None
+
+ # Crop square.
+ box = None
+ if image.height > image.width:
+ top = math.floor((image.height - image.width) / 2)
+ box = 0, top, image.width - 1, top + image.width - 1
+ elif image.height < image.width:
+ left = math.floor((image.width - image.height) / 2)
+ box = left, 0, left + image.height - 1, image.height - 1
+ if box is not None:
+ cropped = image.crop(box)
+ image = cropped.copy()
+
+ # Scale leaving space for background.
+ if image.height > cutoff:
+ image.thumbnail((cutoff, cutoff))
+ elif image.height < cutoff:
+ width = image.width * 2
+ height = image.height * 2
+ bg.thumbnail((width, height))
+ fg.thumbnail((width, height))
+
+ # Pad with blank pixels.
+ padded = Image.new(image.mode, fg.size)
+ left = math.floor((padded.width - image.width) / 2)
+ top = math.floor((padded.height - image.height) / 2)
+ padded.paste(image, (left, top, left + image.width, top + image.height))
+
+ # Merge them.
+ result = Image.alpha_composite(Image.alpha_composite(bg, padded), fg)
+ b = io.BytesIO()
+ result.save(b, 'PNG')
+ return b.getvalue()
+
@asyncio.coroutine
-def do_admin(message, command, raw):
- result = yield from is_admin(message.server, message.author)
- if not result:
- yield from not_admin(message)
- return
+def do_commands(message, command, raw, non_admin):
+ if not non_admin:
+ result = yield from is_admin(message.server, message.author)
+ if not result:
+ yield from not_admin(message)
+ return
- log.debug('Admin command: {}'.format(raw))
+ log.debug('Command: {}'.format(raw))
if command == 'avatar':
# avatar
yield from client.edit_profile(avatar = fd.read())
fd.close()
+ elif command == 'bling':
+ # bling
+ url = None
+ m = re.match(r'\bbling\s+(\S+)', raw.lower())
+ if m is not None:
+ url = m.group(1)
+ elif len(message.attachments):
+ url = message.attachments[0]['url']
+ if url is None:
+ log.debug('No URL for avatar to Deltaify')
+ yield from say(message.channel, 'zzz')
+ return
+ yield from client.send_typing(message.channel)
+ data = delta_avatar(url)
+ if data is None:
+ yield from say(message.channel, 'yelp!')
+ return
+ yield from client.send_file(message.channel, data, filename = message.author.name + '.png', content = message.author.mention if not message.channel.is_private else 'purr')
+
elif command == 'debug':
# debug
m = re.match(r'\bdebug\s+(o(?:ff|n))\b', raw.lower())
modules = {
'admin': {
- 'fn': do_admin,
+ 'fn': do_commands,
'args': [],
'commands': ['avatar', 'debug', 'delete', 'rss']
},
+ 'any': {
+ 'fn': do_commands,
+ 'args': [True],
+ 'commands': ['bling']
+ },
'edi': {
'fn': do_edi,
'args': [p],