mirror of https://gitlab.com/litecord/litecord.git
admin_api.features: make features input as a list
- add PATCH /:id/features - enums: add Feature enum - schemas: add FEATURES - storage: add Storage.guild_features - types: add return type to timestamp_
This commit is contained in:
parent
073f47e0f5
commit
2c1c384409
|
|
@ -17,33 +17,75 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
"""
|
||||
|
||||
from quart import Blueprint, current_app as app
|
||||
from quart import Blueprint, current_app as app, jsonify, request
|
||||
|
||||
from litecord.auth import admin_check
|
||||
from litecord.errors import BadRequest
|
||||
from litecord.schemas import validate, FEATURES
|
||||
from litecord.enums import Feature
|
||||
|
||||
bp = Blueprint('features_admin', __name__)
|
||||
|
||||
FEATURES = [
|
||||
''
|
||||
]
|
||||
|
||||
@bp.route('/<int:guild_id>/<feature>', methods=['PUT'])
|
||||
async def insert_feature(guild_id: int, feature: str):
|
||||
async def _features(guild_id: int):
|
||||
return jsonify({
|
||||
'features': await app.storage.guild_features(guild_id)
|
||||
})
|
||||
|
||||
|
||||
async def _update_features(guild_id: int, features: list):
|
||||
await app.db.execute("""
|
||||
UPDATE guilds
|
||||
SET features = $1
|
||||
WHERE id = $2
|
||||
""", features, guild_id)
|
||||
|
||||
|
||||
@bp.route('/<int:guild_id>/features', methods=['PATCH'])
|
||||
async def replace_features(guild_id: int):
|
||||
"""Replace the feature list in a guild"""
|
||||
await admin_check()
|
||||
j = validate(await request.get_json(), FEATURES)
|
||||
features = j['features']
|
||||
|
||||
# yes, we need to pass it to a set and then to a list before
|
||||
# doing anything, since the api client might just
|
||||
# shove 200 repeated features to us.
|
||||
await _update_features(guild_id, list(set(features)))
|
||||
return await _features(guild_id)
|
||||
|
||||
|
||||
@bp.route('/<int:guild_id>/features', methods=['PUT'])
|
||||
async def insert_features(guild_id: int):
|
||||
"""Insert a feature on a guild."""
|
||||
await admin_check()
|
||||
j = validate(await request.get_json(), FEATURES)
|
||||
|
||||
# TODO
|
||||
if feature not in FEATURES:
|
||||
raise BadRequest('invalid feature')
|
||||
to_add = j['features']
|
||||
features = await app.storage.guild_features(guild_id)
|
||||
features = set(features)
|
||||
|
||||
return '', 204
|
||||
# i'm assuming set.add is mostly safe
|
||||
for feature in to_add:
|
||||
features.add(feature)
|
||||
|
||||
await _update_features(guild_id, list(features))
|
||||
return await _features(guild_id)
|
||||
|
||||
|
||||
@bp.route('/<int:guild_id>/<feature>', methods=['DELETE'])
|
||||
async def remove_feature(guild_id: int, feature: str):
|
||||
async def remove_feature(guild_id: int):
|
||||
"""Remove a feature from a guild"""
|
||||
await admin_check()
|
||||
# TODO
|
||||
await app.db
|
||||
return '', 204
|
||||
j = validate(await request.get_json(), FEATURES)
|
||||
to_remove = j['features']
|
||||
features = await app.storage.guild_features(guild_id)
|
||||
|
||||
for feature in to_remove:
|
||||
try:
|
||||
features.remove(feature)
|
||||
except ValueError:
|
||||
raise BadRequest('Trying to remove already removed feature.')
|
||||
|
||||
await _update_features(guild_id, features)
|
||||
return await _features(guild_id)
|
||||
|
|
|
|||
|
|
@ -197,12 +197,27 @@ class RelationshipType(EasyEnum):
|
|||
|
||||
|
||||
class MessageNotifications(EasyEnum):
|
||||
"""Message notifications"""
|
||||
ALL = 0
|
||||
MENTIONS = 1
|
||||
NOTHING = 2
|
||||
|
||||
|
||||
class PremiumType:
|
||||
"""Premium (Nitro) type."""
|
||||
TIER_1 = 1
|
||||
TIER_2 = 2
|
||||
NONE = None
|
||||
|
||||
|
||||
class Feature(Enum):
|
||||
"""Guild features."""
|
||||
invite_splash = 'INVITE_SPLASH'
|
||||
vip = 'VIP_REGIONS'
|
||||
vanity = 'VANITY_URL'
|
||||
emoji = 'MORE_EMOJI'
|
||||
verified = 'VERIFIED'
|
||||
|
||||
# unknown
|
||||
commerce = 'COMMERCE'
|
||||
news = 'NEWS'
|
||||
|
|
|
|||
|
|
@ -655,3 +655,10 @@ GET_MENTIONS = {
|
|||
'everyone': {'coerce': bool, 'default': True},
|
||||
'guild_id': {'coerce': int, 'required': False}
|
||||
}
|
||||
|
||||
FEATURES = {
|
||||
'features': {
|
||||
'type': 'list', 'required': True,
|
||||
'schema': {'type': 'guild_feature'}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,6 +146,13 @@ class Storage:
|
|||
WHERE username = $1 AND discriminator = $2
|
||||
""", username, discriminator)
|
||||
|
||||
async def guild_features(self, guild_id: int) -> Optional[List[str]]:
|
||||
"""Get a list of guild features for the given guild."""
|
||||
return await self.db.fetchval("""
|
||||
SELECT features FROM guilds
|
||||
WHERE id = $1
|
||||
""", guild_id)
|
||||
|
||||
async def get_guild(self, guild_id: int, user_id=None) -> Optional[Dict]:
|
||||
"""Get gulid payload."""
|
||||
row = await self.db.fetchrow("""
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
# size units
|
||||
KILOBYTES = 1024
|
||||
|
||||
|
|
@ -45,5 +47,6 @@ class Color:
|
|||
return self.value
|
||||
|
||||
|
||||
def timestamp_(dt):
|
||||
def timestamp_(dt) -> Optional[str]:
|
||||
"""safer version for dt.isoformat()"""
|
||||
return f'{dt.isoformat()}+00:00' if dt else None
|
||||
|
|
|
|||
Loading…
Reference in New Issue