blueprints.users: add user avatars

- images: add IconManager.update
 - images: delete all other converted extension variants when deleting
This commit is contained in:
Luna Mendes 2018-11-13 21:52:50 -03:00
parent aaeca125ef
commit 49aa6cd495
4 changed files with 66 additions and 28 deletions

View File

@ -205,18 +205,9 @@ async def _update_guild(guild_id):
if 'icon' in j:
# delete old
old_icon_hash = await app.db.fetchval("""
SELECT icon
FROM guilds
WHERE id = $1
""", guild_id)
old_icon = await app.icons.get_guild_icon(
guild_id, old_icon_hash)
await app.icons.delete(old_icon)
new_icon = await put_guild_icon(guild_id, j['icon'])
new_icon = await app.icons.update(
'guild', guild_id, j['icon']
)
await app.db.execute("""
UPDATE guilds

View File

@ -1,5 +1,5 @@
from os.path import splitext
from quart import Blueprint, current_app as app, send_file
from quart import Blueprint, current_app as app, send_file, request
bp = Blueprint('images', __name__)
@ -20,11 +20,13 @@ def splitext_(filepath):
return name, ext.strip('.')
@bp.route('/emojis/<int:emoji_id>.<ext>', methods=['GET'])
async def _get_raw_emoji(emoji_id: int, ext: str):
@bp.route('/emojis/<emoji_file>', methods=['GET'])
async def _get_raw_emoji(emoji_file):
# emoji = app.icons.get_emoji(emoji_id, ext=ext)
# just a test file for now
return await send_file('./LICENSE')
emoji_id, ext = splitext_(emoji_file)
return await send_icon(
'emoji', emoji_id, emoji_id, ext=ext)
@bp.route('/icons/<int:guild_id>/<icon_file>', methods=['GET'])
@ -43,9 +45,13 @@ async def _get_default_user_avatar(discrim: int):
pass
@bp.route('/avatars/<int:user_id>/<avatar_hash>.<ext>')
async def _get_user_avatar(user_id, avatar_hash, ext):
return await send_icon('user', user_id, avatar_hash, ext=ext)
@bp.route('/avatars/<int:user_id>/<avatar_file>')
async def _get_user_avatar(user_id, avatar_file):
# size_int = int(request.args.get('size', '1024'))
# siz = (size_int, size_int)
avatar_hash, ext = splitext_(avatar_file)
return await send_icon(
'user', user_id, avatar_hash, ext=ext)
# @bp.route('/app-icons/<int:application_id>/<icon_hash>.<ext>')

View File

@ -173,9 +173,15 @@ async def patch_me():
""", j['email'], user_id)
user['email'] = j['email']
if 'avatar' in j:
# TODO: update icon
pass
if 'avatar' in j and j['avatar']:
new_icon = await app.icons.update(
'user', user_id, j['avatar'], size=(128, 128))
await app.db.execute("""
UPDATE users
SET avatar = $1
WHERE id = $2
""", new_icon.icon_hash, user_id)
if 'new_password' in j and j['new_password']:
await _check_pass(j, user)

View File

@ -116,6 +116,27 @@ def parse_data_uri(string) -> tuple:
raise ImageError('data URI invalid syntax')
def _gen_update_sql(scope: str) -> str:
field = {
'user': 'avatar',
'guild': 'icon'
}[scope]
table = {
'user': 'users',
'guild': 'guilds'
}[scope]
col = {
'user': 'id',
'guild': 'id'
}[scope]
return f"""
SELECT {field} FROM {table} WHERE {col} = $1
"""
class IconManager:
"""Main icon manager."""
def __init__(self, app):
@ -140,6 +161,7 @@ class IconManager:
async def generic_get(self, scope, key, icon_hash, **kwargs) -> Icon:
"""Get any icon."""
log.debug('GET {} {} {}', scope, key, icon_hash)
key = str(key)
icon_row = await self.storage.db.fetchrow("""
@ -158,7 +180,7 @@ class IconManager:
if not icon.as_pathlib.exists():
await self.delete(icon)
return None
if 'ext' in kwargs and kwargs['ext'] != icon.extension:
return await self._convert_ext(icon, kwargs['ext'])
@ -252,9 +274,22 @@ class IconManager:
WHERE hash = $1
""", icon.icon_hash)
icon_path = icon.as_pathlib
paths = IMAGE_FOLDER.glob(f'{icon.icon_hash}.*')
try:
icon_path.unlink()
except FileNotFoundError:
pass
for path in paths:
try:
path.unlink()
except FileNotFoundError:
pass
async def update(self, scope: str, key: str,
new_icon_data: str, **kwargs) -> Icon:
"""Update an icon on a key."""
old_icon_hash = await self.storage.db.fetchval(
_gen_update_sql(scope), key)
key = str(key)
old_icon = await self.generic_get(scope, key, old_icon_hash)
await self.delete(old_icon)
return await self.put(scope, key, new_icon_data, **kwargs)