diff --git a/anonstream/__main__.py b/anonstream/__main__.py index 92c2a46..1bc0b53 100644 --- a/anonstream/__main__.py +++ b/anonstream/__main__.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2022 n9k +# SPDX-License-Identifier: AGPL-3.0-or-later + import argparse import os diff --git a/anonstream/access.py b/anonstream/access.py index 3f76c02..e16fd8a 100644 --- a/anonstream/access.py +++ b/anonstream/access.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2022 n9k +# SPDX-License-Identifier: AGPL-3.0-or-later + import time from quart import current_app diff --git a/anonstream/control/spec/methods/user.py b/anonstream/control/spec/methods/user.py index dc09359..f293ce0 100644 --- a/anonstream/control/spec/methods/user.py +++ b/anonstream/control/spec/methods/user.py @@ -46,7 +46,7 @@ async def cmd_user_help(): ' 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 set USER ATTR VALUE......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' @@ -54,6 +54,7 @@ async def cmd_user_help(): ' TOKEN.........................a token, json string\n' ' HASH..........................a token hash\n' ' ATTR..........................a user attribute, re:[a-z0-9_]+\n' + ' VALUE.........................json value\n' ' EYES_ID.......................a user\'s eyes_id, base 10 integer\n' ) return normal, response diff --git a/anonstream/routes/websocket.py b/anonstream/routes/websocket.py index 95048c7..5aa6b75 100644 --- a/anonstream/routes/websocket.py +++ b/anonstream/routes/websocket.py @@ -4,7 +4,7 @@ import asyncio from quart import current_app, websocket -from anonstream.user import see, reading +from anonstream.user import see from anonstream.websocket import websocket_outbound, websocket_inbound from anonstream.routes.wrappers import with_user_from @@ -18,7 +18,7 @@ async def live(timestamp, user_or_token): case dict() as user: queue = asyncio.Queue() user['websockets'][queue] = timestamp - reading(user, timestamp=timestamp) + user['last']['reading'] = timestamp producer = websocket_outbound(queue, user) consumer = websocket_inbound(queue, user) diff --git a/anonstream/routes/wrappers.py b/anonstream/routes/wrappers.py index 3bcc606..cd184ae 100644 --- a/anonstream/routes/wrappers.py +++ b/anonstream/routes/wrappers.py @@ -13,7 +13,6 @@ from werkzeug.exceptions import BadRequest, Unauthorized, Forbidden from werkzeug.security import check_password_hash from anonstream.broadcast import broadcast -from anonstream.user import see from anonstream.helpers.user import generate_user from anonstream.utils.user import generate_token, Presence from anonstream.wrappers import get_timestamp @@ -121,7 +120,9 @@ def with_user_from(context, fallback_to_token=False): raise Unauthorized(Markup( f"You are using the broadcaster's token but you are " f"not logged in. The broadcaster should " - f"click here " + f"" + f"click here" + f" " f"and log in with the credentials printed in their " f"terminal when they started anonstream." )) @@ -138,12 +139,14 @@ def with_user_from(context, fallback_to_token=False): else: raise Forbidden(Markup( f"You have not solved the access captcha. " - f"" + f"" f"Click here." f"" )) else: - if user is None: + if user is not None: + user['last']['seen'] = timestamp + else: user = generate_and_add_user(timestamp, token, broadcaster) response = await f(timestamp, user, *args, **kwargs) diff --git a/anonstream/templates/error.html b/anonstream/templates/error.html index 38aa7ce..dc02fe7 100644 --- a/anonstream/templates/error.html +++ b/anonstream/templates/error.html @@ -5,11 +5,11 @@ {{ error.code }} {{ error.name }}
-

{{ error.code }} {{ error.name }}

+

{{ error.name }}

{% if error.description != error.__class__.description %}

{{ error.description }}

{% endif %} diff --git a/anonstream/user.py b/anonstream/user.py index 112d8d3..0789666 100644 --- a/anonstream/user.py +++ b/anonstream/user.py @@ -132,8 +132,9 @@ def change_tripcode(user, password, dry_run=False): def delete_tripcode(user): user['tripcode'] = None -@with_timestamp() -def see(timestamp, user): +def see(user, timestamp=None): + if timestamp is None: + timestamp = get_timestamp() user['last']['seen'] = timestamp def watching(user, timestamp=None): @@ -284,8 +285,8 @@ def create_eyes(timestamp, user, headers): def renew_eyes(timestamp, user, eyes_id, just_read_new_segment=False): try: eyes = user['eyes']['current'][eyes_id] - except KeyError: - raise DeletedEyes + except KeyError as e: + raise DeletedEyes from e # Enforce expire_after (if the background task hasn't already) renewed_ago = timestamp - eyes['renewed'] diff --git a/anonstream/websocket.py b/anonstream/websocket.py index f358235..ef91202 100644 --- a/anonstream/websocket.py +++ b/anonstream/websocket.py @@ -10,7 +10,7 @@ from anonstream.stream import get_stream_title, get_stream_uptime_and_viewership from anonstream.captcha import get_random_captcha_digest_for from anonstream.chat import get_all_messages_for_websocket, add_chat_message, Rejected from anonstream.user import get_all_users_for_websocket, see, reading, verify, deverify, BadCaptcha, try_change_appearance -from anonstream.wrappers import with_timestamp +from anonstream.wrappers import with_timestamp, get_timestamp from anonstream.utils.chat import generate_nonce from anonstream.utils.user import identifying_string from anonstream.utils.websocket import parse_websocket_data, Malformed, WS @@ -49,7 +49,8 @@ async def websocket_inbound(queue, user): except json.JSONDecodeError: receipt = None finally: - see(user) + timestamp = get_timestamp() + see(user, timestamp=timestamp) try: receipt_type, parsed = parse_websocket_data(receipt) except Malformed as e: @@ -68,25 +69,24 @@ async def websocket_inbound(queue, user): handle = handle_inbound_captcha case WS.PONG: handle = handle_inbound_pong - payload = handle(queue, user, *parsed) + payload = handle(timestamp, queue, user, *parsed) if payload is not None: queue.put_nowait(payload) -@with_timestamp() def handle_inbound_pong(timestamp, queue, user): print(f'[pong] {identifying_string(user)}') - reading(user, timestamp=timestamp) + user['last']['reading'] = timestamp user['websockets'][queue] = timestamp return None -def handle_inbound_captcha(queue, user): +def handle_inbound_captcha(timestamp, queue, user): return { 'type': 'captcha', 'digest': get_random_captcha_digest_for(user), } -def handle_inbound_appearance(queue, user, name, color, password, want_tripcode): +def handle_inbound_appearance(timestamp, queue, user, name, color, password, want_tripcode): errors = try_change_appearance(user, name, color, password, want_tripcode) if errors: return { @@ -102,7 +102,7 @@ def handle_inbound_appearance(queue, user, name, color, password, want_tripcode) #'tripcode': user['tripcode'], } -def handle_inbound_message(queue, user, nonce, comment, digest, answer): +def handle_inbound_message(timestamp, queue, user, nonce, comment, digest, answer): try: verification_happened = verify(user, digest, answer) except BadCaptcha as e: