From 7fdb74370e5756c443caff77b011156aeb598593 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 3 Mar 2019 18:57:54 -0300 Subject: [PATCH] add better implementation for GET /voice/region this takes account of: - the majority region selected in all the guilds the user owns. if that fails: - the majority region on all the guilds the user is in. if that fails: - random region - storage: add Storage.all_voice_regions --- litecord/blueprints/voice.py | 88 ++++++++++++++++++++++++++++++++++-- litecord/storage.py | 9 ++++ 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/litecord/blueprints/voice.py b/litecord/blueprints/voice.py index 85e4121..621a73c 100644 --- a/litecord/blueprints/voice.py +++ b/litecord/blueprints/voice.py @@ -17,13 +17,93 @@ along with this program. If not, see . """ -from quart import Blueprint, jsonify +from collections import Counter +from random import choice + +from quart import Blueprint, jsonify, current_app as app + +from litecord.blueprints.auth import token_check bp = Blueprint('voice', __name__) +def _majority_region_count(regions: list) -> str: + """Return the first most common element in a given list.""" + counter = Counter(regions) + common = counter.most_common(1) + region, _count = common[0] + + return region + + +async def _choose_random_region() -> str: + """Give a random voice region.""" + regions = await app.db.fetchval(""" + SELECT id + FROM voice_regions + """) + + regions = [r['id'] for r in regions] + + if not regions: + return None + + return choice(regions) + + +async def _majority_region_any(user_id) -> str: + """Calculate the most likely region to make the user happy, but + this is based on the guilds the user is IN, instead of the guilds + the user owns.""" + guilds = await app.storage.get_user_guilds(user_id) + + if not guilds: + return await _choose_random_region() + + res = [] + + for guild_id in guilds: + region = await app.db.fetchval(""" + SELECT region + FROM guilds + WHERE id = $1 + """, guild_id) + + res.append(region) + + most_common = _majority_region_count(res) + + if most_common is None: + return await _choose_random_region() + + return most_common + + +async def majority_region(user_id) -> str: + """Given a user ID, give the most likely region for the user to be + happy with.""" + regions = await app.db.fetch(""" + SELECT region + FROM guilds + WHERE owner_id = $1 + """, user_id) + + if not regions: + return await _majority_region_any(user_id) + + regions = [r['region'] for r in regions] + return _majority_region_count(regions) + + @bp.route('/regions', methods=['GET']) async def voice_regions(): - return jsonify([ - {'name': 'Brazil', 'deprecated': False, 'id': 'Brazil', 'optimal': True, 'vip': True} - ]) + """Return voice regions.""" + user_id = await token_check() + + best_region = await majority_region(user_id) + regions = await app.storage.get_all_regions() + + for region in regions: + region['optimal'] = region['id'] == best_region + + return jsonify(regions) diff --git a/litecord/storage.py b/litecord/storage.py index 0910a65..962bb57 100644 --- a/litecord/storage.py +++ b/litecord/storage.py @@ -1015,3 +1015,12 @@ class Storage: """, role_id) return [r['id'] for r in rows] + + async def all_voice_regions(self) -> List[Dict[str, Any]]: + """Return a list of all voice regions.""" + rows = await self.db.fetch(""" + SELECT id, name, vip, deprecated, custom + FROM voice_regions + """) + + return list(map(dict, rows))