From c30e2c16aed70285a5fb8c6de99f1dcb16c5c33d Mon Sep 17 00:00:00 2001 From: ninya9k Date: Mon, 19 Jul 2021 06:28:00 +0000 Subject: [PATCH] organise html/css; token in concatenate.py error messages; fix margins around dates in chat --- website/concatenate.py | 27 +- website/constants.py | 1 - website/routes.py | 3 +- website/static/platform.css | 2 +- website/templates/chat-iframe.html | 461 ++++++++-------- website/templates/comment-confirm-iframe.html | 64 +-- website/templates/comment-iframe.html | 510 +++++++++--------- website/templates/comment.html | 14 + website/templates/index.html | 326 +++++------ website/templates/person.html | 1 + website/templates/secret-club.html | 45 +- website/templates/stream-info-iframe.html | 461 ++++++++-------- website/templates/users-iframe.html | 219 ++++---- website/templates/users.html | 52 ++ 14 files changed, 1140 insertions(+), 1046 deletions(-) create mode 100644 website/templates/comment.html create mode 100644 website/templates/person.html create mode 100644 website/templates/users.html diff --git a/website/concatenate.py b/website/concatenate.py index 8813e43..92df78d 100644 --- a/website/concatenate.py +++ b/website/concatenate.py @@ -18,9 +18,9 @@ def resolve_segment_offset(segment_offset=1): return 0 return _segment_number(segment) -def get_next_segment(after, start_segment): +def get_next_segment(after, start_segment, token=None): if not is_online(): - raise SegmentUnavailable(f'stream went offline') + raise SegmentUnavailable(f'stream went offline', token) start = time.time() while True: time.sleep(0.5) @@ -43,33 +43,36 @@ def get_next_segment(after, start_segment): if time.time() - start >= STREAM_TIMEOUT(): if after == None: - raise SegmentUnavailable(f'timeout waiting for initial segment {SEGMENT_INIT}') + raise SegmentUnavailable(f'timeout waiting for initial segment {SEGMENT_INIT}', token) elif after == SEGMENT_INIT: - raise SegmentUnavailable(f'timeout waiting for start segment {start_segment}') + raise SegmentUnavailable(f'timeout waiting for start segment {start_segment}', token) else: - raise SegmentUnavailable(f'timeout searching after {after}') + raise SegmentUnavailable(f'timeout searching after {after}', token) class SegmentUnavailable(Exception): pass class SegmentsIterator: - def __init__(self, start_segment, skip_init_segment=False): + def __init__(self, start_segment, token=None, skip_init_segment=False): self.start_segment = start_segment + self.token = token self.segment = SEGMENT_INIT if skip_init_segment else None def __iter__(self): return self def __next__(self): - self.segment = get_next_segment(self.segment, self.start_segment) + self.segment = get_next_segment(self.segment, self.start_segment, token=self.token) return self.segment class ConcatenatedSegments: - def __init__(self, start_number, segment_hook=None, corrupt_hook=None, should_close_connection=None): + def __init__(self, start_number, token=None, segment_hook=None, corrupt_hook=None, should_close_connection=None): # start at this segment, after SEGMENT_INIT self.start_number = start_number + # the token of the viewer the stream is being sent to + self.token = token # run this function before sending each segment (if we do it after then if someone gets the most of a segment but then stops, that wouldn't be counted, before = 0 viewers means nobody is retrieving the stream, after = slightly more accurate viewer count but 0 viewers doesn't necessarily mean nobody is retrieving the stream) self.segment_hook = segment_hook or (lambda n: None) # run this function when we send the corrupting segment @@ -78,7 +81,7 @@ class ConcatenatedSegments: self.should_close_connection = should_close_connection or (lambda: None) start_segment = SEGMENT.format(number=start_number) - self.segments = SegmentsIterator(start_segment=start_segment) + self.segments = SegmentsIterator(start_segment=start_segment, token=self.token) self._closed = False self.segment_read_offset = 0 @@ -89,14 +92,14 @@ class ConcatenatedSegments: chunk = b'' while True: if self.should_close_connection(): - raise SegmentUnavailable(f'told to close while reading {self.segment}') + raise SegmentUnavailable(f'told to close while reading {self.segment}', self.token) try: with open(os.path.join(SEGMENTS_DIR, self.segment), 'rb') as fp: fp.seek(self.segment_read_offset) chunk_chunk = fp.read(n - len(chunk)) except FileNotFoundError: - raise SegmentUnavailable(f'deleted while reading {self.segment}') + raise SegmentUnavailable(f'deleted while reading {self.segment}', self.token) self.segment_read_offset += len(chunk_chunk) chunk += chunk_chunk @@ -137,7 +140,7 @@ class ConcatenatedSegments: def _corrupt(self, n): # TODO: make this corrupt more reliably (maybe it has to follow a full segment?) # Doesn't corrupt when directly after init.mp4 - print('ConcatenatedSegments._corrupt') + print('ConcatenatedSegments._corrupt', self.token) self.corrupt_hook() self.close() try: diff --git a/website/constants.py b/website/constants.py index 5c7ce07..49a2155 100644 --- a/website/constants.py +++ b/website/constants.py @@ -17,7 +17,6 @@ CONFIG_FILE = os.path.join(ROOT, 'config.toml') with open(CONFIG_FILE) as fp: CONFIG = toml.load(fp) -# these two are accessed through `CONFIG`; they're just here for completeness # TODO: always read hls_time from stream.m3u8 VIEW_COUNTING_PERIOD = 30 # count views from the last x seconds diff --git a/website/routes.py b/website/routes.py index 73df8f2..190520e 100644 --- a/website/routes.py +++ b/website/routes.py @@ -150,6 +150,7 @@ def segments(): start_number = resolve_segment_offset() try: concatenated_segments = ConcatenatedSegments(start_number=start_number, + token=token, segment_hook=lambda n: viewership.view_segment(n, token, check_exists=False), corrupt_hook=lambda: viewership.video_was_corrupted.add(token), # lock? should_close_connection=should_close_connection) @@ -401,7 +402,7 @@ def add_header(response): def debug(): import copy - # necessary because we store colours as bytes and json can't bytes; + # necessary because we store colours as bytes and json can't bytes class JSONEncoder(json.encoder.JSONEncoder): def default(self, obj): if isinstance(obj, bytes): diff --git a/website/static/platform.css b/website/static/platform.css index 8d60171..359013a 100644 --- a/website/static/platform.css +++ b/website/static/platform.css @@ -3,7 +3,7 @@ margin: 0 0.5em 0.5em 0.5em; padding: 0.5em 0; border-bottom:1px solid gray; - font-size:125%; + font-size: 125%; } .hue-rotate { filter: hue-rotate(144deg); diff --git a/website/templates/chat-iframe.html b/website/templates/chat-iframe.html index 7669c38..d571ab4 100644 --- a/website/templates/chat-iframe.html +++ b/website/templates/chat-iframe.html @@ -1,230 +1,243 @@ - - - - {% if not debug %}{% endif %} - - - -
-
-
{{ stream_title }}
-
{{ stream_viewers }} viewer(s), {% if stream_uptime %}{{ stream_uptime }} uptime{% else %}offline{% endif %}
-
-
== Chat ==
-
-
-{% if broadcaster %} -
+ input[type="submit"] { + padding: 0 0.25em; + margin-bottom: 0.5em; + } + .refresh { + color: #f0f0f0; + background-color: gray; + position: sticky; + /*top: 100vh;*/ /* (when upside down etc.) placement is correct with top when there is no scrollbar */ + bottom: 0; /* (when upside down etc.) placement is correct with bottom when there is a scrollbar */ + padding: 1em; + text-align: center; + font-weight: bold; + border-radius: 4px; + box-shadow: 0px 2px 4px black; + margin: 0; + } + .refresh::after { + content: "Manual refresh required"; + } + input[type="checkbox"] { + vertical-align: middle; + } + .unhide { + animation: unhide 0s forwards 30s; + height: 0; + padding: 0; + visibility: hidden; + } + .unhide-margin { + animation: unhide-margin 0s forwards 30s; + height: 0; + padding: 0; + visibility: hidden; + } + @keyframes unhide { + to { + height: revert; + padding: 1em; + visibility: visible; + } + } + @keyframes unhide-margin { + to { + height: revert; + padding: 1em; + visibility: visible; + margin-bottom: 1.25em; + } + } + td { + width: 100vw; + } + /* for text-based browsers */ + .textonly { + display: none; + } + + + +
+
+
{{ stream_title }}
+
{{ stream_viewers }} viewer(s), {% if stream_uptime %}{{ stream_uptime }} uptime{% else %}offline{% endif %}
+
+
== Chat ==
+
+
+ {% if broadcaster %} +
- - - + + +
-{% endif %} - - - - {% for message in messages %} - - {% if message.get('special') == 'date' %} - - {% else %} - - {% endif %} - - {% endfor %} - -
{{ message['content'] }} - {% if not message['hidden'] %} - {% if broadcaster %} - - {% endif %} - {{ message['time'] }} 🎥{{ RE_WHITESPACE.sub(chr(160), message['viewer']['nickname'] or default_nickname(message['viewer']['token'])) }}{% with tag = message['viewer']['nickname'] == None and not message['viewer']['broadcaster'] %}{% if tag %}{{ message['viewer']['tag'] }}{% endif %} <{{ message['viewer']['tripcode']['string'] }}>
{{ message['markup'] }} - {% endif %} -
- -{% if broadcaster %} - -{% endif %} - -
-
-{% if include_user_list %} -
== List of users ==
-
- -
-
-
- {% with person = people['broadcaster'] %} - {% if person %} -
-
Broadcaster
-
- 🎥{{ person['nickname'] or default_nickname(person['token']) }}{% if person['tripcode']['string'] %} <{{ person['tripcode']['string'] }}>{% endif %} -
-
-
- {% endif %} - {% endwith %} -{% if broadcaster %} -
- - -{% endif %} -
-
Users watching ({{ len(people['watching']) }})
- {% for person in people['watching'] %} -
- {% if broadcaster %}{% endif %}{{ person['nickname'] or default_nickname(person['token']) }}{% with tag = person['nickname'] == None %}{% if tag %}{{ person['tag'] }}{% endif %}{% if person['tripcode']['string'] %}{% if tag %}{% endif %} <{{ person['tripcode']['string'] }}>{% endif %}{% endwith %}{% if person['token'] == token %} (You){% endif %} -
- {% endfor %} -
-
-
-
Users not watching ({{ len(people['not_watching']) }})
- {% for person in people['not_watching'] %} -
- {% if broadcaster %}{% endif %}{{ person['nickname'] or default_nickname(person['token']) }}{% with tag = person['nickname'] == None %}{% if tag %}{{ person['tag'] }}{% endif %}{% if person['tripcode']['string'] %}{% if tag %}{% endif %} <{{ person['tripcode']['string'] }}>{% endif %}{% endwith %}{% if person['token'] == token %} (You){% endif %} -
- {% endfor %} -
-
-{% if broadcaster %} - -
-
-
- - -
Banned ({{ len(people['banned']) }})
-
- {% for person in people['banned'] %} -
- {{ person['nickname'] or default_nickname(person['token']) }}{% with tag = person['nickname'] == None %}{% if tag %}{{ person['tag'] }}{% endif %}{% if person['tripcode']['string'] %}{% if tag %}{% endif %} <{{ person['tripcode']['string'] }}>{% endif %}{% endwith %} -
+ {% endif %} + + + + {% for message in messages %} + + {% if message.get('special') == 'date' %} + + {% else %} + + {% endif %} + {% endfor %} - - - -{% endif %} - - -{% endif %} - + +
+ {{ message['content'] }} + + + {% include 'comment.html' %} +
+ {% if broadcaster %} + + {% endif %} + +
+
+
+ {% if include_user_list %} +
== List of users ==
+
+ +
+
+
+ {% include 'users.html' %} +
+
+ {% endif %} + diff --git a/website/templates/comment-confirm-iframe.html b/website/templates/comment-confirm-iframe.html index 3b23409..21409f0 100644 --- a/website/templates/comment-confirm-iframe.html +++ b/website/templates/comment-confirm-iframe.html @@ -1,34 +1,34 @@ - - - - -
- - - - -
The stream is in secret club mode. Changing your tripcode would kick you out of the secret club. Click here to stay in the secret club, or to get kicked out.
-
- + + + + +
+ + + + +
The stream is in secret club mode. Changing your tripcode would kick you out of the secret club. Click here to stay in the secret club, or to get kicked out.
+
+ diff --git a/website/templates/comment-iframe.html b/website/templates/comment-iframe.html index 3f12d1e..1527f79 100644 --- a/website/templates/comment-iframe.html +++ b/website/templates/comment-iframe.html @@ -1,260 +1,260 @@ - - - - + + + +
+ + +
Send a message:
+ + +
+ + {% if captcha %} + + +
Captcha:
+ {% endif %} - .smalltext { - font-size: 85%; - } - - #password, #cancel-password { - display: none; - } - #password-toggle:checked ~ #password { - display: revert; - } - #password-toggle:checked ~ label[for="password-toggle"] #cancel-password { - display: revert; - } - #password-toggle:checked ~ label[for="password-toggle"] #tripcode-container { - display: none; - } - #password-toggle:checked ~ label[for="password-toggle"] #remove-tripcode { - display: none; - } - #password-toggle:checked ~ label[for="blank-tripcode-toggle"] { - display: none; - } - - #undo-remove-tripcode { - display: none; - } - #blank-tripcode { - display: none; - } - #blank-tripcode-toggle:checked ~ #blank-tripcode { - display: revert; - } - #blank-tripcode-toggle:checked ~ label[for="blank-tripcode-toggle"] #undo-remove-tripcode { - display: revert; - } - #blank-tripcode-toggle:checked ~ label[for="password-toggle"] { - display: none; - } - #blank-tripcode-toggle:checked ~ label[for="blank-tripcode-toggle"] #remove-tripcode { - display: none; - } - - #to-settings::after { - content: "⚙️"; - } - #to-chat::after { - content: "💬"; - } - .empty-tripcode-container::after { - content: "(no tripcode)"; - } - #cancel-password::after { - content: "×"; - } - #remove-tripcode::after { - content: "×"; - } - #blank-tripcode::after { - content: "(cleared)"; - } - #undo-remove-tripcode::after { - content: "undo"; - } - - #tripcode { - font-weight: normal; - padding: 0 5px; - border-radius: 6px; - font-size: 90%; - font-family: monospace; - vertical-align: middle; - display: inline-block; - cursor: pointer; - } - .pseudolink { - color: #a0a0a0; - cursor: pointer; - } - .pseudolink:active, .pseudolink:hover { - color: #00b6f0; - } - - /* for text-based browsers */ - .textonly { - display: none; - } - - - - - - - -
Send a message:
- - -
- - {% if captcha %} - - -
Captcha:
- - {% endif %} -
- -
-
- -
Nickname:
- -
- Set tripcode: - -
- Remove tripcode: - -
Password (to set tripcode):
- - {% if viewer['tripcode']['string'] %} - - - - - {% else %} - - {% endif %} -
-
- - -
-
-
-
{{ note }}
- +
+ +
+
+ +
Nickname:
+ +
+ Set tripcode: + +
+ Remove tripcode: + +
Password (to set tripcode):
+ + {% if viewer['tripcode']['string'] %} + + + + + {% else %} + + {% endif %} +
+
+ + +
+
+
+
{{ note }}
+ diff --git a/website/templates/comment.html b/website/templates/comment.html new file mode 100644 index 0000000..fad7d94 --- /dev/null +++ b/website/templates/comment.html @@ -0,0 +1,14 @@ +{% if not message['hidden'] %} + {% if broadcaster %} + + {% endif %} + {{ message['time'] }} 🎥{{ RE_WHITESPACE.sub(chr(160), message['viewer']['nickname'] or default_nickname(message['viewer']['token'])) }}{% with tag = message['viewer']['nickname'] == None and not message['viewer']['broadcaster'] %}{% if tag %}{{ message['viewer']['tag'] }}{% endif %} <{{ message['viewer']['tripcode']['string'] }}>
{{ message['markup'] }} +{% endif %} diff --git a/website/templates/index.html b/website/templates/index.html index 1757592..c0aa4f4 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -1,173 +1,173 @@ - - - - + + + + + {% if use_videojs %} + + + + + + + {% endif %} + + + +