anonstream/anonstream/control/spec/methods/user.py

136 行
4.2 KiB
Python

import json
from quart import current_app
from anonstream.control.exceptions import Fail
from anonstream.control.spec import NoParse
from anonstream.control.spec.common import Str, End, ArgsInt, ArgsString, ArgsJson, ArgsJsonString
from anonstream.control.spec.utils import get_item, json_dumps_contiguous
from anonstream.utils.user import USER_WEBSOCKET_ATTRS
USERS_BY_TOKEN = current_app.users_by_token
USERS = current_app.users
USERS_UPDATE_BUFFER = current_app.users_update_buffer
class ArgsJsonTokenUser(ArgsJsonString):
def transform_obj(self, token):
try:
user = USERS_BY_TOKEN[token]
except KeyError:
raise NoParse(f'no user with token {token!r}')
return user
def ArgsUser(spec):
return Str({
'token': ArgsJsonTokenUser(spec),
#'hash': ArgsJsonHashUser(spec),
})
async def cmd_user_help():
normal = ['user', 'help']
response = (
'Usage: user [show | attr USER | get USER ATTR | set USER ATTR VALUE]\n'
'Commands:\n'
' user [show].......................show all users\' tokens\n'
' user attr USER....................show names of a user\'s attributes\n'
' user get USER ATTR................show an attribute of a user\n'
' user set USER ATTR................set an attribute of a user\n'
' user eyes USER [show].............show a user\'s active video responses\n'
' user eyes USER delete EYES_ID.....end a video response to a user\n'
'Definitions:\n'
#' USER..............................={token TOKEN | hash HASH}\n'
' USER..............................=token TOKEN\n'
' TOKEN..............................a token, json string\n'
#' HASH..............................a token hash\n'
' ATTR...............................a user attribute, re:[a-z0-9_]+\n'
' EYES_ID............................a user\'s eyes_id, base 10 integer\n'
)
return normal, response
async def cmd_user_show():
normal = ['user', 'show']
response = json.dumps(tuple(USERS_BY_TOKEN)) + '\n'
return normal, response
async def cmd_user_attr(user):
normal = ['user', 'attr', 'token', json_dumps_contiguous(user['token'])]
response = json.dumps(tuple(user.keys())) + '\n'
return normal, response
async def cmd_user_get(user, attr):
try:
value = user[attr]
except KeyError as e:
raise Fail('user has no such attribute') from e
try:
value_json = json.dumps(value)
except (TypeError, ValueError) as e:
raise Fail('value is not representable in json') from e
normal = [
'user',
'get',
'token',
json_dumps_contiguous(user['token']),
attr,
]
response = value_json + '\n'
return normal, response
async def cmd_user_set(user, attr, value):
if attr not in user:
raise Fail(f'user has no attribute {attr!r}')
user[attr] = value
if attr in USER_WEBSOCKET_ATTRS:
USERS_UPDATE_BUFFER.add(user['token'])
normal = [
'user',
'set',
'token',
json_dumps_contiguous(user['token']),
attr,
json_dumps_contiguous(value),
]
response = ''
return normal, response
async def cmd_user_eyes_show(user):
normal = [
'user',
'eyes',
'token',
json_dumps_contiguous(user['token']),
'show'
]
response = json.dumps(user['eyes']['current']) + '\n'
return normal, response
async def cmd_user_eyes_delete(user, eyes_id):
try:
user['eyes']['current'].pop(eyes_id)
except KeyError:
pass
normal = [
'user',
'eyes',
'token',
json_dumps_contiguous(user['token']),
'delete',
str(eyes_id),
]
response = ''
return normal, response
SPEC = Str({
None: End(cmd_user_show),
'help': End(cmd_user_help),
'show': End(cmd_user_show),
'attr': ArgsUser(End(cmd_user_attr)),
'get': ArgsUser(ArgsString(End(cmd_user_get))),
'set': ArgsUser(ArgsString(ArgsJson(End(cmd_user_set)))),
'eyes': ArgsUser(Str({
None: End(cmd_user_eyes_show),
'show': End(cmd_user_eyes_show),
'delete': ArgsInt(End(cmd_user_eyes_delete)),
})),
})