2021-04-13 22:14:01 +09:00
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import time
|
2021-04-15 20:37:04 +09:00
|
|
|
from flask import abort
|
2021-04-13 22:14:01 +09:00
|
|
|
from website.constants import SEGMENTS_DIR, SEGMENTS_M3U8, SEGMENT_INIT, STREAM_PIDFILE, STREAM_START, STREAM_TITLE
|
|
|
|
|
2021-04-15 20:37:04 +09:00
|
|
|
RE_SEGMENT_OR_INIT = re.compile(r'\b(stream(?P<number>\d+)\.m4s|init\.mp4)\b')
|
|
|
|
RE_SEGMENT = re.compile(r'stream(?P<number>\d+)\.m4s')
|
2021-04-13 22:14:01 +09:00
|
|
|
|
|
|
|
def _segment_number(fn):
|
|
|
|
if fn == SEGMENT_INIT: return None
|
|
|
|
return int(RE_SEGMENT.fullmatch(fn).group('number'))
|
|
|
|
|
|
|
|
def _is_segment(fn):
|
|
|
|
return bool(RE_SEGMENT.fullmatch(fn))
|
|
|
|
|
Update website/static/external/grids-responsive-min.css, website/static/external/pure-min.css, website/static/external/video-js.css, website/static/external/video.js, website/static/external/videojs-contrib-hls.js, website/static/platform.css, website/static/platform.js, website/templates/chat-iframe.html, website/templates/comment-iframe.html, website/templates/index.html, website/templates/stream-info-iframe.html, website/utils/captcha.py, website/utils/colour.py, website/utils/stream.py, website/utils/tripcode.py, website/chat.py, website/concatenate.py, website/routes.py, website/viewership.py files
2021-04-14 23:12:40 +09:00
|
|
|
def _get_segments(sort=False):
|
2021-04-13 22:14:01 +09:00
|
|
|
try:
|
Update website/static/external/grids-responsive-min.css, website/static/external/pure-min.css, website/static/external/video-js.css, website/static/external/video.js, website/static/external/videojs-contrib-hls.js, website/static/platform.css, website/static/platform.js, website/templates/chat-iframe.html, website/templates/comment-iframe.html, website/templates/index.html, website/templates/stream-info-iframe.html, website/utils/captcha.py, website/utils/colour.py, website/utils/stream.py, website/utils/tripcode.py, website/chat.py, website/concatenate.py, website/routes.py, website/viewership.py files
2021-04-14 23:12:40 +09:00
|
|
|
m3u8 = [line.rstrip() for line in open(SEGMENTS_M3U8).readlines() if _is_segment(line.rstrip())]
|
2021-04-13 22:14:01 +09:00
|
|
|
except FileNotFoundError:
|
Update website/static/external/grids-responsive-min.css, website/static/external/pure-min.css, website/static/external/video-js.css, website/static/external/video.js, website/static/external/videojs-contrib-hls.js, website/static/platform.css, website/static/platform.js, website/templates/chat-iframe.html, website/templates/comment-iframe.html, website/templates/index.html, website/templates/stream-info-iframe.html, website/utils/captcha.py, website/utils/colour.py, website/utils/stream.py, website/utils/tripcode.py, website/chat.py, website/concatenate.py, website/routes.py, website/viewership.py files
2021-04-14 23:12:40 +09:00
|
|
|
return []
|
2021-04-13 22:14:01 +09:00
|
|
|
|
Update website/static/external/grids-responsive-min.css, website/static/external/pure-min.css, website/static/external/video-js.css, website/static/external/video.js, website/static/external/videojs-contrib-hls.js, website/static/platform.css, website/static/platform.js, website/templates/chat-iframe.html, website/templates/comment-iframe.html, website/templates/index.html, website/templates/stream-info-iframe.html, website/utils/captcha.py, website/utils/colour.py, website/utils/stream.py, website/utils/tripcode.py, website/chat.py, website/concatenate.py, website/routes.py, website/viewership.py files
2021-04-14 23:12:40 +09:00
|
|
|
if sort:
|
|
|
|
m3u8.sort(key=_segment_number)
|
|
|
|
return m3u8
|
2021-04-13 22:14:01 +09:00
|
|
|
|
Update website/static/external/grids-responsive-min.css, website/static/external/pure-min.css, website/static/external/video-js.css, website/static/external/video.js, website/static/external/videojs-contrib-hls.js, website/static/platform.css, website/static/platform.js, website/templates/chat-iframe.html, website/templates/comment-iframe.html, website/templates/index.html, website/templates/stream-info-iframe.html, website/utils/captcha.py, website/utils/colour.py, website/utils/stream.py, website/utils/tripcode.py, website/chat.py, website/concatenate.py, website/routes.py, website/viewership.py files
2021-04-14 23:12:40 +09:00
|
|
|
def _is_available(fn, m3u8):
|
|
|
|
return fn in m3u8
|
2021-04-13 22:14:01 +09:00
|
|
|
|
Update website/static/external/grids-responsive-min.css, website/static/external/pure-min.css, website/static/external/video-js.css, website/static/external/video.js, website/static/external/videojs-contrib-hls.js, website/static/platform.css, website/static/platform.js, website/templates/chat-iframe.html, website/templates/comment-iframe.html, website/templates/index.html, website/templates/stream-info-iframe.html, website/utils/captcha.py, website/utils/colour.py, website/utils/stream.py, website/utils/tripcode.py, website/chat.py, website/concatenate.py, website/routes.py, website/viewership.py files
2021-04-14 23:12:40 +09:00
|
|
|
def current_segment():
|
|
|
|
if is_online():
|
|
|
|
segments = _get_segments()
|
|
|
|
if len(segments) == 0:
|
|
|
|
return None
|
|
|
|
last_segment = max(segments, key=_segment_number)
|
2021-04-13 22:14:01 +09:00
|
|
|
return _segment_number(last_segment)
|
Update website/static/external/grids-responsive-min.css, website/static/external/pure-min.css, website/static/external/video-js.css, website/static/external/video.js, website/static/external/videojs-contrib-hls.js, website/static/platform.css, website/static/platform.js, website/templates/chat-iframe.html, website/templates/comment-iframe.html, website/templates/index.html, website/templates/stream-info-iframe.html, website/utils/captcha.py, website/utils/colour.py, website/utils/stream.py, website/utils/tripcode.py, website/chat.py, website/concatenate.py, website/routes.py, website/viewership.py files
2021-04-14 23:12:40 +09:00
|
|
|
else:
|
2021-04-13 22:14:01 +09:00
|
|
|
return None
|
|
|
|
|
|
|
|
def is_online():
|
|
|
|
# If the pidfile doesn't exist, return False
|
|
|
|
try:
|
|
|
|
pid = open(STREAM_PIDFILE).read()
|
|
|
|
pid = int(pid)
|
|
|
|
except (FileNotFoundError, ValueError):
|
|
|
|
return False
|
|
|
|
|
|
|
|
# If the process ID doesn't exist, return False
|
|
|
|
try:
|
|
|
|
os.kill(pid, 0)
|
|
|
|
except OSError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
# Otherwise return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
def get_title():
|
|
|
|
try:
|
|
|
|
return open(STREAM_TITLE).read().strip()
|
|
|
|
except FileNotFoundError:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
def get_start(absolute=True, relative=False):
|
|
|
|
try:
|
|
|
|
start = open(STREAM_START).read()
|
|
|
|
start = int(start)
|
|
|
|
except (FileNotFoundError, ValueError):
|
|
|
|
start = None
|
|
|
|
|
|
|
|
diff = None if start == None else int(time.time()) - start
|
|
|
|
|
|
|
|
if absolute and relative:
|
|
|
|
return start, diff
|
|
|
|
elif absolute:
|
|
|
|
return start
|
|
|
|
elif relative:
|
2021-04-15 20:37:04 +09:00
|
|
|
return diff
|
|
|
|
|
|
|
|
|
|
|
|
class TokenPlaylist:
|
|
|
|
'''
|
|
|
|
Append '?token={token}' to each segment in the playlist
|
|
|
|
'''
|
|
|
|
def __init__(self, token):
|
|
|
|
self.token = token
|
|
|
|
self.fp = open(SEGMENTS_M3U8)
|
|
|
|
self.leftover = b''
|
|
|
|
|
|
|
|
def read(self, n):
|
|
|
|
if self.token == None:
|
|
|
|
return self.fp.read(n)
|
|
|
|
|
|
|
|
leftover = self.leftover
|
|
|
|
chunk = b''
|
|
|
|
while True:
|
|
|
|
line = self.fp.readline()
|
|
|
|
if len(line) == 0:
|
|
|
|
break
|
|
|
|
injected_line = RE_SEGMENT_OR_INIT.sub(lambda match: f'{match.group()}?token={self.token}', line)
|
|
|
|
chunk += injected_line.encode()
|
|
|
|
if len(chunk) >= n:
|
|
|
|
chunk, self.leftover = chunk[:n], chunk[n:]
|
|
|
|
break
|
|
|
|
return leftover + chunk
|
|
|
|
|
|
|
|
def close(self):
|
2021-05-22 18:57:15 +09:00
|
|
|
self.fp.close()
|