Get stream title from disk
By default from `title.txt`. Also replace newlines with spaces when setting the title in js, for parity with the nojs info iframe.
このコミットが含まれているのは:
コミット
8b4d6e8c09
|
@ -1,3 +1,4 @@
|
||||||
__pycache__/
|
__pycache__/
|
||||||
stream/
|
stream/
|
||||||
*~
|
*~
|
||||||
|
title.txt
|
||||||
|
|
|
@ -32,6 +32,8 @@ def create_app(config_file):
|
||||||
'SEGMENT_SEARCH_COOLDOWN': config['segments']['search_cooldown'],
|
'SEGMENT_SEARCH_COOLDOWN': config['segments']['search_cooldown'],
|
||||||
'SEGMENT_SEARCH_TIMEOUT': config['segments']['search_timeout'],
|
'SEGMENT_SEARCH_TIMEOUT': config['segments']['search_timeout'],
|
||||||
'SEGMENT_STREAM_INITIAL_BUFFER': config['segments']['stream_initial_buffer'],
|
'SEGMENT_STREAM_INITIAL_BUFFER': config['segments']['stream_initial_buffer'],
|
||||||
|
'STREAM_TITLE': config['title']['file'],
|
||||||
|
'STREAM_TITLE_CACHE_LIFETIME': config['title']['file_cache_lifetime'],
|
||||||
'DEFAULT_HOST_NAME': config['names']['broadcaster'],
|
'DEFAULT_HOST_NAME': config['names']['broadcaster'],
|
||||||
'DEFAULT_ANON_NAME': config['names']['anonymous'],
|
'DEFAULT_ANON_NAME': config['names']['anonymous'],
|
||||||
'MAX_STATES': config['memory']['states'],
|
'MAX_STATES': config['memory']['states'],
|
||||||
|
|
|
@ -19,7 +19,7 @@ async def nojs_info(user):
|
||||||
return await render_template(
|
return await render_template(
|
||||||
'nojs_info.html',
|
'nojs_info.html',
|
||||||
user=user,
|
user=user,
|
||||||
title=get_stream_title(),
|
title=await get_stream_title(),
|
||||||
uptime=get_stream_uptime(),
|
uptime=get_stream_uptime(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -316,6 +316,12 @@ const disable_captcha = () => {
|
||||||
chat_form_captcha_image.removeAttribute("src");
|
chat_form_captcha_image.removeAttribute("src");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const set_title = (title) => {
|
||||||
|
const element = document.createElement("h1");
|
||||||
|
element.innerText = title.replaceAll(/\r?\n/g, " ");
|
||||||
|
info_title.innerHTML = element.outerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
let frozen_uptime = null;
|
let frozen_uptime = null;
|
||||||
let frozen_uptime_received = null;
|
let frozen_uptime_received = null;
|
||||||
const set_frozen_uptime = (x) => {
|
const set_frozen_uptime = (x) => {
|
||||||
|
@ -357,7 +363,7 @@ const on_websocket_message = (event) => {
|
||||||
case "init":
|
case "init":
|
||||||
console.log("ws init", receipt);
|
console.log("ws init", receipt);
|
||||||
|
|
||||||
info_title.innerText = receipt.title;
|
set_title(receipt.title);
|
||||||
set_frozen_uptime(receipt.uptime);
|
set_frozen_uptime(receipt.uptime);
|
||||||
update_uptime();
|
update_uptime();
|
||||||
|
|
||||||
|
@ -395,7 +401,7 @@ const on_websocket_message = (event) => {
|
||||||
|
|
||||||
case "title":
|
case "title":
|
||||||
console.log("ws title", receipt);
|
console.log("ws title", receipt);
|
||||||
info_title.innerText = receipt.title;
|
set_title(receipt.title);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ack":
|
case "ack":
|
||||||
|
|
|
@ -68,8 +68,10 @@ noscript {
|
||||||
float: right;
|
float: right;
|
||||||
font-size: 11pt;
|
font-size: 11pt;
|
||||||
}
|
}
|
||||||
#info_js__title {
|
#info_js__title > h1 {
|
||||||
|
margin: 0;
|
||||||
font-size: 18pt;
|
font-size: 18pt;
|
||||||
|
line-height: 1.125;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
#info_nojs {
|
#info_nojs {
|
||||||
|
|
|
@ -1,9 +1,21 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from anonstream.segments import get_playlist, Offline
|
import aiofiles
|
||||||
|
from quart import current_app
|
||||||
|
|
||||||
def get_stream_title():
|
from anonstream.segments import get_playlist, Offline
|
||||||
return 'Stream title'
|
from anonstream.wrappers import ttl_cache_async
|
||||||
|
|
||||||
|
CONFIG = current_app.config
|
||||||
|
|
||||||
|
@ttl_cache_async(CONFIG['STREAM_TITLE_CACHE_LIFETIME'])
|
||||||
|
async def get_stream_title():
|
||||||
|
try:
|
||||||
|
async with aiofiles.open(CONFIG['STREAM_TITLE']) as fp:
|
||||||
|
title = await fp.read(8192)
|
||||||
|
except FileNotFoundError:
|
||||||
|
title = ''
|
||||||
|
return title
|
||||||
|
|
||||||
def get_stream_uptime(rounded=True):
|
def get_stream_uptime(rounded=True):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#title > h1 {
|
#title > h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 18pt;
|
font-size: 18pt;
|
||||||
|
line-height: 1.125;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -15,7 +15,7 @@ async def websocket_outbound(queue, user):
|
||||||
payload = {
|
payload = {
|
||||||
'type': 'init',
|
'type': 'init',
|
||||||
'nonce': generate_nonce(),
|
'nonce': generate_nonce(),
|
||||||
'title': get_stream_title(),
|
'title': await get_stream_title(),
|
||||||
'uptime': get_stream_uptime(),
|
'uptime': get_stream_uptime(),
|
||||||
'messages': get_all_messages_for_websocket(),
|
'messages': get_all_messages_for_websocket(),
|
||||||
'users': get_all_users_for_websocket(),
|
'users': get_all_users_for_websocket(),
|
||||||
|
|
|
@ -53,3 +53,24 @@ def ttl_cache(ttl):
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return ttl_cache_specific
|
return ttl_cache_specific
|
||||||
|
|
||||||
|
def ttl_cache_async(ttl):
|
||||||
|
'''
|
||||||
|
Async version of `ttl_cache`. Wraps zero-argument coroutines.
|
||||||
|
'''
|
||||||
|
def ttl_cache_specific(f):
|
||||||
|
value, expires = None, None
|
||||||
|
|
||||||
|
@wraps(f)
|
||||||
|
async def wrapper():
|
||||||
|
nonlocal value, expires
|
||||||
|
|
||||||
|
if expires is None or time.monotonic() >= expires:
|
||||||
|
value = await f()
|
||||||
|
expires = time.monotonic() + ttl
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return ttl_cache_specific
|
||||||
|
|
|
@ -12,6 +12,10 @@ search_cooldown = 0.25
|
||||||
search_timeout = 5.0
|
search_timeout = 5.0
|
||||||
stream_initial_buffer = 3
|
stream_initial_buffer = 3
|
||||||
|
|
||||||
|
[title]
|
||||||
|
file = "title.txt"
|
||||||
|
file_cache_lifetime = 0.5
|
||||||
|
|
||||||
[captcha]
|
[captcha]
|
||||||
lifetime = 1800
|
lifetime = 1800
|
||||||
fonts = []
|
fonts = []
|
||||||
|
|
読み込み中…
新しいイシューから参照