Merge branch 'dev'

このコミットが含まれているのは:
n9k 2022-06-29 04:32:35 +00:00
コミット 322dc9b361
16個のファイルの変更38行の追加28行の削除

ファイルの表示

@ -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'>&middot;&middot;&middot;</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]