load video from render
This commit is contained in:
		@@ -47,37 +47,17 @@ class ProxyElem():
 | 
			
		||||
        return aiohttp.ClientSession(connector=connector, timeout=timeout)
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return str(self.proxy)
 | 
			
		||||
    async def content_type(self, url):
 | 
			
		||||
        cached = ctype_cache.get(url)
 | 
			
		||||
        if isinstance(cached, str) and "binary" not in cached.lower():
 | 
			
		||||
            return cached
 | 
			
		||||
        async with self.session() as session:
 | 
			
		||||
            for i in range(5):
 | 
			
		||||
                try:
 | 
			
		||||
                    resp = await session.head(url)
 | 
			
		||||
                    ctype = resp.headers.get("Content-Type", None)
 | 
			
		||||
                except Exception as e:
 | 
			
		||||
                    logger.info(e)
 | 
			
		||||
                else:
 | 
			
		||||
                    if isinstance(ctype, str):
 | 
			
		||||
                        ctype_cache[url] = ctype
 | 
			
		||||
                        return ctype
 | 
			
		||||
        return "binary/octet-type"
 | 
			
		||||
    async def proxy_url(self, current, path):
 | 
			
		||||
    async def proxy_url(self, urls):
 | 
			
		||||
        if not isinstance(proxy_server, str):
 | 
			
		||||
            return urls
 | 
			
		||||
        jdata = None
 | 
			
		||||
        data = {}
 | 
			
		||||
        data_list = [data]
 | 
			
		||||
        if path is None:
 | 
			
		||||
            data["upstream"] = current
 | 
			
		||||
        else:
 | 
			
		||||
            data["upstream"] = urllib.parse.urljoin(current, path)
 | 
			
		||||
        data["proxied"] = True
 | 
			
		||||
        if self.proxy is None:
 | 
			
		||||
            data["proxied"] = False
 | 
			
		||||
        else:
 | 
			
		||||
        data_list = []
 | 
			
		||||
        for url in urls:
 | 
			
		||||
            data = {}
 | 
			
		||||
            data["upstream"] = url
 | 
			
		||||
            data["proxy"] = self.proxy
 | 
			
		||||
        if proxy_server is None:
 | 
			
		||||
            return data["upstream"]
 | 
			
		||||
            data["proxied"] = isinstance(self.proxy, str)
 | 
			
		||||
            data_list.append(data)
 | 
			
		||||
        try:
 | 
			
		||||
            async with self.local() as session:
 | 
			
		||||
                resp = await session.post(proxy_server, json=data_list)
 | 
			
		||||
@@ -85,10 +65,16 @@ class ProxyElem():
 | 
			
		||||
                jdata = json.loads(text)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            logger.info(e)
 | 
			
		||||
        if isinstance(jdata, list) and len(jdata) == 1:
 | 
			
		||||
            return jdata[0]
 | 
			
		||||
        if isinstance(jdata, list):
 | 
			
		||||
            ret_data = []
 | 
			
		||||
            for i in range(len(jdata)):
 | 
			
		||||
                if isinstance(urls[i], str):
 | 
			
		||||
                    ret_data.append(jdata[i])
 | 
			
		||||
                else:
 | 
			
		||||
                    ret_data.append(None)
 | 
			
		||||
            return ret_data
 | 
			
		||||
        else:
 | 
			
		||||
            return data["upstream"]
 | 
			
		||||
            return urls
 | 
			
		||||
 | 
			
		||||
class AsyncSessionData():
 | 
			
		||||
    def __init__(self, resp, current):
 | 
			
		||||
@@ -125,28 +111,18 @@ stream_providers.setup(proxy_keys)
 | 
			
		||||
class UpstreamHandler():
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.provider = None
 | 
			
		||||
        self.render_url = None
 | 
			
		||||
        self.stream_url = None
 | 
			
		||||
        self.valid = False
 | 
			
		||||
        self.proxy = None
 | 
			
		||||
        self.upstream = None
 | 
			
		||||
        self.upstream_safe = None
 | 
			
		||||
        self.render = False
 | 
			
		||||
        self.stream = False
 | 
			
		||||
    async def setup(self, handler):
 | 
			
		||||
        self.provider = handler.get_query_argument("provider", None)
 | 
			
		||||
        render_str = handler.get_query_argument("render", "false")
 | 
			
		||||
        if self.provider in providers.keys():
 | 
			
		||||
            if render_str.lower() == "true":
 | 
			
		||||
                self.render = True
 | 
			
		||||
            else:
 | 
			
		||||
                self.stream = True
 | 
			
		||||
 | 
			
		||||
            self.valid = True
 | 
			
		||||
            path = handler.request.path
 | 
			
		||||
            if self.provider == "nextcloud":
 | 
			
		||||
                path = path.removesuffix("/").removesuffix("download").removesuffix("/")
 | 
			
		||||
            elif self.provider == "youtube":
 | 
			
		||||
                path = path.removeprefix("/")
 | 
			
		||||
 | 
			
		||||
            src = providers[self.provider] + path
 | 
			
		||||
            proxy_list = proxies.get(self.provider)
 | 
			
		||||
            if isinstance(proxy_list, list):
 | 
			
		||||
@@ -170,10 +146,8 @@ class UpstreamHandler():
 | 
			
		||||
                        new_url = str(resp.url)
 | 
			
		||||
                        if new_url.lower().startswith("https://consent.youtube.com"):
 | 
			
		||||
                            self.upstream = src
 | 
			
		||||
                            self.upstream_safe = urllib.parse.quote(src)
 | 
			
		||||
                        else:
 | 
			
		||||
                            self.upstream = new_url
 | 
			
		||||
                            self.upstream_safe = urllib.parse.quote(new_url)
 | 
			
		||||
                        self.proxy = result.current
 | 
			
		||||
                        break
 | 
			
		||||
                for future in futures:
 | 
			
		||||
@@ -201,7 +175,7 @@ if icecast_server is not None and stream_server is not None:
 | 
			
		||||
        logger.info(e)
 | 
			
		||||
 | 
			
		||||
template_html = None
 | 
			
		||||
script_file = None
 | 
			
		||||
template_script = None
 | 
			
		||||
videojs_version = None
 | 
			
		||||
font_awesome_version = None
 | 
			
		||||
custom_style = None
 | 
			
		||||
@@ -210,9 +184,7 @@ try:
 | 
			
		||||
    with open("/app/index.html", "r") as f:
 | 
			
		||||
        template_html = tornado.template.Template(f.read().strip())
 | 
			
		||||
    with open("/app/script.js", "r") as f:
 | 
			
		||||
        script_raw = bytes(f.read().strip(), "utf-8")
 | 
			
		||||
        b64 = str(base64.b64encode(script_raw), "ascii")
 | 
			
		||||
        script_file = f'data:text/javascript;charset=utf-8;base64,{b64}'
 | 
			
		||||
        template_script = tornado.template.Template(f.read().strip())
 | 
			
		||||
    with open("/app/version/video.js.txt", "r") as f:
 | 
			
		||||
        videojs_version = f.read().strip()
 | 
			
		||||
    with open("/app/version/chromecast.txt", "r") as f:
 | 
			
		||||
@@ -232,18 +204,31 @@ class MainHandler(tornado.web.RequestHandler):
 | 
			
		||||
    async def handle_any(self, redir):
 | 
			
		||||
        handler = UpstreamHandler()
 | 
			
		||||
        await handler.setup(self)
 | 
			
		||||
        if handler.render:
 | 
			
		||||
        if handler.valid:
 | 
			
		||||
            await self.handle_render(handler)
 | 
			
		||||
        elif handler.stream:
 | 
			
		||||
            await self.handle_stream(handler, redir)
 | 
			
		||||
        else:
 | 
			
		||||
            logger.info(f'provider missing {self.request.uri}')
 | 
			
		||||
            self.set_status(404)
 | 
			
		||||
            self.write("Stream not found. (provider missing)")
 | 
			
		||||
    
 | 
			
		||||
    async def handle_render(self, handler):
 | 
			
		||||
        if script_file is not None and template_html is not None:
 | 
			
		||||
            provider_data = await stream_providers.get_any(handler.upstream, handler.proxy, logger)
 | 
			
		||||
        if template_script is not None and template_html is not None:
 | 
			
		||||
            provider_data = None
 | 
			
		||||
            if handler.provider == "nextcloud":
 | 
			
		||||
                provider_data = await stream_providers.get_nextcloud(handler.upstream, handler.proxy, logger)
 | 
			
		||||
            else:
 | 
			
		||||
                provider_data = await stream_providers.get_any(handler.upstream, handler.proxy, logger)
 | 
			
		||||
            proxied = await handler.proxy.proxy_url([provider_data.upstream(), provider_data.thumbnail()])
 | 
			
		||||
 | 
			
		||||
            video_info = {}
 | 
			
		||||
            video_info["upstream"] = proxied[0]
 | 
			
		||||
            video_info["poster"] = proxied[1]
 | 
			
		||||
            video_info["ctype"] = provider_data.ctype()
 | 
			
		||||
 | 
			
		||||
            script = template_script.generate(info=json.dumps(video_info))
 | 
			
		||||
            b64 = str(base64.b64encode(script), "ascii")
 | 
			
		||||
            script_file = f'data:text/javascript;charset=utf-8;base64,{b64}'
 | 
			
		||||
 | 
			
		||||
            data["script"] = script_file
 | 
			
		||||
            data["videojs_version"] = videojs_version
 | 
			
		||||
            data["chromecast_version"] = chromecast_version
 | 
			
		||||
@@ -255,35 +240,6 @@ class MainHandler(tornado.web.RequestHandler):
 | 
			
		||||
            self.set_status(404)
 | 
			
		||||
            self.write("HTML template missing.")
 | 
			
		||||
 | 
			
		||||
    async def handle_stream(self, handler, redir):
 | 
			
		||||
        upstream = None
 | 
			
		||||
        if handler.provider == "nextcloud":
 | 
			
		||||
            upstream = handler.upstream + "/download"
 | 
			
		||||
        else:
 | 
			
		||||
            provider_data = await stream_providers.get_any(handler.upstream, handler.proxy, logger)
 | 
			
		||||
            upstream = provider_data.upstream()
 | 
			
		||||
            if isinstance(provider_data.thumbnail(), str):
 | 
			
		||||
                image = await handler.proxy.proxy_url(provider_data.thumbnail(), None)
 | 
			
		||||
                if isinstance(image, str):
 | 
			
		||||
                    self.set_header("Custom-Poster", image)
 | 
			
		||||
        if upstream is None:
 | 
			
		||||
            logger.info(f'invalid upstream ({handler.provider})')
 | 
			
		||||
            self.set_status(404)
 | 
			
		||||
            self.write("Stream not found. (invalid upstream)")
 | 
			
		||||
        else:
 | 
			
		||||
            upstream_proxy = await handler.proxy.proxy_url(upstream, None)
 | 
			
		||||
            logger.info(upstream_proxy)
 | 
			
		||||
            ctype = await handler.proxy.content_type(upstream_proxy)
 | 
			
		||||
            self.set_header("Content-Type", ctype)
 | 
			
		||||
            if redir:
 | 
			
		||||
                if ctype == "application/vnd.apple.mpegurl":
 | 
			
		||||
                    async with handler.proxy.local() as session:
 | 
			
		||||
                        resp = await session.get(upstream_proxy)
 | 
			
		||||
                        data = await resp.read()
 | 
			
		||||
                        self.write(data)
 | 
			
		||||
                else:
 | 
			
		||||
                    self.redirect(upstream_proxy, status=303)
 | 
			
		||||
 | 
			
		||||
    async def get(self):
 | 
			
		||||
        await self.handle_any(True)
 | 
			
		||||
    async def head(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import requests
 | 
			
		||||
import asyncio
 | 
			
		||||
import html.parser
 | 
			
		||||
import expiringdict
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
streamlink_sessions = {}
 | 
			
		||||
streamlink_default_session = streamlink.Streamlink()
 | 
			
		||||
@@ -41,10 +42,41 @@ class MetaParser(html.parser.HTMLParser):
 | 
			
		||||
                    elif attr[0] == "property" and attr[1] in self.accepted_attrs:
 | 
			
		||||
                        name = attr[1]
 | 
			
		||||
 | 
			
		||||
class NextcloudParser(html.parser.HTMLParser):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.meta_data = {}
 | 
			
		||||
        super().__init__()
 | 
			
		||||
    def handle_starttag_meta(self, attrs):
 | 
			
		||||
        name = None
 | 
			
		||||
        for attr in (attrs + attrs):
 | 
			
		||||
            if len(attr) == 2:
 | 
			
		||||
                if isinstance(name, str):
 | 
			
		||||
                    if attr[0] == "content":
 | 
			
		||||
                        self.meta_data[name] = attr[1]
 | 
			
		||||
                        return
 | 
			
		||||
                elif attr[0] == "property":
 | 
			
		||||
                    name = attr[1]
 | 
			
		||||
    def handle_starttag_input(self, attrs):
 | 
			
		||||
        name = None
 | 
			
		||||
        for attr in (attrs + attrs):
 | 
			
		||||
            if len(attr) == 2:
 | 
			
		||||
                if isinstance(name, str):
 | 
			
		||||
                    if attr[0] == "value":
 | 
			
		||||
                        self.meta_data[name] = attr[1]
 | 
			
		||||
                        return
 | 
			
		||||
                elif attr[0] == "name":
 | 
			
		||||
                    name = attr[1]
 | 
			
		||||
    def handle_starttag(self, tag, attrs):
 | 
			
		||||
        if tag == "meta":
 | 
			
		||||
            return self.handle_starttag_meta(attrs)
 | 
			
		||||
        elif tag == "input":
 | 
			
		||||
            return self.handle_starttag_input(attrs)
 | 
			
		||||
 | 
			
		||||
class StreamData():
 | 
			
		||||
    def __init__(self, upstream, thumbnail, title, description, override):
 | 
			
		||||
    def __init__(self, upstream, ctype, thumbnail, title, description, override):
 | 
			
		||||
        self.values = {}
 | 
			
		||||
        self.values["upstream"] = upstream
 | 
			
		||||
        self.values["ctype"] = ctype
 | 
			
		||||
        self.values["thumbnail"] = thumbnail
 | 
			
		||||
        self.values["title"] = title
 | 
			
		||||
        self.values["description"] = description
 | 
			
		||||
@@ -56,6 +88,8 @@ class StreamData():
 | 
			
		||||
            self.values[key] = value
 | 
			
		||||
    def upstream(self):
 | 
			
		||||
        return self.values.get("upstream")
 | 
			
		||||
    def ctype(self):
 | 
			
		||||
        return self.values.get("ctype")
 | 
			
		||||
    def thumbnail(self):
 | 
			
		||||
        return self.values.get("thumbnail")
 | 
			
		||||
    def title(self):
 | 
			
		||||
@@ -83,10 +117,27 @@ class StreamProvider():
 | 
			
		||||
        proxy = str(proxy)
 | 
			
		||||
        if len(proxy) > 5:
 | 
			
		||||
            self.proxy = proxy
 | 
			
		||||
    def process(self):
 | 
			
		||||
        data = self.stream()
 | 
			
		||||
        if not isinstance(data.upstream(), str):
 | 
			
		||||
            return data
 | 
			
		||||
        proxies = None
 | 
			
		||||
        if isinstance(self.proxy, str):
 | 
			
		||||
            proxies = {}
 | 
			
		||||
            proxies["http"] = "socks5://" + self.proxy
 | 
			
		||||
            proxies["https"] = "socks5://" + self.proxy
 | 
			
		||||
        ctype = "binary/octet-stream"
 | 
			
		||||
        try:
 | 
			
		||||
            resp = requests.head(data.upstream(), proxies=proxies)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.logger.info(e)
 | 
			
		||||
        else:
 | 
			
		||||
            ctype = resp.headers.get("Content-Type", "binary/octet-stream")
 | 
			
		||||
        return StreamData(data.upstream(), ctype, data.thumbnail(), data.title(), data.description(), data.override)
 | 
			
		||||
    async def run(self):
 | 
			
		||||
        data = None
 | 
			
		||||
        try:
 | 
			
		||||
            future = asyncio.to_thread(self.stream)
 | 
			
		||||
            future = asyncio.to_thread(self.process)
 | 
			
		||||
            data = await asyncio.wait_for(future, timeout=5)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.logger.info(e)
 | 
			
		||||
@@ -106,10 +157,10 @@ class StreamlinkRunner(StreamProvider):
 | 
			
		||||
                for key in reversed(streams):
 | 
			
		||||
                    stream = streams.get(key)
 | 
			
		||||
                    if hasattr(stream, "url"):
 | 
			
		||||
                        return StreamData(stream.url, None, None, None, False)
 | 
			
		||||
                        return StreamData(stream.url, None, None, None, None, False)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.logger.info(e)
 | 
			
		||||
        return StreamData(None, None, None, None, False)
 | 
			
		||||
        return StreamData(None, None, None, None, None, False)
 | 
			
		||||
 | 
			
		||||
class YoutubeRunner(StreamProvider):
 | 
			
		||||
    def stream(self):
 | 
			
		||||
@@ -153,7 +204,20 @@ class YoutubeRunner(StreamProvider):
 | 
			
		||||
                            best_url = new_url
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.logger.info(e)
 | 
			
		||||
        return StreamData(best_url, thumbnail, title, description, True)
 | 
			
		||||
        print(json.dumps(best_format, indent=4))
 | 
			
		||||
        return StreamData(best_url, None, thumbnail, title, description, True)
 | 
			
		||||
 | 
			
		||||
class NextcloudRunner(StreamProvider):
 | 
			
		||||
    def stream(self):
 | 
			
		||||
        data = {}
 | 
			
		||||
        try:
 | 
			
		||||
            resp = requests.get(self.upstream)
 | 
			
		||||
            parser = NextcloudParser()
 | 
			
		||||
            parser.feed(resp.text)
 | 
			
		||||
            data = parser.meta_data
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.logger.info(e)
 | 
			
		||||
        return StreamData(data.get("downloadURL"), data.get("mimetype"), None, data.get("og:title"), data.get("og:description"), False)
 | 
			
		||||
 | 
			
		||||
class MetaRunner(StreamProvider):
 | 
			
		||||
    def stream(self):
 | 
			
		||||
@@ -165,7 +229,7 @@ class MetaRunner(StreamProvider):
 | 
			
		||||
            data = parser.meta_data
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.logger.info(e)
 | 
			
		||||
        return StreamData(None, data.get("og:image"), data.get("og:title"), data.get("og:description"), False)
 | 
			
		||||
        return StreamData(None, None, data.get("og:image"), data.get("og:title"), data.get("og:description"), False)
 | 
			
		||||
 | 
			
		||||
upstream_cache = expiringdict.ExpiringDict(max_len=512, max_age_seconds=1800)
 | 
			
		||||
 | 
			
		||||
@@ -192,8 +256,11 @@ async def get_ytdl(upstream, proxy, logger):
 | 
			
		||||
async def get_meta(upstream, proxy, logger):
 | 
			
		||||
    return await get_from_runner((2, upstream), MetaRunner(upstream, proxy, logger), logger)
 | 
			
		||||
 | 
			
		||||
async def get_nextcloud(upstream, proxy, logger):
 | 
			
		||||
    return await get_from_runner((3, upstream), NextcloudRunner(upstream, proxy, logger), logger)
 | 
			
		||||
 | 
			
		||||
async def get_any(upstream, proxy, logger):
 | 
			
		||||
    cache_key = (3, upstream)
 | 
			
		||||
    cache_key = (4, upstream)
 | 
			
		||||
    cached = upstream_cache.get(cache_key)
 | 
			
		||||
    if isinstance(cached, StreamData):
 | 
			
		||||
        return cached
 | 
			
		||||
@@ -201,7 +268,8 @@ async def get_any(upstream, proxy, logger):
 | 
			
		||||
    tasks.append(asyncio.create_task(get_streamlink(upstream, proxy, logger)))
 | 
			
		||||
    tasks.append(asyncio.create_task(get_ytdl(upstream, proxy, logger)))
 | 
			
		||||
    tasks.append(asyncio.create_task(get_meta(upstream, proxy, logger)))
 | 
			
		||||
    result = StreamData(None, None, None, None, False)
 | 
			
		||||
 | 
			
		||||
    result = StreamData(None, None, None, None, None, False)
 | 
			
		||||
    for task in asyncio.as_completed(tasks):
 | 
			
		||||
        temp_result = await task
 | 
			
		||||
        if isinstance(temp_result, StreamData):
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,4 @@
 | 
			
		||||
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/{{ data["font_awesome_version"] }}/css/all.min.css">
 | 
			
		||||
        <link rel="stylesheet" href="{{ data["custom_style"] }}">
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +1,10 @@
 | 
			
		||||
(() => {
 | 
			
		||||
    const findUpstreamVideo = () => {
 | 
			
		||||
        const search = new URLSearchParams(location.search);
 | 
			
		||||
        search.set("render", "false");
 | 
			
		||||
        const url = new URL(location.origin);
 | 
			
		||||
        url.pathname = location.pathname;
 | 
			
		||||
        url.search = search.toString();
 | 
			
		||||
        return url.href;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const upstream = findUpstreamVideo();
 | 
			
		||||
    const xhr = new XMLHttpRequest();
 | 
			
		||||
    xhr.open("HEAD", upstream, true);
 | 
			
		||||
    xhr.send();
 | 
			
		||||
 | 
			
		||||
    let count = 2;
 | 
			
		||||
    const handleCount = () => {
 | 
			
		||||
        if(--count === 0) {
 | 
			
		||||
            handle();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const info = {% raw info %};
 | 
			
		||||
    const handle = () => {
 | 
			
		||||
        const [body] = document.getElementsByTagName("body");
 | 
			
		||||
        const video = document.createElement("video");
 | 
			
		||||
        video.className = "video-js vjs-big-play-centered";
 | 
			
		||||
        body.appendChild(video);
 | 
			
		||||
        const ctype = xhr.getResponseHeader("Content-Type");
 | 
			
		||||
        const image = xhr.getResponseHeader("Custom-Poster");
 | 
			
		||||
        console.log(ctype);
 | 
			
		||||
        const options = {};
 | 
			
		||||
        options.controls = true;
 | 
			
		||||
        options.liveui = true;
 | 
			
		||||
@@ -38,14 +15,14 @@
 | 
			
		||||
        options.plugins.chromecast = {};
 | 
			
		||||
        options.plugins.chromecast.addButtonToControlBar = false;
 | 
			
		||||
        const player = videojs(video, options);
 | 
			
		||||
        if((image instanceof String) || ((typeof image) == "string")) {
 | 
			
		||||
            player.poster(image);
 | 
			
		||||
        if((info.poster instanceof String) || ((typeof info.poster) == "string")) {
 | 
			
		||||
            player.poster(info.poster);
 | 
			
		||||
        }
 | 
			
		||||
        const source = {};
 | 
			
		||||
        source.type = ctype;
 | 
			
		||||
        source.src = upstream;
 | 
			
		||||
        source.type = info.ctype;
 | 
			
		||||
        source.src = info.upstream;
 | 
			
		||||
        player.src(source);
 | 
			
		||||
        const canPlayTypeRaw = player.canPlayType(ctype);
 | 
			
		||||
        const canPlayTypeRaw = player.canPlayType(info.ctype);
 | 
			
		||||
        const canPlayType = (canPlayTypeRaw === "maybe") || (canPlayTypeRaw === "probably");
 | 
			
		||||
        if(canPlayType) {
 | 
			
		||||
            const Button = videojs.getComponent("Button");
 | 
			
		||||
@@ -84,6 +61,5 @@
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    document.addEventListener("DOMContentLoaded", handleCount);
 | 
			
		||||
    xhr.addEventListener("load", handleCount);
 | 
			
		||||
    document.addEventListener("DOMContentLoaded", handle);
 | 
			
		||||
})();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user