50 行
1.7 KiB
Python
50 行
1.7 KiB
Python
# SPDX-FileCopyrightText: 2022 n9k <https://git.076.ne.jp/ninya9k>
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
import base64
|
|
import hashlib
|
|
import math
|
|
import re
|
|
import secrets
|
|
from functools import lru_cache
|
|
|
|
from quart import escape
|
|
|
|
class NonceReuse(Exception):
|
|
pass
|
|
|
|
def generate_nonce():
|
|
return secrets.token_urlsafe(16)
|
|
|
|
def get_message_for_websocket(user, message):
|
|
message_keys = ('seq', 'date', 'time_minutes', 'time_seconds', 'markup')
|
|
user_keys = ('token_hash',)
|
|
return {
|
|
**{key: message[key] for key in message_keys},
|
|
**{key: user[key] for key in user_keys},
|
|
}
|
|
|
|
def get_approx_linespan(text):
|
|
def height(line):
|
|
return math.ceil(len(line) / 48)
|
|
linespan = sum(map(height, text.splitlines()))
|
|
linespan = linespan if linespan > 0 else 1
|
|
return linespan
|
|
|
|
def precompute_emote_regex(schema):
|
|
for emote in schema:
|
|
assert emote['name'], 'emote names cannot be empty'
|
|
assert not re.search(r'\s', emote['name']), \
|
|
'whitespace is not allowed in emote names'
|
|
# If the emote name begins with a word character [a-zA-Z0-9_],
|
|
# match only if preceded by a non-word character or the empty
|
|
# string. Similarly for the end of the emote name.
|
|
# Examples:
|
|
# * ":joy:" matches "abc :joy:~xyz" and "abc:joy:xyz"
|
|
# * "JoySi" matches "abc JoySi~xyz" but NOT "abcJoySiabc"
|
|
onset = r'(?:^|(?<=\W))' if re.fullmatch(r'\w', emote['name'][0]) else r''
|
|
finish = r'(?:$|(?=\W))' if re.fullmatch(r'\w', emote['name'][-1]) else r''
|
|
emote['regex'] = re.compile(''.join(
|
|
(onset, re.escape(escape(emote['name'])), finish)
|
|
))
|