Eyes: send Retry-After header during cooldown
このコミットが含まれているのは:
コミット
7db8895750
|
@ -43,6 +43,7 @@ def generate_user(timestamp, token, broadcaster, presence):
|
||||||
'last': {
|
'last': {
|
||||||
'seen': timestamp,
|
'seen': timestamp,
|
||||||
'watching': -inf,
|
'watching': -inf,
|
||||||
|
'eyes': -inf,
|
||||||
},
|
},
|
||||||
'presence': presence,
|
'presence': presence,
|
||||||
'linespan': deque(),
|
'linespan': deque(),
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
# SPDX-FileCopyrightText: 2022 n9k [https://git.076.ne.jp/ninya9k]
|
# SPDX-FileCopyrightText: 2022 n9k [https://git.076.ne.jp/ninya9k]
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
from quart import current_app, request, render_template, abort, make_response, redirect, url_for, abort
|
from quart import current_app, request, render_template, abort, make_response, redirect, url_for, abort
|
||||||
|
from werkzeug.exceptions import TooManyRequests
|
||||||
|
|
||||||
from anonstream.captcha import get_captcha_image
|
from anonstream.captcha import get_captcha_image
|
||||||
from anonstream.segments import segments, StopSendingSegments
|
from anonstream.segments import segments, StopSendingSegments
|
||||||
from anonstream.stream import is_online, get_stream_uptime
|
from anonstream.stream import is_online, get_stream_uptime
|
||||||
from anonstream.user import watched, create_eyes, renew_eyes, EyesException
|
from anonstream.user import watched, create_eyes, renew_eyes, EyesException, RatelimitedEyes
|
||||||
from anonstream.routes.wrappers import with_user_from, auth_required
|
from anonstream.routes.wrappers import with_user_from, auth_required
|
||||||
from anonstream.utils.security import generate_csp
|
from anonstream.utils.security import generate_csp
|
||||||
|
|
||||||
|
@ -27,6 +30,9 @@ async def stream(user):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
eyes_id = create_eyes(user, dict(request.headers))
|
eyes_id = create_eyes(user, dict(request.headers))
|
||||||
|
except RatelimitedEyes as e:
|
||||||
|
retry_after, *_ = e.args
|
||||||
|
return TooManyRequests(), {'Retry-After': math.ceil(retry_after)}
|
||||||
except EyesException:
|
except EyesException:
|
||||||
return abort(429)
|
return abort(429)
|
||||||
|
|
||||||
|
|
|
@ -239,13 +239,11 @@ def get_users_by_presence(timestamp):
|
||||||
@with_timestamp
|
@with_timestamp
|
||||||
def create_eyes(timestamp, user, headers):
|
def create_eyes(timestamp, user, headers):
|
||||||
# Enforce cooldown
|
# Enforce cooldown
|
||||||
last_created = max(
|
last_created_ago = timestamp - user['last']['eyes']
|
||||||
map(operator.itemgetter('created'), user['eyes']['current'].values()),
|
cooldown_ended_ago = last_created_ago - CONFIG['FLOOD_VIDEO_COOLDOWN']
|
||||||
default=-inf,
|
cooldown_remaining = -cooldown_ended_ago
|
||||||
)
|
if cooldown_remaining > 0:
|
||||||
last_created_ago = timestamp - last_created
|
raise RatelimitedEyes(cooldown_remaining)
|
||||||
if last_created_ago < CONFIG['FLOOD_VIDEO_COOLDOWN']:
|
|
||||||
raise RatelimitedEyes
|
|
||||||
|
|
||||||
# Enforce max_eyes & overwrite
|
# Enforce max_eyes & overwrite
|
||||||
if len(user['eyes']['current']) >= CONFIG['FLOOD_VIDEO_MAX_EYES']:
|
if len(user['eyes']['current']) >= CONFIG['FLOOD_VIDEO_MAX_EYES']:
|
||||||
|
@ -262,6 +260,7 @@ def create_eyes(timestamp, user, headers):
|
||||||
# Create eyes
|
# Create eyes
|
||||||
eyes_id = user['eyes']['total']
|
eyes_id = user['eyes']['total']
|
||||||
user['eyes']['total'] += 1
|
user['eyes']['total'] += 1
|
||||||
|
user['last']['eyes'] = timestamp
|
||||||
user['eyes']['current'][eyes_id] = {
|
user['eyes']['current'][eyes_id] = {
|
||||||
'id': eyes_id,
|
'id': eyes_id,
|
||||||
'token': user['token'],
|
'token': user['token'],
|
||||||
|
|
読み込み中…
新しいイシューから参照