Merge branch 'dev'
このコミットが含まれているのは:
コミット
322dc9b361
18
HACKING.md
18
HACKING.md
|
@ -32,31 +32,21 @@ on chat, e.g. text-to-speech or Twitch Plays Pokémon.
|
|||
|
||||
View events like this:
|
||||
```sh
|
||||
socat UNIX-CONNECT:event.sock STDOUT
|
||||
socat -u UNIX-CONNECT:event.sock STDOUT
|
||||
```
|
||||
|
||||
Sidenote, this will still read from stdin, and if you send anything on
|
||||
stdin the event socket will close itself. If you want to ignore stdin,
|
||||
I couldn't figure out how to get `socat` to do it so you can do it like
|
||||
this:
|
||||
```sh
|
||||
cat > /dev/null | socat UNIX-CONNECT:event.sock STDOUT
|
||||
```
|
||||
If you do this `cat` will not exit when the connection is closed so you
|
||||
will probably have to interrupt it with `^C`.
|
||||
|
||||
#### Examples
|
||||
|
||||
If you have `jq` you can view prettified events like this:
|
||||
```sh
|
||||
socat UNIX-CONNECT:event.sock STDOUT | jq
|
||||
socat -u UNIX-CONNECT:event.sock STDOUT | jq
|
||||
```
|
||||
(On older versions of `jq` you have to say `jq .` when reading from
|
||||
stdin.)
|
||||
|
||||
Use this to get each new chat message on a new line:
|
||||
```sh
|
||||
socat UNIX-CONNECT:event.sock STDOUT | jq 'select(.type == "message") | .event.nomarkup'
|
||||
socat -u UNIX-CONNECT:event.sock STDOUT | jq 'select(.type == "message") | .event.nomarkup'
|
||||
```
|
||||
|
||||
##### Text-to-speech
|
||||
|
@ -65,7 +55,7 @@ This command will take each new chat message with the prefix "!say ",
|
|||
strip the prefix, and synthesize the rest of the message as speech using
|
||||
`espeak`:
|
||||
```sh
|
||||
socat UNIX-CONNECT:event.sock STDOUT \
|
||||
socat -u UNIX-CONNECT:event.sock STDOUT \
|
||||
| jq --unbuffered 'select(.type == "message") | .event.nomarkup' \
|
||||
| grep -E --line-buffered '^"!say ' \
|
||||
| sed -Eu 's/^"!say /"/' \
|
||||
|
|
|
@ -75,7 +75,7 @@ def create_app(toml_config):
|
|||
from anonstream.events import start_event_server_at
|
||||
async def start_event_server():
|
||||
return await start_event_server_at(
|
||||
app.config['SOCKET_EVENT_ADDRESS']
|
||||
app.config['SOCKET_EVENT_ADDRESS']
|
||||
)
|
||||
app.add_background_task(start_event_server)
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class ArgsSeqs(Args):
|
|||
async def cmd_chat_help():
|
||||
normal = ['chat', 'help']
|
||||
response = (
|
||||
'Usage: chat {show [MESSAGES] | delete SEQS}\n'
|
||||
'Usage: chat delete SEQS\n'
|
||||
'Commands:\n'
|
||||
#' chat show [MESSAGES]......show chat messages\n'
|
||||
' chat delete SEQS..........delete chat messages\n'
|
||||
|
|
|
@ -23,7 +23,8 @@ def generate_token_hash_and_tag(token):
|
|||
return token_hash, tag
|
||||
|
||||
def generate_user(
|
||||
timestamp, token, broadcaster, verified=False, presence=Presence.NOTWATCHING,
|
||||
timestamp, token, broadcaster,
|
||||
verified=False, presence=Presence.NOTWATCHING, headers=None,
|
||||
):
|
||||
colour = generate_colour(
|
||||
seed='name\0' + token,
|
||||
|
@ -54,6 +55,7 @@ def generate_user(
|
|||
'total': 0,
|
||||
'current': {},
|
||||
},
|
||||
'headers': headers,
|
||||
}
|
||||
|
||||
def get_default_name(user):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-FileCopyrightText: 2022 n9k <https://git.076.ne.jp/ninya9k>
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import anonstream.routes.errors
|
||||
import anonstream.routes.error
|
||||
import anonstream.routes.core
|
||||
import anonstream.routes.websocket
|
||||
import anonstream.routes.nojs
|
||||
|
|
|
@ -47,7 +47,7 @@ async def stream(timestamp, user):
|
|||
raise NotFound('The stream is offline.')
|
||||
else:
|
||||
try:
|
||||
eyes_id = create_eyes(user, dict(request.headers))
|
||||
eyes_id = create_eyes(user, tuple(request.headers))
|
||||
except RatelimitedEyes as e:
|
||||
retry_after, *_ = e.args
|
||||
error = TooManyRequests(
|
||||
|
|
|
@ -151,7 +151,7 @@ async def nojs_submit_message(timestamp, user):
|
|||
else:
|
||||
state_id = None
|
||||
if message_was_added:
|
||||
deverify(user)
|
||||
deverify(user, timestamp=timestamp)
|
||||
|
||||
url = url_for(
|
||||
'nojs_chat_form',
|
||||
|
|
|
@ -72,7 +72,7 @@ def auth_required(f):
|
|||
return wrapper
|
||||
|
||||
def generate_and_add_user(
|
||||
timestamp, token=None, broadcaster=False, verified=False,
|
||||
timestamp, token=None, broadcaster=False, verified=False, headers=None,
|
||||
):
|
||||
token = token or generate_token()
|
||||
user = generate_user(
|
||||
|
@ -80,6 +80,7 @@ def generate_and_add_user(
|
|||
token=token,
|
||||
broadcaster=broadcaster,
|
||||
verified=verified,
|
||||
headers=headers,
|
||||
)
|
||||
USERS_BY_TOKEN[token] = user
|
||||
USERS_UPDATE_BUFFER.add(token)
|
||||
|
@ -132,6 +133,7 @@ def with_user_from(context, fallback_to_token=False):
|
|||
if CONFIG['ACCESS_CAPTCHA'] and not broadcaster:
|
||||
if user is not None:
|
||||
user['last']['seen'] = timestamp
|
||||
user['headers'] = tuple(context.headers)
|
||||
response = await f(timestamp, user, *args, **kwargs)
|
||||
elif fallback_to_token:
|
||||
#assert not broadcaster
|
||||
|
@ -146,8 +148,14 @@ def with_user_from(context, fallback_to_token=False):
|
|||
else:
|
||||
if user is not None:
|
||||
user['last']['seen'] = timestamp
|
||||
user['headers'] = tuple(context.headers)
|
||||
else:
|
||||
user = generate_and_add_user(timestamp, token, broadcaster)
|
||||
user = generate_and_add_user(
|
||||
timestamp,
|
||||
token,
|
||||
broadcaster,
|
||||
headers=tuple(context.headers),
|
||||
)
|
||||
response = await f(timestamp, user, *args, **kwargs)
|
||||
|
||||
# Set cookie
|
||||
|
|
|
@ -851,6 +851,7 @@ const connect_websocket = () => {
|
|||
}
|
||||
chat_live_ball.style.borderColor = "gold";
|
||||
chat_live_status.innerHTML = "<span data-verbose='true'>Connecting to chat...</span><span data-verbose='false'>···</span>";
|
||||
ws = null;
|
||||
ws = new WebSocket(`ws://${document.domain}:${location.port}/live?token=${encodeURIComponent(TOKEN)}`);
|
||||
ws.addEventListener("open", (event) => {
|
||||
console.log("websocket open", event);
|
||||
|
|
|
@ -9,7 +9,7 @@ from quart import current_app, websocket
|
|||
|
||||
from anonstream.broadcast import broadcast, broadcast_users_update
|
||||
from anonstream.stream import is_online, get_stream_title, get_stream_uptime_and_viewership
|
||||
from anonstream.user import get_sunsettable_users
|
||||
from anonstream.user import get_absent_users, get_sunsettable_users, deverify
|
||||
from anonstream.wrappers import with_timestamp
|
||||
|
||||
CONFIG = current_app.config
|
||||
|
@ -64,6 +64,12 @@ async def t_sunset_users(timestamp, iteration):
|
|||
if iteration == 0:
|
||||
return
|
||||
|
||||
# Deverify absent users
|
||||
for user in get_absent_users(timestamp):
|
||||
deverify(user, timestamp=timestamp)
|
||||
|
||||
# Remove as many absent users as possible
|
||||
|
||||
# Broadcast a users update, in case any users being
|
||||
# removed have been mutated or are new.
|
||||
broadcast_users_update()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="content-security-policy" content="default-src 'none'; img-src 'self'; style-src 'nonce-{{ csp }}';">
|
||||
<style nonce="{{ csp }}">
|
||||
body {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ error.code }} {{ error.name }}</title>
|
||||
<style>
|
||||
body {
|
||||
|
@ -9,7 +10,7 @@
|
|||
color: #ddd;
|
||||
font-family: sans-serif;
|
||||
font-size: 14pt;
|
||||
margin: 4pt 6pt;
|
||||
margin: 3pt 6pt;
|
||||
text-align: center;
|
||||
text-shadow: 2px 0px 1px orangered;
|
||||
}
|
||||
|
|
|
@ -173,8 +173,9 @@ def verify(user, digest, answer):
|
|||
|
||||
return verification_happened
|
||||
|
||||
@with_timestamp()
|
||||
def deverify(timestamp, user):
|
||||
def deverify(user, timestamp=None):
|
||||
if timestamp is None:
|
||||
timestamp = get_timestamp()
|
||||
if user['verified'] and not user['broadcaster']:
|
||||
n_user_messages = 0
|
||||
for message in reversed(MESSAGES):
|
||||
|
|
|
@ -122,7 +122,7 @@ def handle_inbound_message(timestamp, queue, user, nonce, comment, digest, answe
|
|||
else:
|
||||
notice = None
|
||||
if message_was_added:
|
||||
deverify(user)
|
||||
deverify(user, timestamp=timestamp)
|
||||
return {
|
||||
'type': 'ack',
|
||||
'nonce': nonce,
|
||||
|
|
|
@ -75,7 +75,7 @@ threshold = 20
|
|||
[flood.video]
|
||||
max_eyes = 3
|
||||
cooldown = 12.0
|
||||
expire_after = 5.0
|
||||
expire_after = 10.0
|
||||
overwrite = true
|
||||
|
||||
[presence]
|
||||
|
|
読み込み中…
新しいイシューから参照