streamlink / streamlink
Showing 1 of 1 files from the diff.

@@ -1,13 +1,12 @@
Loading
1 1
import logging
2 2
import re
3 -
from html import unescape as html_unescape
4 3
from urllib.parse import unquote
5 4
6 5
from streamlink.plugin import Plugin, PluginError, pluginmatcher
7 6
from streamlink.plugin.api import validate
7 +
from streamlink.stream.dash import DASHStream
8 8
from streamlink.stream.hls import HLSStream
9 9
from streamlink.stream.http import HTTPStream
10 -
from streamlink.stream.rtmpdump import RTMPStream
11 10
12 11
log = logging.getLogger(__name__)
13 12
@@ -16,96 +15,93 @@
Loading
16 15
    r'https?://(?:www\.)?ok\.ru/'
17 16
))
18 17
class OKru(Plugin):
19 -
    _data_re = re.compile(r'''data-options=(?P<q>["'])(?P<data>{[^"']+})(?P=q)''')
20 -
21 -
    _metadata_schema = validate.Schema(
22 -
        validate.parse_json(),
23 -
        validate.any({
24 -
            'videos': validate.any(
25 -
                [],
26 -
                [
27 -
                    {
28 -
                        'name': validate.text,
29 -
                        'url': validate.text,
30 -
                    }
31 -
                ]
32 -
            ),
33 -
            validate.optional('hlsManifestUrl'): validate.text,
34 -
            validate.optional('hlsMasterPlaylistUrl'): validate.text,
35 -
            validate.optional('liveDashManifestUrl'): validate.text,
36 -
            validate.optional('rtmpUrl'): validate.text,
37 -
        }, None)
38 -
    )
39 -
    _data_schema = validate.Schema(
40 -
        validate.all(
41 -
            validate.transform(_data_re.search),
42 -
            validate.get('data'),
43 -
            validate.transform(html_unescape),
44 -
            validate.parse_json(),
45 -
            validate.get('flashvars'),
46 -
            validate.any({
47 -
                'metadata': _metadata_schema
48 -
            }, {
49 -
                'metadataUrl': validate.transform(unquote)
50 -
            }, None)
51 -
        )
52 -
    )
53 -
54 18
    QUALITY_WEIGHTS = {
55 -
        'full': 1080,
56 -
        '1080': 1080,
57 -
        'hd': 720,
58 -
        '720': 720,
59 -
        'sd': 480,
60 -
        '480': 480,
61 -
        '360': 360,
62 -
        'low': 360,
63 -
        'lowest': 240,
64 -
        'mobile': 144,
19 +
        "full": 1080,
20 +
        "1080": 1080,
21 +
        "hd": 720,
22 +
        "720": 720,
23 +
        "sd": 480,
24 +
        "480": 480,
25 +
        "360": 360,
26 +
        "low": 360,
27 +
        "lowest": 240,
28 +
        "mobile": 144,
65 29
    }
66 30
67 31
    @classmethod
68 32
    def stream_weight(cls, key):
69 33
        weight = cls.QUALITY_WEIGHTS.get(key)
70 34
        if weight:
71 -
            return weight, 'okru'
35 +
            return weight, "okru"
72 36
73 -
        return Plugin.stream_weight(key)
37 +
        return super().stream_weight(key)
74 38
75 39
    def _get_streams(self):
76 -
        self.session.http.headers.update({'Referer': self.url})
40 +
        schema_metadata = validate.Schema(
41 +
            validate.parse_json(),
42 +
            {
43 +
                validate.optional("author"): validate.all({"name": str}, validate.get("name")),
44 +
                validate.optional("movie"): validate.all({"title": str}, validate.get("title")),
45 +
                validate.optional("hlsManifestUrl"): validate.url(),
46 +
                validate.optional("hlsMasterPlaylistUrl"): validate.url(),
47 +
                validate.optional("liveDashManifestUrl"): validate.url(),
48 +
                validate.optional("videos"): [validate.all(
49 +
                    {
50 +
                        "name": str,
51 +
                        "url": validate.url()
52 +
                    },
53 +
                    validate.union_get("name", "url")
54 +
                )]
55 +
            }
56 +
        )
77 57
78 58
        try:
79 -
            data = self.session.http.get(self.url, schema=self._data_schema)
59 +
            metadata, metadata_url = self.session.http.get(self.url, schema=validate.Schema(
60 +
                validate.parse_html(),
61 +
                validate.xml_find(".//*[@data-options]"),
62 +
                validate.get("data-options"),
63 +
                validate.parse_json(),
64 +
                {"flashvars": {
65 +
                    validate.optional("metadata"): str,
66 +
                    validate.optional("metadataUrl"): validate.all(
67 +
                        validate.transform(unquote),
68 +
                        validate.url()
69 +
                    )
70 +
                }},
71 +
                validate.get("flashvars"),
72 +
                validate.union_get("metadata", "metadataUrl")
73 +
            ))
80 74
        except PluginError:
81 -
            log.error('unable to validate _data_schema for {0}'.format(self.url))
75 +
            log.error("Could not find metadata")
82 76
            return
83 77
84 -
        metadata = data.get('metadata')
85 -
        metadata_url = data.get('metadataUrl')
86 -
        if metadata_url and not metadata:
87 -
            metadata = self.session.http.post(metadata_url,
88 -
                                              schema=self._metadata_schema)
89 -
90 -
        if metadata:
91 -
            log.trace('{0!r}'.format(metadata))
92 -
            for hls_url in [metadata.get('hlsManifestUrl'),
93 -
                            metadata.get('hlsMasterPlaylistUrl')]:
94 -
                if hls_url is not None:
95 -
                    yield from HLSStream.parse_variant_playlist(self.session, hls_url).items()
96 -
97 -
            if metadata.get('videos'):
98 -
                for http_stream in metadata['videos']:
99 -
                    http_name = http_stream['name']
100 -
                    http_url = http_stream['url']
101 -
                    try:
102 -
                        http_name = '{0}p'.format(self.QUALITY_WEIGHTS[http_name])
103 -
                    except KeyError:
104 -
                        pass
105 -
                    yield http_name, HTTPStream(self.session, http_url)
106 -
107 -
            if metadata.get('rtmpUrl'):
108 -
                yield 'live', RTMPStream(self.session, params={'rtmp': metadata['rtmpUrl']})
78 +
        self.session.http.headers.update({"Referer": self.url})
79 +
80 +
        if not metadata and metadata_url:
81 +
            metadata = self.session.http.post(metadata_url).text
82 +
83 +
        log.trace(f"{metadata!r}")
84 +
85 +
        try:
86 +
            data = schema_metadata.validate(metadata)
87 +
        except PluginError:
88 +
            log.error("Could not parse metadata")
89 +
            return
90 +
91 +
        self.author = data.get("author")
92 +
        self.title = data.get("movie")
93 +
94 +
        for hls_url in data.get("hlsManifestUrl"), data.get("hlsMasterPlaylistUrl"):
95 +
            if hls_url is not None:
96 +
                return HLSStream.parse_variant_playlist(self.session, hls_url)
97 +
98 +
        if data.get("liveDashManifestUrl"):
99 +
            return DASHStream.parse_manifest(self.session, data.get("liveDashManifestUrl"))
100 +
101 +
        return {
102 +
            f"{self.QUALITY_WEIGHTS[name]}p" if name in self.QUALITY_WEIGHTS else name: HTTPStream(self.session, url)
103 +
            for name, url in data.get("videos", [])
104 +
        }
109 105
110 106
111 107
__plugin__ = OKru
Files Coverage
src 53.10%
tests 100.00%
Project Totals (430 files) 66.55%
os:ubuntu-20.04 py:3.7
Build #1330021559 -
os:ubuntu-20.04 py:3.10
Build #1330021559 -
os:ubuntu-20.04 py:3.9
Build #1330021559 -
os:ubuntu-20.04 py:3.8
Build #1330021559 -
os:windows-latest py:3.6
Build #1330021559 -
os:ubuntu-20.04 py:3.6
Build #1330021559 -
os:windows-latest py:3.9
Build #1330021559 -
os:windows-latest py:3.8
Build #1330021559 -
os:windows-latest py:3.10
Build #1330021559 -
os:windows-latest py:3.7
Build #1330021559 -

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading