diff --git a/anonstream/routes/core.py b/anonstream/routes/core.py index d0ab784..0ae66a7 100644 --- a/anonstream/routes/core.py +++ b/anonstream/routes/core.py @@ -15,6 +15,7 @@ from anonstream.routes.wrappers import with_user_from, auth_required, clean_cach from anonstream.helpers.captcha import check_captcha_digest, Answer from anonstream.utils.security import generate_csp from anonstream.utils.user import identifying_string +from anonstream.wrappers import with_timestamp CAPTCHA_SIGNER = current_app.captcha_signer STATIC_DIRECTORY = current_app.root_path / 'static' @@ -66,15 +67,18 @@ async def stream(timestamp, user): f'End one of those before making a new request.' ) else: - def segment_read_hook(uri): + @with_timestamp(precise=True) + def segment_read_hook(timestamp, uri): + user['last']['seen'] = timestamp try: - renew_eyes(user, eyes_id, just_read_new_segment=True) + renew_eyes(timestamp, user, eyes_id, just_read_new_segment=True) except EyesException as e: raise StopSendingSegments( f'eyes {eyes_id} not allowed: {e!r}' ) from e + else: + user['last']['watching'] = timestamp print(f'{uri}: \033[37m{eyes_id}\033[0m~{identifying_string(user)}') - watching(user) generator = segments(segment_read_hook, token=f'\033[35m{user["token"]}\033[0m') response = await make_response(generator) response.headers['Content-Type'] = 'video/mp4' diff --git a/anonstream/user.py b/anonstream/user.py index 69fbbfa..5ecc711 100644 --- a/anonstream/user.py +++ b/anonstream/user.py @@ -43,6 +43,9 @@ class DeletedEyes(EyesException): class ExpiredEyes(EyesException): pass +class DisallowedEyes(EyesException): + pass + class AllowednessException(Exception): pass @@ -264,6 +267,9 @@ def get_users_by_presence(timestamp): @with_timestamp(precise=True) def create_eyes(timestamp, user, headers): + # Unlike in renew_eyes, allowedness is NOT checked here because it is + # assumed to have already been checked (by the route handler). + # Enforce cooldown last_created_ago = timestamp - user['last']['eyes'] cooldown_ended_ago = last_created_ago - CONFIG['FLOOD_VIDEO_COOLDOWN'] @@ -297,7 +303,6 @@ def create_eyes(timestamp, user, headers): } return eyes_id -@with_timestamp(precise=True) def renew_eyes(timestamp, user, eyes_id, just_read_new_segment=False): try: eyes = user['eyes']['current'][eyes_id] @@ -310,6 +315,13 @@ def renew_eyes(timestamp, user, eyes_id, just_read_new_segment=False): user['eyes']['current'].pop(eyes_id) raise ExpiredEyes + # Ensure allowedness + try: + ensure_allowedness(user, timestamp=timestamp) + except AllowednessException as e: + user['eyes']['current'].pop(eyes_id) + raise DisallowedEyes from e + if just_read_new_segment: eyes['n_segments'] += 1 eyes['renewed'] = timestamp