mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-13 12:35:05 +00:00
Deployed c6ecdb6 with MkDocs version: 1.6.1
This commit is contained in:
+193
-180
@@ -2064,6 +2064,18 @@ split is exactly why every URL lives in <code>config.yaml</code> with <code>{}</
|
||||
placeholders while the secrets that fill them stay out of it. Both halves
|
||||
read back through the same <code>self.config[...]</code>.</p>
|
||||
</div>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Split across files? Use relative imports</p>
|
||||
<p>If your service grows beyond a single <code>__init__.py</code>, import your own
|
||||
modules <strong>relatively</strong>:</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">.helpers</span><span class="w"> </span><span class="kn">import</span> <span class="n">parse_manifest</span> <span class="c1"># correct</span>
|
||||
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.services.TAG.helpers</span><span class="w"> </span><span class="kn">import</span> <span class="n">parse_manifest</span> <span class="c1"># breaks from a repo</span>
|
||||
</span></code></pre></div>
|
||||
<p>A service loaded from a remote repo lives outside the <code>unshackle</code> package,
|
||||
so the absolute <code>unshackle.services.<TAG>.*</code> path does not resolve and the
|
||||
import fails with <code>no known parent package</code>. Relative imports work both
|
||||
locally and from a cloned repo.</p>
|
||||
</div>
|
||||
<hr />
|
||||
<h2 id="the-service-base-class">The Service base class<a class="headerlink" href="#the-service-base-class" title="Permanent link">¶</a></h2>
|
||||
<p>Every service subclasses <code>unshackle.core.service.Service</code>. The minimum is a
|
||||
@@ -2116,10 +2128,10 @@ subtitle work for services that never carry subtitles; leave it off otherwise.</
|
||||
<p><code>GEOFENCE</code> drives an automatic proxy: on startup, if you did not pass an
|
||||
explicit <code>--proxy</code>, the base class does a live IP check and, if your region is
|
||||
blocked, fetches a proxy to <code>GEOFENCE[0]</code> from your configured proxy providers.</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="k">class</span><span class="w"> </span><span class="nc">EXAMPLE</span><span class="p">(</span><span class="n">Service</span><span class="p">):</span>
|
||||
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a> <span class="n">ALIASES</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"EX"</span><span class="p">,</span> <span class="s2">"DOMAIN"</span><span class="p">)</span>
|
||||
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a> <span class="n">GEOFENCE</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"US"</span><span class="p">,</span> <span class="s2">"UK"</span><span class="p">)</span>
|
||||
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a> <span class="n">VAULT_TAG</span> <span class="o">=</span> <span class="s2">"DIFFERENT_NAME"</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="k">class</span><span class="w"> </span><span class="nc">EXAMPLE</span><span class="p">(</span><span class="n">Service</span><span class="p">):</span>
|
||||
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a> <span class="n">ALIASES</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"EX"</span><span class="p">,</span> <span class="s2">"DOMAIN"</span><span class="p">)</span>
|
||||
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a> <span class="n">GEOFENCE</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"US"</span><span class="p">,</span> <span class="s2">"UK"</span><span class="p">)</span>
|
||||
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a> <span class="n">VAULT_TAG</span> <span class="o">=</span> <span class="s2">"DIFFERENT_NAME"</span>
|
||||
</span></code></pre></div>
|
||||
<h3 id="what-service__init__-wires-up">What <code>Service.__init__</code> wires up<a class="headerlink" href="#what-service__init__-wires-up" title="Permanent link">¶</a></h3>
|
||||
<p>When you call <code>super().__init__(ctx)</code>, the base class sets up the attributes you
|
||||
@@ -2172,11 +2184,11 @@ will use throughout the service:</p>
|
||||
</table>
|
||||
<p><code>self.track_request</code> is a small dataclass you can read <em>and rewrite</em> before
|
||||
fetching tracks:</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="nd">@dataclass</span>
|
||||
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="k">class</span><span class="w"> </span><span class="nc">TrackRequest</span><span class="p">:</span>
|
||||
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a> <span class="n">codecs</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Codec</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># empty == accept any codec</span>
|
||||
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a> <span class="n">ranges</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="o">.</span><span class="n">SDR</span><span class="p">]</span>
|
||||
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a> <span class="n">best_available</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="nd">@dataclass</span>
|
||||
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="k">class</span><span class="w"> </span><span class="nc">TrackRequest</span><span class="p">:</span>
|
||||
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a> <span class="n">codecs</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Codec</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># empty == accept any codec</span>
|
||||
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a> <span class="n">ranges</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="o">.</span><span class="n">SDR</span><span class="p">]</span>
|
||||
</span><span id="__span-4-5"><a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a> <span class="n">best_available</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
</span></code></pre></div>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Read the request, don't second-guess the user</p>
|
||||
@@ -2213,21 +2225,21 @@ just produces confusing <code>--help</code>/usage output that names the wrong co
|
||||
That confusing output is the reason to keep it in sync, not any dispatch
|
||||
requirement.</p>
|
||||
</div>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="nd">@staticmethod</span>
|
||||
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="nd">@click</span><span class="o">.</span><span class="n">command</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"EXAMPLE"</span><span class="p">,</span> <span class="n">short_help</span><span class="o">=</span><span class="s2">"https://domain.com"</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="vm">__doc__</span><span class="p">)</span>
|
||||
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="nd">@click</span><span class="o">.</span><span class="n">argument</span><span class="p">(</span><span class="s2">"title"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">)</span>
|
||||
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="nd">@click</span><span class="o">.</span><span class="n">option</span><span class="p">(</span><span class="s2">"-m"</span><span class="p">,</span> <span class="s2">"--movie"</span><span class="p">,</span> <span class="n">is_flag</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s2">"Treat the title as a movie."</span><span class="p">)</span>
|
||||
</span><span id="__span-4-5"><a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a><span class="nd">@click</span><span class="o">.</span><span class="n">option</span><span class="p">(</span><span class="s2">"-d"</span><span class="p">,</span> <span class="s2">"--device"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="n">click</span><span class="o">.</span><span class="n">Choice</span><span class="p">([</span><span class="s2">"android_tv"</span><span class="p">,</span> <span class="s2">"web"</span><span class="p">,</span> <span class="s2">"ios"</span><span class="p">]),</span> <span class="n">default</span><span class="o">=</span><span class="s2">"android_tv"</span><span class="p">)</span>
|
||||
</span><span id="__span-4-6"><a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a><span class="nd">@click</span><span class="o">.</span><span class="n">pass_context</span>
|
||||
</span><span id="__span-4-7"><a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a><span class="k">def</span><span class="w"> </span><span class="nf">cli</span><span class="p">(</span><span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-></span> <span class="n">EXAMPLE</span><span class="p">:</span>
|
||||
</span><span id="__span-4-8"><a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a> <span class="k">return</span> <span class="n">EXAMPLE</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
</span><span id="__span-4-9"><a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a>
|
||||
</span><span id="__span-4-10"><a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a><span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">movie</span><span class="p">:</span> <span class="nb">bool</span><span class="p">,</span> <span class="n">device</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
|
||||
</span><span id="__span-4-11"><a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a> <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
|
||||
</span><span id="__span-4-12"><a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a> <span class="bp">self</span><span class="o">.</span><span class="n">movie</span> <span class="o">=</span> <span class="n">movie</span>
|
||||
</span><span id="__span-4-13"><a id="__codelineno-4-13" name="__codelineno-4-13" href="#__codelineno-4-13"></a> <span class="bp">self</span><span class="o">.</span><span class="n">device</span> <span class="o">=</span> <span class="n">device</span>
|
||||
</span><span id="__span-4-14"><a id="__codelineno-4-14" name="__codelineno-4-14" href="#__codelineno-4-14"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span> <span class="c1"># wires up config, log, session, caches, track_request...</span>
|
||||
</span><span id="__span-4-15"><a id="__codelineno-4-15" name="__codelineno-4-15" href="#__codelineno-4-15"></a> <span class="bp">self</span><span class="o">.</span><span class="n">cdm</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">cdm</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="nd">@staticmethod</span>
|
||||
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="nd">@click</span><span class="o">.</span><span class="n">command</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"EXAMPLE"</span><span class="p">,</span> <span class="n">short_help</span><span class="o">=</span><span class="s2">"https://domain.com"</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="vm">__doc__</span><span class="p">)</span>
|
||||
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="nd">@click</span><span class="o">.</span><span class="n">argument</span><span class="p">(</span><span class="s2">"title"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">)</span>
|
||||
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="nd">@click</span><span class="o">.</span><span class="n">option</span><span class="p">(</span><span class="s2">"-m"</span><span class="p">,</span> <span class="s2">"--movie"</span><span class="p">,</span> <span class="n">is_flag</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s2">"Treat the title as a movie."</span><span class="p">)</span>
|
||||
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="nd">@click</span><span class="o">.</span><span class="n">option</span><span class="p">(</span><span class="s2">"-d"</span><span class="p">,</span> <span class="s2">"--device"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="n">click</span><span class="o">.</span><span class="n">Choice</span><span class="p">([</span><span class="s2">"android_tv"</span><span class="p">,</span> <span class="s2">"web"</span><span class="p">,</span> <span class="s2">"ios"</span><span class="p">]),</span> <span class="n">default</span><span class="o">=</span><span class="s2">"android_tv"</span><span class="p">)</span>
|
||||
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a><span class="nd">@click</span><span class="o">.</span><span class="n">pass_context</span>
|
||||
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a><span class="k">def</span><span class="w"> </span><span class="nf">cli</span><span class="p">(</span><span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-></span> <span class="n">EXAMPLE</span><span class="p">:</span>
|
||||
</span><span id="__span-5-8"><a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a> <span class="k">return</span> <span class="n">EXAMPLE</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
</span><span id="__span-5-9"><a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a>
|
||||
</span><span id="__span-5-10"><a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a><span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">movie</span><span class="p">:</span> <span class="nb">bool</span><span class="p">,</span> <span class="n">device</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
|
||||
</span><span id="__span-5-11"><a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a> <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
|
||||
</span><span id="__span-5-12"><a id="__codelineno-5-12" name="__codelineno-5-12" href="#__codelineno-5-12"></a> <span class="bp">self</span><span class="o">.</span><span class="n">movie</span> <span class="o">=</span> <span class="n">movie</span>
|
||||
</span><span id="__span-5-13"><a id="__codelineno-5-13" name="__codelineno-5-13" href="#__codelineno-5-13"></a> <span class="bp">self</span><span class="o">.</span><span class="n">device</span> <span class="o">=</span> <span class="n">device</span>
|
||||
</span><span id="__span-5-14"><a id="__codelineno-5-14" name="__codelineno-5-14" href="#__codelineno-5-14"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span> <span class="c1"># wires up config, log, session, caches, track_request...</span>
|
||||
</span><span id="__span-5-15"><a id="__codelineno-5-15" name="__codelineno-5-15" href="#__codelineno-5-15"></a> <span class="bp">self</span><span class="o">.</span><span class="n">cdm</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">cdm</span>
|
||||
</span></code></pre></div>
|
||||
<p>Your docstring becomes the CLI <code>--help</code> text (<code>help=__doc__</code>), so document the
|
||||
accepted URL/ID formats and options there.</p>
|
||||
@@ -2244,17 +2256,17 @@ manifest endpoint based on which DRM the CDM speaks.</p>
|
||||
first</strong>: the base implementation loads the cookie jar into <code>self.session.cookies</code>
|
||||
and stores <code>self.credential</code>. Do all token fetching here; it runs before
|
||||
<code>get_titles</code>.</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cookies</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">credential</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">authenticate</span><span class="p">(</span><span class="n">cookies</span><span class="p">,</span> <span class="n">credential</span><span class="p">)</span>
|
||||
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">"user-agent"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"client"</span><span class="p">][</span><span class="bp">self</span><span class="o">.</span><span class="n">device</span><span class="p">][</span><span class="s2">"user_agent"</span><span class="p">]})</span>
|
||||
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a>
|
||||
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a> <span class="n">cache</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="sa">f</span><span class="s2">"tokens_</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">device</span><span class="si">}</span><span class="s2">_</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">profile</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a> <span class="k">if</span> <span class="n">cache</span> <span class="ow">and</span> <span class="n">cache</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"expires_in"</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">></span> <span class="nb">int</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">timestamp</span><span class="p">()):</span>
|
||||
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">" + Using cached tokens"</span><span class="p">)</span>
|
||||
</span><span id="__span-5-8"><a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a> <span class="k">else</span><span class="p">:</span>
|
||||
</span><span id="__span-5-9"><a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a> <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"login"</span><span class="p">],</span> <span class="n">data</span><span class="o">=</span><span class="n">body</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-5-10"><a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a> <span class="n">cache</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="n">token</span><span class="p">,</span> <span class="n">expiration</span><span class="o">=</span><span class="n">token</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"expires_in"</span><span class="p">))</span>
|
||||
</span><span id="__span-5-11"><a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a> <span class="bp">self</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">cache</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="s2">"token"</span><span class="p">]</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cookies</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">credential</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">authenticate</span><span class="p">(</span><span class="n">cookies</span><span class="p">,</span> <span class="n">credential</span><span class="p">)</span>
|
||||
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">"user-agent"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"client"</span><span class="p">][</span><span class="bp">self</span><span class="o">.</span><span class="n">device</span><span class="p">][</span><span class="s2">"user_agent"</span><span class="p">]})</span>
|
||||
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>
|
||||
</span><span id="__span-6-5"><a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a> <span class="n">cache</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="sa">f</span><span class="s2">"tokens_</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">device</span><span class="si">}</span><span class="s2">_</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">profile</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
</span><span id="__span-6-6"><a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a> <span class="k">if</span> <span class="n">cache</span> <span class="ow">and</span> <span class="n">cache</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"expires_in"</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">></span> <span class="nb">int</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">timestamp</span><span class="p">()):</span>
|
||||
</span><span id="__span-6-7"><a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">" + Using cached tokens"</span><span class="p">)</span>
|
||||
</span><span id="__span-6-8"><a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a> <span class="k">else</span><span class="p">:</span>
|
||||
</span><span id="__span-6-9"><a id="__codelineno-6-9" name="__codelineno-6-9" href="#__codelineno-6-9"></a> <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"login"</span><span class="p">],</span> <span class="n">data</span><span class="o">=</span><span class="n">body</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-6-10"><a id="__codelineno-6-10" name="__codelineno-6-10" href="#__codelineno-6-10"></a> <span class="n">cache</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="n">token</span><span class="p">,</span> <span class="n">expiration</span><span class="o">=</span><span class="n">token</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"expires_in"</span><span class="p">))</span>
|
||||
</span><span id="__span-6-11"><a id="__codelineno-6-11" name="__codelineno-6-11" href="#__codelineno-6-11"></a> <span class="bp">self</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">cache</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="s2">"token"</span><span class="p">]</span>
|
||||
</span></code></pre></div>
|
||||
<p>Cookies come from files under <code>directories.cookies</code>; credentials from the
|
||||
<code>credentials</code> map in <code>unshackle.yaml</code>. For interactive prompts (OTP, captcha)
|
||||
@@ -2309,44 +2321,44 @@ identity for you.</p>
|
||||
<p>Every title carries a <code>language</code> (its <strong>original recorded language</strong>) and an
|
||||
arbitrary <code>data</code> dict you can use to stash metadata for later methods. At least
|
||||
one title must be returned, or the ID is treated as invalid.</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_titles</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Titles_T</span><span class="p">:</span>
|
||||
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a> <span class="n">match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">TITLE_RE</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
|
||||
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span>
|
||||
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Could not parse a title ID - is the URL/ID correct?"</span><span class="p">)</span>
|
||||
</span><span id="__span-6-5"><a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a> <span class="n">metadata</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
|
||||
</span><span id="__span-6-6"><a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"metadata"</span><span class="p">]</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">title_id</span><span class="o">=</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"title_id"</span><span class="p">)),</span>
|
||||
</span><span id="__span-6-7"><a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a> <span class="n">params</span><span class="o">=</span><span class="p">{</span><span class="s2">"token"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">token</span><span class="p">},</span>
|
||||
</span><span id="__span-6-8"><a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a> <span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-6-9"><a id="__codelineno-6-9" name="__codelineno-6-9" href="#__codelineno-6-9"></a> <span class="n">original_lang</span> <span class="o">=</span> <span class="n">Language</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">metadata</span><span class="p">[</span><span class="s2">"languages"</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
|
||||
</span><span id="__span-6-10"><a id="__codelineno-6-10" name="__codelineno-6-10" href="#__codelineno-6-10"></a>
|
||||
</span><span id="__span-6-11"><a id="__codelineno-6-11" name="__codelineno-6-11" href="#__codelineno-6-11"></a> <span class="k">return</span> <span class="n">Movies</span><span class="p">([</span>
|
||||
</span><span id="__span-6-12"><a id="__codelineno-6-12" name="__codelineno-6-12" href="#__codelineno-6-12"></a> <span class="n">Movie</span><span class="p">(</span>
|
||||
</span><span id="__span-6-13"><a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a> <span class="n">id_</span><span class="o">=</span><span class="n">metadata</span><span class="p">[</span><span class="s2">"id"</span><span class="p">],</span>
|
||||
</span><span id="__span-6-14"><a id="__codelineno-6-14" name="__codelineno-6-14" href="#__codelineno-6-14"></a> <span class="n">service</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span>
|
||||
</span><span id="__span-6-15"><a id="__codelineno-6-15" name="__codelineno-6-15" href="#__codelineno-6-15"></a> <span class="n">name</span><span class="o">=</span><span class="n">metadata</span><span class="p">[</span><span class="s2">"title"</span><span class="p">],</span>
|
||||
</span><span id="__span-6-16"><a id="__codelineno-6-16" name="__codelineno-6-16" href="#__codelineno-6-16"></a> <span class="n">year</span><span class="o">=</span><span class="n">metadata</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"releaseYear"</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span><span class="p">,</span>
|
||||
</span><span id="__span-6-17"><a id="__codelineno-6-17" name="__codelineno-6-17" href="#__codelineno-6-17"></a> <span class="n">language</span><span class="o">=</span><span class="n">original_lang</span><span class="p">,</span> <span class="c1"># ORIGINAL audio language, not the -l preference</span>
|
||||
</span><span id="__span-6-18"><a id="__codelineno-6-18" name="__codelineno-6-18" href="#__codelineno-6-18"></a> <span class="n">data</span><span class="o">=</span><span class="n">metadata</span><span class="p">,</span> <span class="c1"># read later as title.data</span>
|
||||
</span><span id="__span-6-19"><a id="__codelineno-6-19" name="__codelineno-6-19" href="#__codelineno-6-19"></a> <span class="p">)</span>
|
||||
</span><span id="__span-6-20"><a id="__codelineno-6-20" name="__codelineno-6-20" href="#__codelineno-6-20"></a> <span class="p">])</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_titles</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Titles_T</span><span class="p">:</span>
|
||||
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a> <span class="n">match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">TITLE_RE</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
|
||||
</span><span id="__span-7-3"><a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span>
|
||||
</span><span id="__span-7-4"><a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Could not parse a title ID - is the URL/ID correct?"</span><span class="p">)</span>
|
||||
</span><span id="__span-7-5"><a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a> <span class="n">metadata</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
|
||||
</span><span id="__span-7-6"><a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"metadata"</span><span class="p">]</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">title_id</span><span class="o">=</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"title_id"</span><span class="p">)),</span>
|
||||
</span><span id="__span-7-7"><a id="__codelineno-7-7" name="__codelineno-7-7" href="#__codelineno-7-7"></a> <span class="n">params</span><span class="o">=</span><span class="p">{</span><span class="s2">"token"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">token</span><span class="p">},</span>
|
||||
</span><span id="__span-7-8"><a id="__codelineno-7-8" name="__codelineno-7-8" href="#__codelineno-7-8"></a> <span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-7-9"><a id="__codelineno-7-9" name="__codelineno-7-9" href="#__codelineno-7-9"></a> <span class="n">original_lang</span> <span class="o">=</span> <span class="n">Language</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">metadata</span><span class="p">[</span><span class="s2">"languages"</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
|
||||
</span><span id="__span-7-10"><a id="__codelineno-7-10" name="__codelineno-7-10" href="#__codelineno-7-10"></a>
|
||||
</span><span id="__span-7-11"><a id="__codelineno-7-11" name="__codelineno-7-11" href="#__codelineno-7-11"></a> <span class="k">return</span> <span class="n">Movies</span><span class="p">([</span>
|
||||
</span><span id="__span-7-12"><a id="__codelineno-7-12" name="__codelineno-7-12" href="#__codelineno-7-12"></a> <span class="n">Movie</span><span class="p">(</span>
|
||||
</span><span id="__span-7-13"><a id="__codelineno-7-13" name="__codelineno-7-13" href="#__codelineno-7-13"></a> <span class="n">id_</span><span class="o">=</span><span class="n">metadata</span><span class="p">[</span><span class="s2">"id"</span><span class="p">],</span>
|
||||
</span><span id="__span-7-14"><a id="__codelineno-7-14" name="__codelineno-7-14" href="#__codelineno-7-14"></a> <span class="n">service</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span>
|
||||
</span><span id="__span-7-15"><a id="__codelineno-7-15" name="__codelineno-7-15" href="#__codelineno-7-15"></a> <span class="n">name</span><span class="o">=</span><span class="n">metadata</span><span class="p">[</span><span class="s2">"title"</span><span class="p">],</span>
|
||||
</span><span id="__span-7-16"><a id="__codelineno-7-16" name="__codelineno-7-16" href="#__codelineno-7-16"></a> <span class="n">year</span><span class="o">=</span><span class="n">metadata</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"releaseYear"</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span><span class="p">,</span>
|
||||
</span><span id="__span-7-17"><a id="__codelineno-7-17" name="__codelineno-7-17" href="#__codelineno-7-17"></a> <span class="n">language</span><span class="o">=</span><span class="n">original_lang</span><span class="p">,</span> <span class="c1"># ORIGINAL audio language, not the -l preference</span>
|
||||
</span><span id="__span-7-18"><a id="__codelineno-7-18" name="__codelineno-7-18" href="#__codelineno-7-18"></a> <span class="n">data</span><span class="o">=</span><span class="n">metadata</span><span class="p">,</span> <span class="c1"># read later as title.data</span>
|
||||
</span><span id="__span-7-19"><a id="__codelineno-7-19" name="__codelineno-7-19" href="#__codelineno-7-19"></a> <span class="p">)</span>
|
||||
</span><span id="__span-7-20"><a id="__codelineno-7-20" name="__codelineno-7-20" href="#__codelineno-7-20"></a> <span class="p">])</span>
|
||||
</span></code></pre></div>
|
||||
<p>Common constructor fields:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:3"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Movie</label><label for="__tabbed_1_2">Episode</label><label for="__tabbed_1_3">Song</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="n">Movie</span><span class="p">(</span><span class="n">id_</span><span class="p">,</span> <span class="n">service</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">language</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="n">Movie</span><span class="p">(</span><span class="n">id_</span><span class="p">,</span> <span class="n">service</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">language</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="n">Episode</span><span class="p">(</span><span class="n">id_</span><span class="p">,</span> <span class="n">service</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">season</span><span class="p">,</span> <span class="n">number</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a> <span class="n">language</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">air_date</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="n">Episode</span><span class="p">(</span><span class="n">id_</span><span class="p">,</span> <span class="n">service</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">season</span><span class="p">,</span> <span class="n">number</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
</span><span id="__span-9-2"><a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a> <span class="n">language</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">air_date</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>Pass <code>air_date</code> for daily/sports content to name by date instead of
|
||||
<code>SxxExx</code>. Return a <code>Series([...])</code> of episodes.</p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-9-1"><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="n">Song</span><span class="p">(</span><span class="n">id_</span><span class="p">,</span> <span class="n">service</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">artist</span><span class="p">,</span> <span class="n">album</span><span class="p">,</span> <span class="n">track</span><span class="p">,</span> <span class="n">disc</span><span class="p">,</span> <span class="n">year</span><span class="p">,</span>
|
||||
</span><span id="__span-9-2"><a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a> <span class="n">language</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="n">Song</span><span class="p">(</span><span class="n">id_</span><span class="p">,</span> <span class="n">service</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">artist</span><span class="p">,</span> <span class="n">album</span><span class="p">,</span> <span class="n">track</span><span class="p">,</span> <span class="n">disc</span><span class="p">,</span> <span class="n">year</span><span class="p">,</span>
|
||||
</span><span id="__span-10-2"><a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a> <span class="n">language</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>Return an <code>Album([...])</code> of songs.</p>
|
||||
</div>
|
||||
@@ -2368,29 +2380,29 @@ when the API errors. It also applies the per-service <code>title_map</code> conf
|
||||
<code>Subtitle</code> tracks. In almost all cases you build these by parsing a manifest,
|
||||
not by hand.</p>
|
||||
<p>The manifest parsers live in <code>unshackle.core.manifests</code>:</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-10-1"><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.manifests</span><span class="w"> </span><span class="kn">import</span> <span class="n">DASH</span><span class="p">,</span> <span class="n">HLS</span><span class="p">,</span> <span class="n">ISM</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-11-1"><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.manifests</span><span class="w"> </span><span class="kn">import</span> <span class="n">DASH</span><span class="p">,</span> <span class="n">HLS</span><span class="p">,</span> <span class="n">ISM</span>
|
||||
</span></code></pre></div>
|
||||
<p>Each exposes <code>from_url(url, session=...)</code> (or <code>from_text(text, url)</code>) and then
|
||||
<code>.to_tracks(language=...)</code>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:3"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">DASH (.mpd)</label><label for="__tabbed_2_2">HLS (.m3u8)</label><label for="__tabbed_2_3">ISM (Smooth Streaming)</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-11-1"><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-11-2"><a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a> <span class="k">return</span> <span class="n">DASH</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span><span class="n">manifest_url</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span> \
|
||||
</span><span id="__span-11-3"><a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a> <span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-12-1"><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-12-2"><a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a> <span class="k">return</span> <span class="n">DASH</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span><span class="n">manifest_url</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span> \
|
||||
</span><span id="__span-12-3"><a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a> <span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-12-1"><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-12-2"><a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a> <span class="k">return</span> <span class="n">HLS</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span><span class="n">manifest_url</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span> \
|
||||
</span><span id="__span-12-3"><a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a> <span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-13-1"><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-13-2"><a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a> <span class="k">return</span> <span class="n">HLS</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span><span class="n">manifest_url</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span> \
|
||||
</span><span id="__span-13-3"><a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a> <span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>The URL must be a <strong>variant (master) playlist</strong>, not a media playlist.</p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-13-1"><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-13-2"><a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a> <span class="k">return</span> <span class="n">ISM</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span><span class="n">manifest_url</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span> \
|
||||
</span><span id="__span-13-3"><a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a> <span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-14-1"><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-14-2"><a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a> <span class="k">return</span> <span class="n">ISM</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span><span class="n">manifest_url</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span> \
|
||||
</span><span id="__span-14-3"><a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a> <span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2408,11 +2420,11 @@ token.</p>
|
||||
provides <code>_get_tracks_for_variants(title, fetch_fn)</code> to fan out over every
|
||||
codec×range in the <code>TrackRequest</code>, including <code>HYBRID</code> (fetch HDR10 + DV and
|
||||
merge) and <code>--best-available</code> skip-on-error handling:</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-14-1"><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-14-2"><a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a> <span class="k">def</span><span class="w"> </span><span class="nf">_fetch_variant</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">codec</span><span class="p">,</span> <span class="n">range_</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-14-3"><a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a> <span class="n">vcodec</span> <span class="o">=</span> <span class="s2">"H265"</span> <span class="k">if</span> <span class="n">codec</span> <span class="o">==</span> <span class="n">Video</span><span class="o">.</span><span class="n">Codec</span><span class="o">.</span><span class="n">HEVC</span> <span class="k">else</span> <span class="s2">"H264"</span>
|
||||
</span><span id="__span-14-4"><a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fetch_dash_manifest</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">vcodec</span><span class="o">=</span><span class="n">vcodec</span><span class="p">,</span> <span class="n">range_</span><span class="o">=</span><span class="n">range_</span><span class="p">)</span>
|
||||
</span><span id="__span-14-5"><a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_tracks_for_variants</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">_fetch_variant</span><span class="p">)</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-15-1"><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-15-2"><a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a> <span class="k">def</span><span class="w"> </span><span class="nf">_fetch_variant</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">codec</span><span class="p">,</span> <span class="n">range_</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-15-3"><a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a> <span class="n">vcodec</span> <span class="o">=</span> <span class="s2">"H265"</span> <span class="k">if</span> <span class="n">codec</span> <span class="o">==</span> <span class="n">Video</span><span class="o">.</span><span class="n">Codec</span><span class="o">.</span><span class="n">HEVC</span> <span class="k">else</span> <span class="s2">"H264"</span>
|
||||
</span><span id="__span-15-4"><a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fetch_dash_manifest</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">vcodec</span><span class="o">=</span><span class="n">vcodec</span><span class="p">,</span> <span class="n">range_</span><span class="o">=</span><span class="n">range_</span><span class="p">)</span>
|
||||
</span><span id="__span-15-5"><a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_tracks_for_variants</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">_fetch_variant</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>After parsing, you may <strong>correct</strong> track metadata the manifest gets wrong:
|
||||
stamp the real <code>video.range</code>, fix odd audio channel counts, mark descriptive
|
||||
@@ -2449,16 +2461,16 @@ sure encrypted tracks carry the correct <code>drm</code> so the core licenses th
|
||||
sort them; <code>Chapters</code> does that automatically and inserts a <code>00:00:00.000</code>
|
||||
marker if missing. A <code>Chapter</code> timestamp accepts <code>"HH:MM:SS[.mmm]"</code>, an int in
|
||||
milliseconds, or a float in seconds.</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-15-1"><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_chapters</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Chapters</span><span class="p">:</span>
|
||||
</span><span id="__span-15-2"><a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a> <span class="n">chapters</span> <span class="o">=</span> <span class="n">Chapters</span><span class="p">()</span>
|
||||
</span><span id="__span-15-3"><a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a> <span class="n">seen</span><span class="p">:</span> <span class="nb">set</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
||||
</span><span id="__span-15-4"><a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a> <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">title</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"chapters"</span><span class="p">,</span> <span class="p">[]):</span>
|
||||
</span><span id="__span-15-5"><a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a> <span class="n">chapter</span> <span class="o">=</span> <span class="n">Chapter</span><span class="p">(</span><span class="n">timestamp</span><span class="o">=</span><span class="n">ch</span><span class="p">[</span><span class="s2">"start"</span><span class="p">],</span> <span class="n">name</span><span class="o">=</span><span class="n">ch</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"name"</span><span class="p">))</span>
|
||||
</span><span id="__span-15-6"><a id="__codelineno-15-6" name="__codelineno-15-6" href="#__codelineno-15-6"></a> <span class="k">if</span> <span class="n">chapter</span><span class="o">.</span><span class="n">timestamp</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">chapter</span><span class="o">.</span><span class="n">timestamp</span> <span class="ow">in</span> <span class="n">seen</span><span class="p">:</span>
|
||||
</span><span id="__span-15-7"><a id="__codelineno-15-7" name="__codelineno-15-7" href="#__codelineno-15-7"></a> <span class="k">continue</span> <span class="c1"># see the warning below</span>
|
||||
</span><span id="__span-15-8"><a id="__codelineno-15-8" name="__codelineno-15-8" href="#__codelineno-15-8"></a> <span class="n">seen</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">chapter</span><span class="o">.</span><span class="n">timestamp</span><span class="p">)</span>
|
||||
</span><span id="__span-15-9"><a id="__codelineno-15-9" name="__codelineno-15-9" href="#__codelineno-15-9"></a> <span class="n">chapters</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">chapter</span><span class="p">)</span>
|
||||
</span><span id="__span-15-10"><a id="__codelineno-15-10" name="__codelineno-15-10" href="#__codelineno-15-10"></a> <span class="k">return</span> <span class="n">chapters</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-16-1"><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_chapters</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Chapters</span><span class="p">:</span>
|
||||
</span><span id="__span-16-2"><a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a> <span class="n">chapters</span> <span class="o">=</span> <span class="n">Chapters</span><span class="p">()</span>
|
||||
</span><span id="__span-16-3"><a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a> <span class="n">seen</span><span class="p">:</span> <span class="nb">set</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
||||
</span><span id="__span-16-4"><a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a> <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">title</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"chapters"</span><span class="p">,</span> <span class="p">[]):</span>
|
||||
</span><span id="__span-16-5"><a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a> <span class="n">chapter</span> <span class="o">=</span> <span class="n">Chapter</span><span class="p">(</span><span class="n">timestamp</span><span class="o">=</span><span class="n">ch</span><span class="p">[</span><span class="s2">"start"</span><span class="p">],</span> <span class="n">name</span><span class="o">=</span><span class="n">ch</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"name"</span><span class="p">))</span>
|
||||
</span><span id="__span-16-6"><a id="__codelineno-16-6" name="__codelineno-16-6" href="#__codelineno-16-6"></a> <span class="k">if</span> <span class="n">chapter</span><span class="o">.</span><span class="n">timestamp</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">chapter</span><span class="o">.</span><span class="n">timestamp</span> <span class="ow">in</span> <span class="n">seen</span><span class="p">:</span>
|
||||
</span><span id="__span-16-7"><a id="__codelineno-16-7" name="__codelineno-16-7" href="#__codelineno-16-7"></a> <span class="k">continue</span> <span class="c1"># see the warning below</span>
|
||||
</span><span id="__span-16-8"><a id="__codelineno-16-8" name="__codelineno-16-8" href="#__codelineno-16-8"></a> <span class="n">seen</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">chapter</span><span class="o">.</span><span class="n">timestamp</span><span class="p">)</span>
|
||||
</span><span id="__span-16-9"><a id="__codelineno-16-9" name="__codelineno-16-9" href="#__codelineno-16-9"></a> <span class="n">chapters</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">chapter</span><span class="p">)</span>
|
||||
</span><span id="__span-16-10"><a id="__codelineno-16-10" name="__codelineno-16-10" href="#__codelineno-16-10"></a> <span class="k">return</span> <span class="n">chapters</span>
|
||||
</span></code></pre></div>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Skip markers at 0 and de-duplicate timestamps before <code>add()</code></p>
|
||||
@@ -2521,17 +2533,17 @@ current <code>title</code> and <code>track</code>:</p>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-16-1"><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_widevine_license</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span><span class="p">):</span>
|
||||
</span><span id="__span-16-2"><a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a> <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
|
||||
</span><span id="__span-16-3"><a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a> <span class="bp">self</span><span class="o">.</span><span class="n">license_data</span><span class="p">[</span><span class="s2">"url"</span><span class="p">],</span>
|
||||
</span><span id="__span-16-4"><a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a> <span class="n">data</span><span class="o">=</span><span class="n">challenge</span><span class="p">,</span> <span class="c1"># POST the challenge as-is</span>
|
||||
</span><span id="__span-16-5"><a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">"dt-custom-data"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">license_data</span><span class="p">[</span><span class="s2">"data"</span><span class="p">]},</span>
|
||||
</span><span id="__span-16-6"><a id="__codelineno-16-6" name="__codelineno-16-6" href="#__codelineno-16-6"></a> <span class="p">)</span>
|
||||
</span><span id="__span-16-7"><a id="__codelineno-16-7" name="__codelineno-16-7" href="#__codelineno-16-7"></a> <span class="n">response</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
|
||||
</span><span id="__span-16-8"><a id="__codelineno-16-8" name="__codelineno-16-8" href="#__codelineno-16-8"></a> <span class="k">try</span><span class="p">:</span>
|
||||
</span><span id="__span-16-9"><a id="__codelineno-16-9" name="__codelineno-16-9" href="#__codelineno-16-9"></a> <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s2">"license"</span><span class="p">]</span> <span class="c1"># some services wrap it in JSON</span>
|
||||
</span><span id="__span-16-10"><a id="__codelineno-16-10" name="__codelineno-16-10" href="#__codelineno-16-10"></a> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">KeyError</span><span class="p">):</span>
|
||||
</span><span id="__span-16-11"><a id="__codelineno-16-11" name="__codelineno-16-11" href="#__codelineno-16-11"></a> <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span> <span class="c1"># others return raw bytes</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-17-1"><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_widevine_license</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span><span class="p">):</span>
|
||||
</span><span id="__span-17-2"><a id="__codelineno-17-2" name="__codelineno-17-2" href="#__codelineno-17-2"></a> <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
|
||||
</span><span id="__span-17-3"><a id="__codelineno-17-3" name="__codelineno-17-3" href="#__codelineno-17-3"></a> <span class="bp">self</span><span class="o">.</span><span class="n">license_data</span><span class="p">[</span><span class="s2">"url"</span><span class="p">],</span>
|
||||
</span><span id="__span-17-4"><a id="__codelineno-17-4" name="__codelineno-17-4" href="#__codelineno-17-4"></a> <span class="n">data</span><span class="o">=</span><span class="n">challenge</span><span class="p">,</span> <span class="c1"># POST the challenge as-is</span>
|
||||
</span><span id="__span-17-5"><a id="__codelineno-17-5" name="__codelineno-17-5" href="#__codelineno-17-5"></a> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">"dt-custom-data"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">license_data</span><span class="p">[</span><span class="s2">"data"</span><span class="p">]},</span>
|
||||
</span><span id="__span-17-6"><a id="__codelineno-17-6" name="__codelineno-17-6" href="#__codelineno-17-6"></a> <span class="p">)</span>
|
||||
</span><span id="__span-17-7"><a id="__codelineno-17-7" name="__codelineno-17-7" href="#__codelineno-17-7"></a> <span class="n">response</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
|
||||
</span><span id="__span-17-8"><a id="__codelineno-17-8" name="__codelineno-17-8" href="#__codelineno-17-8"></a> <span class="k">try</span><span class="p">:</span>
|
||||
</span><span id="__span-17-9"><a id="__codelineno-17-9" name="__codelineno-17-9" href="#__codelineno-17-9"></a> <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s2">"license"</span><span class="p">]</span> <span class="c1"># some services wrap it in JSON</span>
|
||||
</span><span id="__span-17-10"><a id="__codelineno-17-10" name="__codelineno-17-10" href="#__codelineno-17-10"></a> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">KeyError</span><span class="p">):</span>
|
||||
</span><span id="__span-17-11"><a id="__codelineno-17-11" name="__codelineno-17-11" href="#__codelineno-17-11"></a> <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span> <span class="c1"># others return raw bytes</span>
|
||||
</span></code></pre></div>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Return the license untouched</p>
|
||||
@@ -2570,99 +2582,99 @@ flagged, banned, or downgraded.</p>
|
||||
<code>on_segment_downloaded</code>, <code>on_track_downloaded</code>, <code>on_track_decrypted</code>,
|
||||
<code>on_track_repacked</code>, <code>on_track_multiplex</code>. Also override <code>search()</code> to yield
|
||||
<code>SearchResult</code> objects for <code>unshackle search</code>.</p>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-17-1"><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Generator</span><span class="p">[</span><span class="n">SearchResult</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">]:</span>
|
||||
</span><span id="__span-17-2"><a id="__codelineno-17-2" name="__codelineno-17-2" href="#__codelineno-17-2"></a> <span class="n">results</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"search"</span><span class="p">],</span>
|
||||
</span><span id="__span-17-3"><a id="__codelineno-17-3" name="__codelineno-17-3" href="#__codelineno-17-3"></a> <span class="n">params</span><span class="o">=</span><span class="p">{</span><span class="s2">"q"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">})</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-17-4"><a id="__codelineno-17-4" name="__codelineno-17-4" href="#__codelineno-17-4"></a> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span><span class="p">[</span><span class="s2">"entries"</span><span class="p">]:</span>
|
||||
</span><span id="__span-17-5"><a id="__codelineno-17-5" name="__codelineno-17-5" href="#__codelineno-17-5"></a> <span class="k">yield</span> <span class="n">SearchResult</span><span class="p">(</span><span class="n">id_</span><span class="o">=</span><span class="n">r</span><span class="p">[</span><span class="s2">"id"</span><span class="p">],</span> <span class="n">title</span><span class="o">=</span><span class="n">r</span><span class="p">[</span><span class="s2">"title"</span><span class="p">],</span>
|
||||
</span><span id="__span-17-6"><a id="__codelineno-17-6" name="__codelineno-17-6" href="#__codelineno-17-6"></a> <span class="n">description</span><span class="o">=</span><span class="n">r</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"description"</span><span class="p">),</span> <span class="n">url</span><span class="o">=</span><span class="n">r</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"url"</span><span class="p">))</span>
|
||||
<div class="language-python highlight"><pre><span></span><code><span id="__span-18-1"><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Generator</span><span class="p">[</span><span class="n">SearchResult</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">]:</span>
|
||||
</span><span id="__span-18-2"><a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a> <span class="n">results</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"search"</span><span class="p">],</span>
|
||||
</span><span id="__span-18-3"><a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a> <span class="n">params</span><span class="o">=</span><span class="p">{</span><span class="s2">"q"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">})</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-18-4"><a id="__codelineno-18-4" name="__codelineno-18-4" href="#__codelineno-18-4"></a> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span><span class="p">[</span><span class="s2">"entries"</span><span class="p">]:</span>
|
||||
</span><span id="__span-18-5"><a id="__codelineno-18-5" name="__codelineno-18-5" href="#__codelineno-18-5"></a> <span class="k">yield</span> <span class="n">SearchResult</span><span class="p">(</span><span class="n">id_</span><span class="o">=</span><span class="n">r</span><span class="p">[</span><span class="s2">"id"</span><span class="p">],</span> <span class="n">title</span><span class="o">=</span><span class="n">r</span><span class="p">[</span><span class="s2">"title"</span><span class="p">],</span>
|
||||
</span><span id="__span-18-6"><a id="__codelineno-18-6" name="__codelineno-18-6" href="#__codelineno-18-6"></a> <span class="n">description</span><span class="o">=</span><span class="n">r</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"description"</span><span class="p">),</span> <span class="n">url</span><span class="o">=</span><span class="n">r</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"url"</span><span class="p">))</span>
|
||||
</span></code></pre></div>
|
||||
<hr />
|
||||
<h2 id="minimal-service-skeleton">Minimal service skeleton<a class="headerlink" href="#minimal-service-skeleton" title="Permanent link">¶</a></h2>
|
||||
<p>A complete, minimal single-manifest service. Save as
|
||||
<code>services/MYSVC/__init__.py</code> (class name <code>MYSVC</code>), with an optional
|
||||
<code>services/MYSVC/config.yaml</code> beside it.</p>
|
||||
<div class="language-python highlight"><span class="filename">services/MYSVC/__init__.py</span><pre><span></span><code><span id="__span-18-1"><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">__future__</span><span class="w"> </span><span class="kn">import</span> <span class="n">annotations</span>
|
||||
</span><span id="__span-18-2"><a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a>
|
||||
</span><span id="__span-18-3"><a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>
|
||||
</span><span id="__span-18-4"><a id="__codelineno-18-4" name="__codelineno-18-4" href="#__codelineno-18-4"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Optional</span>
|
||||
</span><span id="__span-18-5"><a id="__codelineno-18-5" name="__codelineno-18-5" href="#__codelineno-18-5"></a>
|
||||
</span><span id="__span-18-6"><a id="__codelineno-18-6" name="__codelineno-18-6" href="#__codelineno-18-6"></a><span class="kn">import</span><span class="w"> </span><span class="nn">click</span>
|
||||
</span><span id="__span-18-7"><a id="__codelineno-18-7" name="__codelineno-18-7" href="#__codelineno-18-7"></a>
|
||||
</span><span id="__span-18-8"><a id="__codelineno-18-8" name="__codelineno-18-8" href="#__codelineno-18-8"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.manifests</span><span class="w"> </span><span class="kn">import</span> <span class="n">DASH</span>
|
||||
</span><span id="__span-18-9"><a id="__codelineno-18-9" name="__codelineno-18-9" href="#__codelineno-18-9"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.service</span><span class="w"> </span><span class="kn">import</span> <span class="n">Service</span>
|
||||
</span><span id="__span-18-10"><a id="__codelineno-18-10" name="__codelineno-18-10" href="#__codelineno-18-10"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.titles</span><span class="w"> </span><span class="kn">import</span> <span class="n">Movie</span><span class="p">,</span> <span class="n">Movies</span><span class="p">,</span> <span class="n">Title_T</span><span class="p">,</span> <span class="n">Titles_T</span>
|
||||
</span><span id="__span-18-11"><a id="__codelineno-18-11" name="__codelineno-18-11" href="#__codelineno-18-11"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.tracks</span><span class="w"> </span><span class="kn">import</span> <span class="n">Chapters</span><span class="p">,</span> <span class="n">Tracks</span>
|
||||
</span><span id="__span-18-12"><a id="__codelineno-18-12" name="__codelineno-18-12" href="#__codelineno-18-12"></a>
|
||||
</span><span id="__span-18-13"><a id="__codelineno-18-13" name="__codelineno-18-13" href="#__codelineno-18-13"></a>
|
||||
</span><span id="__span-18-14"><a id="__codelineno-18-14" name="__codelineno-18-14" href="#__codelineno-18-14"></a><span class="k">class</span><span class="w"> </span><span class="nc">MYSVC</span><span class="p">(</span><span class="n">Service</span><span class="p">):</span>
|
||||
</span><span id="__span-18-15"><a id="__codelineno-18-15" name="__codelineno-18-15" href="#__codelineno-18-15"></a><span class="w"> </span><span class="sd">"""</span>
|
||||
</span><span id="__span-18-16"><a id="__codelineno-18-16" name="__codelineno-18-16" href="#__codelineno-18-16"></a><span class="sd"> MyService - https://myservice.com</span>
|
||||
</span><span id="__span-18-17"><a id="__codelineno-18-17" name="__codelineno-18-17" href="#__codelineno-18-17"></a>
|
||||
</span><span id="__span-18-18"><a id="__codelineno-18-18" name="__codelineno-18-18" href="#__codelineno-18-18"></a><span class="sd"> \b</span>
|
||||
</span><span id="__span-18-19"><a id="__codelineno-18-19" name="__codelineno-18-19" href="#__codelineno-18-19"></a><span class="sd"> Usage: unshackle dl MYSVC <title-id-or-url></span>
|
||||
</span><span id="__span-18-20"><a id="__codelineno-18-20" name="__codelineno-18-20" href="#__codelineno-18-20"></a><span class="sd"> """</span>
|
||||
</span><span id="__span-18-21"><a id="__codelineno-18-21" name="__codelineno-18-21" href="#__codelineno-18-21"></a>
|
||||
</span><span id="__span-18-22"><a id="__codelineno-18-22" name="__codelineno-18-22" href="#__codelineno-18-22"></a> <span class="n">ALIASES</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"MY"</span><span class="p">,)</span>
|
||||
</span><span id="__span-18-23"><a id="__codelineno-18-23" name="__codelineno-18-23" href="#__codelineno-18-23"></a> <span class="n">GEOFENCE</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"US"</span><span class="p">,)</span>
|
||||
</span><span id="__span-18-24"><a id="__codelineno-18-24" name="__codelineno-18-24" href="#__codelineno-18-24"></a> <span class="n">TITLE_RE</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">"^(?:https?://myservice\.com/watch/)?(?P<id>[\w-]+)"</span>
|
||||
</span><span id="__span-18-25"><a id="__codelineno-18-25" name="__codelineno-18-25" href="#__codelineno-18-25"></a>
|
||||
</span><span id="__span-18-26"><a id="__codelineno-18-26" name="__codelineno-18-26" href="#__codelineno-18-26"></a> <span class="nd">@staticmethod</span>
|
||||
</span><span id="__span-18-27"><a id="__codelineno-18-27" name="__codelineno-18-27" href="#__codelineno-18-27"></a> <span class="nd">@click</span><span class="o">.</span><span class="n">command</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"MYSVC"</span><span class="p">,</span> <span class="n">short_help</span><span class="o">=</span><span class="s2">"https://myservice.com"</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="vm">__doc__</span><span class="p">)</span>
|
||||
</span><span id="__span-18-28"><a id="__codelineno-18-28" name="__codelineno-18-28" href="#__codelineno-18-28"></a> <span class="nd">@click</span><span class="o">.</span><span class="n">argument</span><span class="p">(</span><span class="s2">"title"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">)</span>
|
||||
</span><span id="__span-18-29"><a id="__codelineno-18-29" name="__codelineno-18-29" href="#__codelineno-18-29"></a> <span class="nd">@click</span><span class="o">.</span><span class="n">pass_context</span>
|
||||
</span><span id="__span-18-30"><a id="__codelineno-18-30" name="__codelineno-18-30" href="#__codelineno-18-30"></a> <span class="k">def</span><span class="w"> </span><span class="nf">cli</span><span class="p">(</span><span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"MYSVC"</span><span class="p">:</span>
|
||||
</span><span id="__span-18-31"><a id="__codelineno-18-31" name="__codelineno-18-31" href="#__codelineno-18-31"></a> <span class="k">return</span> <span class="n">MYSVC</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
</span><span id="__span-18-32"><a id="__codelineno-18-32" name="__codelineno-18-32" href="#__codelineno-18-32"></a>
|
||||
</span><span id="__span-18-33"><a id="__codelineno-18-33" name="__codelineno-18-33" href="#__codelineno-18-33"></a> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
|
||||
</span><span id="__span-18-34"><a id="__codelineno-18-34" name="__codelineno-18-34" href="#__codelineno-18-34"></a> <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
|
||||
</span><span id="__span-18-35"><a id="__codelineno-18-35" name="__codelineno-18-35" href="#__codelineno-18-35"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
||||
</span><span id="__span-18-36"><a id="__codelineno-18-36" name="__codelineno-18-36" href="#__codelineno-18-36"></a>
|
||||
</span><span id="__span-18-37"><a id="__codelineno-18-37" name="__codelineno-18-37" href="#__codelineno-18-37"></a> <span class="k">def</span><span class="w"> </span><span class="nf">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cookies</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">credential</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||
</span><span id="__span-18-38"><a id="__codelineno-18-38" name="__codelineno-18-38" href="#__codelineno-18-38"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">authenticate</span><span class="p">(</span><span class="n">cookies</span><span class="p">,</span> <span class="n">credential</span><span class="p">)</span>
|
||||
</span><span id="__span-18-39"><a id="__codelineno-18-39" name="__codelineno-18-39" href="#__codelineno-18-39"></a> <span class="c1"># obtain any tokens here, e.g. self.token = ...</span>
|
||||
</span><span id="__span-18-40"><a id="__codelineno-18-40" name="__codelineno-18-40" href="#__codelineno-18-40"></a>
|
||||
</span><span id="__span-18-41"><a id="__codelineno-18-41" name="__codelineno-18-41" href="#__codelineno-18-41"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_titles</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Titles_T</span><span class="p">:</span>
|
||||
</span><span id="__span-18-42"><a id="__codelineno-18-42" name="__codelineno-18-42" href="#__codelineno-18-42"></a> <span class="n">match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">TITLE_RE</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
|
||||
</span><span id="__span-18-43"><a id="__codelineno-18-43" name="__codelineno-18-43" href="#__codelineno-18-43"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span>
|
||||
</span><span id="__span-18-44"><a id="__codelineno-18-44" name="__codelineno-18-44" href="#__codelineno-18-44"></a> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Could not parse a title ID."</span><span class="p">)</span>
|
||||
</span><span id="__span-18-45"><a id="__codelineno-18-45" name="__codelineno-18-45" href="#__codelineno-18-45"></a> <span class="n">meta</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
|
||||
</span><span id="__span-18-46"><a id="__codelineno-18-46" name="__codelineno-18-46" href="#__codelineno-18-46"></a> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"metadata"</span><span class="p">]</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"id"</span><span class="p">))</span>
|
||||
</span><span id="__span-18-47"><a id="__codelineno-18-47" name="__codelineno-18-47" href="#__codelineno-18-47"></a> <span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-18-48"><a id="__codelineno-18-48" name="__codelineno-18-48" href="#__codelineno-18-48"></a> <span class="k">return</span> <span class="n">Movies</span><span class="p">([</span>
|
||||
</span><span id="__span-18-49"><a id="__codelineno-18-49" name="__codelineno-18-49" href="#__codelineno-18-49"></a> <span class="n">Movie</span><span class="p">(</span>
|
||||
</span><span id="__span-18-50"><a id="__codelineno-18-50" name="__codelineno-18-50" href="#__codelineno-18-50"></a> <span class="n">id_</span><span class="o">=</span><span class="n">meta</span><span class="p">[</span><span class="s2">"id"</span><span class="p">],</span>
|
||||
</span><span id="__span-18-51"><a id="__codelineno-18-51" name="__codelineno-18-51" href="#__codelineno-18-51"></a> <span class="n">service</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span>
|
||||
</span><span id="__span-18-52"><a id="__codelineno-18-52" name="__codelineno-18-52" href="#__codelineno-18-52"></a> <span class="n">name</span><span class="o">=</span><span class="n">meta</span><span class="p">[</span><span class="s2">"title"</span><span class="p">],</span>
|
||||
</span><span id="__span-18-53"><a id="__codelineno-18-53" name="__codelineno-18-53" href="#__codelineno-18-53"></a> <span class="n">year</span><span class="o">=</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"year"</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span><span class="p">,</span>
|
||||
</span><span id="__span-18-54"><a id="__codelineno-18-54" name="__codelineno-18-54" href="#__codelineno-18-54"></a> <span class="n">language</span><span class="o">=</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"originalLanguage"</span><span class="p">),</span>
|
||||
</span><span id="__span-18-55"><a id="__codelineno-18-55" name="__codelineno-18-55" href="#__codelineno-18-55"></a> <span class="n">data</span><span class="o">=</span><span class="n">meta</span><span class="p">,</span>
|
||||
</span><span id="__span-18-56"><a id="__codelineno-18-56" name="__codelineno-18-56" href="#__codelineno-18-56"></a> <span class="p">)</span>
|
||||
</span><span id="__span-18-57"><a id="__codelineno-18-57" name="__codelineno-18-57" href="#__codelineno-18-57"></a> <span class="p">])</span>
|
||||
</span><span id="__span-18-58"><a id="__codelineno-18-58" name="__codelineno-18-58" href="#__codelineno-18-58"></a>
|
||||
</span><span id="__span-18-59"><a id="__codelineno-18-59" name="__codelineno-18-59" href="#__codelineno-18-59"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-18-60"><a id="__codelineno-18-60" name="__codelineno-18-60" href="#__codelineno-18-60"></a> <span class="n">playback</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
|
||||
</span><span id="__span-18-61"><a id="__codelineno-18-61" name="__codelineno-18-61" href="#__codelineno-18-61"></a> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"playback"</span><span class="p">]</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
|
||||
</span><span id="__span-18-62"><a id="__codelineno-18-62" name="__codelineno-18-62" href="#__codelineno-18-62"></a> <span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-18-63"><a id="__codelineno-18-63" name="__codelineno-18-63" href="#__codelineno-18-63"></a> <span class="k">return</span> <span class="n">DASH</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span>
|
||||
</span><span id="__span-18-64"><a id="__codelineno-18-64" name="__codelineno-18-64" href="#__codelineno-18-64"></a> <span class="n">url</span><span class="o">=</span><span class="n">playback</span><span class="p">[</span><span class="s2">"manifest_url"</span><span class="p">],</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span>
|
||||
</span><span id="__span-18-65"><a id="__codelineno-18-65" name="__codelineno-18-65" href="#__codelineno-18-65"></a> <span class="p">)</span><span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
</span><span id="__span-18-66"><a id="__codelineno-18-66" name="__codelineno-18-66" href="#__codelineno-18-66"></a>
|
||||
</span><span id="__span-18-67"><a id="__codelineno-18-67" name="__codelineno-18-67" href="#__codelineno-18-67"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_chapters</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Chapters</span><span class="p">:</span>
|
||||
</span><span id="__span-18-68"><a id="__codelineno-18-68" name="__codelineno-18-68" href="#__codelineno-18-68"></a> <span class="k">return</span> <span class="n">Chapters</span><span class="p">()</span>
|
||||
</span><span id="__span-18-69"><a id="__codelineno-18-69" name="__codelineno-18-69" href="#__codelineno-18-69"></a>
|
||||
</span><span id="__span-18-70"><a id="__codelineno-18-70" name="__codelineno-18-70" href="#__codelineno-18-70"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_widevine_license</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span><span class="p">):</span>
|
||||
</span><span id="__span-18-71"><a id="__codelineno-18-71" name="__codelineno-18-71" href="#__codelineno-18-71"></a> <span class="n">res</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"license"</span><span class="p">],</span> <span class="n">data</span><span class="o">=</span><span class="n">challenge</span><span class="p">)</span>
|
||||
</span><span id="__span-18-72"><a id="__codelineno-18-72" name="__codelineno-18-72" href="#__codelineno-18-72"></a> <span class="n">res</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
|
||||
</span><span id="__span-18-73"><a id="__codelineno-18-73" name="__codelineno-18-73" href="#__codelineno-18-73"></a> <span class="k">return</span> <span class="n">res</span><span class="o">.</span><span class="n">content</span>
|
||||
<div class="language-python highlight"><span class="filename">services/MYSVC/__init__.py</span><pre><span></span><code><span id="__span-19-1"><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">__future__</span><span class="w"> </span><span class="kn">import</span> <span class="n">annotations</span>
|
||||
</span><span id="__span-19-2"><a id="__codelineno-19-2" name="__codelineno-19-2" href="#__codelineno-19-2"></a>
|
||||
</span><span id="__span-19-3"><a id="__codelineno-19-3" name="__codelineno-19-3" href="#__codelineno-19-3"></a><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>
|
||||
</span><span id="__span-19-4"><a id="__codelineno-19-4" name="__codelineno-19-4" href="#__codelineno-19-4"></a><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Optional</span>
|
||||
</span><span id="__span-19-5"><a id="__codelineno-19-5" name="__codelineno-19-5" href="#__codelineno-19-5"></a>
|
||||
</span><span id="__span-19-6"><a id="__codelineno-19-6" name="__codelineno-19-6" href="#__codelineno-19-6"></a><span class="kn">import</span><span class="w"> </span><span class="nn">click</span>
|
||||
</span><span id="__span-19-7"><a id="__codelineno-19-7" name="__codelineno-19-7" href="#__codelineno-19-7"></a>
|
||||
</span><span id="__span-19-8"><a id="__codelineno-19-8" name="__codelineno-19-8" href="#__codelineno-19-8"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.manifests</span><span class="w"> </span><span class="kn">import</span> <span class="n">DASH</span>
|
||||
</span><span id="__span-19-9"><a id="__codelineno-19-9" name="__codelineno-19-9" href="#__codelineno-19-9"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.service</span><span class="w"> </span><span class="kn">import</span> <span class="n">Service</span>
|
||||
</span><span id="__span-19-10"><a id="__codelineno-19-10" name="__codelineno-19-10" href="#__codelineno-19-10"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.titles</span><span class="w"> </span><span class="kn">import</span> <span class="n">Movie</span><span class="p">,</span> <span class="n">Movies</span><span class="p">,</span> <span class="n">Title_T</span><span class="p">,</span> <span class="n">Titles_T</span>
|
||||
</span><span id="__span-19-11"><a id="__codelineno-19-11" name="__codelineno-19-11" href="#__codelineno-19-11"></a><span class="kn">from</span><span class="w"> </span><span class="nn">unshackle.core.tracks</span><span class="w"> </span><span class="kn">import</span> <span class="n">Chapters</span><span class="p">,</span> <span class="n">Tracks</span>
|
||||
</span><span id="__span-19-12"><a id="__codelineno-19-12" name="__codelineno-19-12" href="#__codelineno-19-12"></a>
|
||||
</span><span id="__span-19-13"><a id="__codelineno-19-13" name="__codelineno-19-13" href="#__codelineno-19-13"></a>
|
||||
</span><span id="__span-19-14"><a id="__codelineno-19-14" name="__codelineno-19-14" href="#__codelineno-19-14"></a><span class="k">class</span><span class="w"> </span><span class="nc">MYSVC</span><span class="p">(</span><span class="n">Service</span><span class="p">):</span>
|
||||
</span><span id="__span-19-15"><a id="__codelineno-19-15" name="__codelineno-19-15" href="#__codelineno-19-15"></a><span class="w"> </span><span class="sd">"""</span>
|
||||
</span><span id="__span-19-16"><a id="__codelineno-19-16" name="__codelineno-19-16" href="#__codelineno-19-16"></a><span class="sd"> MyService - https://myservice.com</span>
|
||||
</span><span id="__span-19-17"><a id="__codelineno-19-17" name="__codelineno-19-17" href="#__codelineno-19-17"></a>
|
||||
</span><span id="__span-19-18"><a id="__codelineno-19-18" name="__codelineno-19-18" href="#__codelineno-19-18"></a><span class="sd"> \b</span>
|
||||
</span><span id="__span-19-19"><a id="__codelineno-19-19" name="__codelineno-19-19" href="#__codelineno-19-19"></a><span class="sd"> Usage: unshackle dl MYSVC <title-id-or-url></span>
|
||||
</span><span id="__span-19-20"><a id="__codelineno-19-20" name="__codelineno-19-20" href="#__codelineno-19-20"></a><span class="sd"> """</span>
|
||||
</span><span id="__span-19-21"><a id="__codelineno-19-21" name="__codelineno-19-21" href="#__codelineno-19-21"></a>
|
||||
</span><span id="__span-19-22"><a id="__codelineno-19-22" name="__codelineno-19-22" href="#__codelineno-19-22"></a> <span class="n">ALIASES</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"MY"</span><span class="p">,)</span>
|
||||
</span><span id="__span-19-23"><a id="__codelineno-19-23" name="__codelineno-19-23" href="#__codelineno-19-23"></a> <span class="n">GEOFENCE</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"US"</span><span class="p">,)</span>
|
||||
</span><span id="__span-19-24"><a id="__codelineno-19-24" name="__codelineno-19-24" href="#__codelineno-19-24"></a> <span class="n">TITLE_RE</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">"^(?:https?://myservice\.com/watch/)?(?P<id>[\w-]+)"</span>
|
||||
</span><span id="__span-19-25"><a id="__codelineno-19-25" name="__codelineno-19-25" href="#__codelineno-19-25"></a>
|
||||
</span><span id="__span-19-26"><a id="__codelineno-19-26" name="__codelineno-19-26" href="#__codelineno-19-26"></a> <span class="nd">@staticmethod</span>
|
||||
</span><span id="__span-19-27"><a id="__codelineno-19-27" name="__codelineno-19-27" href="#__codelineno-19-27"></a> <span class="nd">@click</span><span class="o">.</span><span class="n">command</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"MYSVC"</span><span class="p">,</span> <span class="n">short_help</span><span class="o">=</span><span class="s2">"https://myservice.com"</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="vm">__doc__</span><span class="p">)</span>
|
||||
</span><span id="__span-19-28"><a id="__codelineno-19-28" name="__codelineno-19-28" href="#__codelineno-19-28"></a> <span class="nd">@click</span><span class="o">.</span><span class="n">argument</span><span class="p">(</span><span class="s2">"title"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">)</span>
|
||||
</span><span id="__span-19-29"><a id="__codelineno-19-29" name="__codelineno-19-29" href="#__codelineno-19-29"></a> <span class="nd">@click</span><span class="o">.</span><span class="n">pass_context</span>
|
||||
</span><span id="__span-19-30"><a id="__codelineno-19-30" name="__codelineno-19-30" href="#__codelineno-19-30"></a> <span class="k">def</span><span class="w"> </span><span class="nf">cli</span><span class="p">(</span><span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"MYSVC"</span><span class="p">:</span>
|
||||
</span><span id="__span-19-31"><a id="__codelineno-19-31" name="__codelineno-19-31" href="#__codelineno-19-31"></a> <span class="k">return</span> <span class="n">MYSVC</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
</span><span id="__span-19-32"><a id="__codelineno-19-32" name="__codelineno-19-32" href="#__codelineno-19-32"></a>
|
||||
</span><span id="__span-19-33"><a id="__codelineno-19-33" name="__codelineno-19-33" href="#__codelineno-19-33"></a> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
|
||||
</span><span id="__span-19-34"><a id="__codelineno-19-34" name="__codelineno-19-34" href="#__codelineno-19-34"></a> <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
|
||||
</span><span id="__span-19-35"><a id="__codelineno-19-35" name="__codelineno-19-35" href="#__codelineno-19-35"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
||||
</span><span id="__span-19-36"><a id="__codelineno-19-36" name="__codelineno-19-36" href="#__codelineno-19-36"></a>
|
||||
</span><span id="__span-19-37"><a id="__codelineno-19-37" name="__codelineno-19-37" href="#__codelineno-19-37"></a> <span class="k">def</span><span class="w"> </span><span class="nf">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cookies</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">credential</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||||
</span><span id="__span-19-38"><a id="__codelineno-19-38" name="__codelineno-19-38" href="#__codelineno-19-38"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">authenticate</span><span class="p">(</span><span class="n">cookies</span><span class="p">,</span> <span class="n">credential</span><span class="p">)</span>
|
||||
</span><span id="__span-19-39"><a id="__codelineno-19-39" name="__codelineno-19-39" href="#__codelineno-19-39"></a> <span class="c1"># obtain any tokens here, e.g. self.token = ...</span>
|
||||
</span><span id="__span-19-40"><a id="__codelineno-19-40" name="__codelineno-19-40" href="#__codelineno-19-40"></a>
|
||||
</span><span id="__span-19-41"><a id="__codelineno-19-41" name="__codelineno-19-41" href="#__codelineno-19-41"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_titles</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Titles_T</span><span class="p">:</span>
|
||||
</span><span id="__span-19-42"><a id="__codelineno-19-42" name="__codelineno-19-42" href="#__codelineno-19-42"></a> <span class="n">match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">TITLE_RE</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
|
||||
</span><span id="__span-19-43"><a id="__codelineno-19-43" name="__codelineno-19-43" href="#__codelineno-19-43"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span>
|
||||
</span><span id="__span-19-44"><a id="__codelineno-19-44" name="__codelineno-19-44" href="#__codelineno-19-44"></a> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Could not parse a title ID."</span><span class="p">)</span>
|
||||
</span><span id="__span-19-45"><a id="__codelineno-19-45" name="__codelineno-19-45" href="#__codelineno-19-45"></a> <span class="n">meta</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
|
||||
</span><span id="__span-19-46"><a id="__codelineno-19-46" name="__codelineno-19-46" href="#__codelineno-19-46"></a> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"metadata"</span><span class="p">]</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"id"</span><span class="p">))</span>
|
||||
</span><span id="__span-19-47"><a id="__codelineno-19-47" name="__codelineno-19-47" href="#__codelineno-19-47"></a> <span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-19-48"><a id="__codelineno-19-48" name="__codelineno-19-48" href="#__codelineno-19-48"></a> <span class="k">return</span> <span class="n">Movies</span><span class="p">([</span>
|
||||
</span><span id="__span-19-49"><a id="__codelineno-19-49" name="__codelineno-19-49" href="#__codelineno-19-49"></a> <span class="n">Movie</span><span class="p">(</span>
|
||||
</span><span id="__span-19-50"><a id="__codelineno-19-50" name="__codelineno-19-50" href="#__codelineno-19-50"></a> <span class="n">id_</span><span class="o">=</span><span class="n">meta</span><span class="p">[</span><span class="s2">"id"</span><span class="p">],</span>
|
||||
</span><span id="__span-19-51"><a id="__codelineno-19-51" name="__codelineno-19-51" href="#__codelineno-19-51"></a> <span class="n">service</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span>
|
||||
</span><span id="__span-19-52"><a id="__codelineno-19-52" name="__codelineno-19-52" href="#__codelineno-19-52"></a> <span class="n">name</span><span class="o">=</span><span class="n">meta</span><span class="p">[</span><span class="s2">"title"</span><span class="p">],</span>
|
||||
</span><span id="__span-19-53"><a id="__codelineno-19-53" name="__codelineno-19-53" href="#__codelineno-19-53"></a> <span class="n">year</span><span class="o">=</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"year"</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span><span class="p">,</span>
|
||||
</span><span id="__span-19-54"><a id="__codelineno-19-54" name="__codelineno-19-54" href="#__codelineno-19-54"></a> <span class="n">language</span><span class="o">=</span><span class="n">meta</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"originalLanguage"</span><span class="p">),</span>
|
||||
</span><span id="__span-19-55"><a id="__codelineno-19-55" name="__codelineno-19-55" href="#__codelineno-19-55"></a> <span class="n">data</span><span class="o">=</span><span class="n">meta</span><span class="p">,</span>
|
||||
</span><span id="__span-19-56"><a id="__codelineno-19-56" name="__codelineno-19-56" href="#__codelineno-19-56"></a> <span class="p">)</span>
|
||||
</span><span id="__span-19-57"><a id="__codelineno-19-57" name="__codelineno-19-57" href="#__codelineno-19-57"></a> <span class="p">])</span>
|
||||
</span><span id="__span-19-58"><a id="__codelineno-19-58" name="__codelineno-19-58" href="#__codelineno-19-58"></a>
|
||||
</span><span id="__span-19-59"><a id="__codelineno-19-59" name="__codelineno-19-59" href="#__codelineno-19-59"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Tracks</span><span class="p">:</span>
|
||||
</span><span id="__span-19-60"><a id="__codelineno-19-60" name="__codelineno-19-60" href="#__codelineno-19-60"></a> <span class="n">playback</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
|
||||
</span><span id="__span-19-61"><a id="__codelineno-19-61" name="__codelineno-19-61" href="#__codelineno-19-61"></a> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"playback"</span><span class="p">]</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
|
||||
</span><span id="__span-19-62"><a id="__codelineno-19-62" name="__codelineno-19-62" href="#__codelineno-19-62"></a> <span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
</span><span id="__span-19-63"><a id="__codelineno-19-63" name="__codelineno-19-63" href="#__codelineno-19-63"></a> <span class="k">return</span> <span class="n">DASH</span><span class="o">.</span><span class="n">from_url</span><span class="p">(</span>
|
||||
</span><span id="__span-19-64"><a id="__codelineno-19-64" name="__codelineno-19-64" href="#__codelineno-19-64"></a> <span class="n">url</span><span class="o">=</span><span class="n">playback</span><span class="p">[</span><span class="s2">"manifest_url"</span><span class="p">],</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span>
|
||||
</span><span id="__span-19-65"><a id="__codelineno-19-65" name="__codelineno-19-65" href="#__codelineno-19-65"></a> <span class="p">)</span><span class="o">.</span><span class="n">to_tracks</span><span class="p">(</span><span class="n">language</span><span class="o">=</span><span class="n">title</span><span class="o">.</span><span class="n">language</span><span class="p">)</span>
|
||||
</span><span id="__span-19-66"><a id="__codelineno-19-66" name="__codelineno-19-66" href="#__codelineno-19-66"></a>
|
||||
</span><span id="__span-19-67"><a id="__codelineno-19-67" name="__codelineno-19-67" href="#__codelineno-19-67"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_chapters</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Chapters</span><span class="p">:</span>
|
||||
</span><span id="__span-19-68"><a id="__codelineno-19-68" name="__codelineno-19-68" href="#__codelineno-19-68"></a> <span class="k">return</span> <span class="n">Chapters</span><span class="p">()</span>
|
||||
</span><span id="__span-19-69"><a id="__codelineno-19-69" name="__codelineno-19-69" href="#__codelineno-19-69"></a>
|
||||
</span><span id="__span-19-70"><a id="__codelineno-19-70" name="__codelineno-19-70" href="#__codelineno-19-70"></a> <span class="k">def</span><span class="w"> </span><span class="nf">get_widevine_license</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span><span class="p">):</span>
|
||||
</span><span id="__span-19-71"><a id="__codelineno-19-71" name="__codelineno-19-71" href="#__codelineno-19-71"></a> <span class="n">res</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">"endpoints"</span><span class="p">][</span><span class="s2">"license"</span><span class="p">],</span> <span class="n">data</span><span class="o">=</span><span class="n">challenge</span><span class="p">)</span>
|
||||
</span><span id="__span-19-72"><a id="__codelineno-19-72" name="__codelineno-19-72" href="#__codelineno-19-72"></a> <span class="n">res</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
|
||||
</span><span id="__span-19-73"><a id="__codelineno-19-73" name="__codelineno-19-73" href="#__codelineno-19-73"></a> <span class="k">return</span> <span class="n">res</span><span class="o">.</span><span class="n">content</span>
|
||||
</span></code></pre></div>
|
||||
<div class="language-yaml highlight"><span class="filename">services/MYSVC/config.yaml</span><pre><span></span><code><span id="__span-19-1"><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="nt">endpoints</span><span class="p">:</span>
|
||||
</span><span id="__span-19-2"><a id="__codelineno-19-2" name="__codelineno-19-2" href="#__codelineno-19-2"></a><span class="w"> </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.myservice.com/v1/metadata/{id}</span>
|
||||
</span><span id="__span-19-3"><a id="__codelineno-19-3" name="__codelineno-19-3" href="#__codelineno-19-3"></a><span class="w"> </span><span class="nt">playback</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.myservice.com/v1/playback/{id}</span>
|
||||
</span><span id="__span-19-4"><a id="__codelineno-19-4" name="__codelineno-19-4" href="#__codelineno-19-4"></a><span class="w"> </span><span class="nt">license</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.myservice.com/v1/license/widevine</span>
|
||||
<div class="language-yaml highlight"><span class="filename">services/MYSVC/config.yaml</span><pre><span></span><code><span id="__span-20-1"><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="nt">endpoints</span><span class="p">:</span>
|
||||
</span><span id="__span-20-2"><a id="__codelineno-20-2" name="__codelineno-20-2" href="#__codelineno-20-2"></a><span class="w"> </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.myservice.com/v1/metadata/{id}</span>
|
||||
</span><span id="__span-20-3"><a id="__codelineno-20-3" name="__codelineno-20-3" href="#__codelineno-20-3"></a><span class="w"> </span><span class="nt">playback</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.myservice.com/v1/playback/{id}</span>
|
||||
</span><span id="__span-20-4"><a id="__codelineno-20-4" name="__codelineno-20-4" href="#__codelineno-20-4"></a><span class="w"> </span><span class="nt">license</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.myservice.com/v1/license/widevine</span>
|
||||
</span></code></pre></div>
|
||||
<p>Test it with:</p>
|
||||
<div class="language-bash highlight"><pre><span></span><code><span id="__span-20-1"><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a>unshackle<span class="w"> </span>dl<span class="w"> </span>MYSVC<span class="w"> </span>https://myservice.com/watch/abc123
|
||||
<div class="language-bash highlight"><pre><span></span><code><span id="__span-21-1"><a id="__codelineno-21-1" name="__codelineno-21-1" href="#__codelineno-21-1"></a>unshackle<span class="w"> </span>dl<span class="w"> </span>MYSVC<span class="w"> </span>https://myservice.com/watch/abc123
|
||||
</span></code></pre></div>
|
||||
<hr />
|
||||
<h2 id="checklist">Checklist<a class="headerlink" href="#checklist" title="Permanent link">¶</a></h2>
|
||||
@@ -2673,6 +2685,7 @@ flagged, banned, or downgraded.</p>
|
||||
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Tracks come from a manifest parser with <code>to_tracks(language=title.language)</code>; no filtering by quality/language.</li>
|
||||
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Encrypted tracks are marked with DRM; the license callbacks you need return responses <strong>unmodified</strong>.</li>
|
||||
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> URLs, user agents, and certificates live in <code>config.yaml</code>, read via <code>self.config[...]</code>.</li>
|
||||
<li class="task-list-item"><label class="task-list-control"><input type="checkbox" disabled/><span class="task-list-indicator"></span></label> Multi-file services import their own modules relatively (<code>from .helpers import x</code>), so they work when loaded from a repo.</li>
|
||||
</ul>
|
||||
<p>Read <code>unshackle/services/EXAMPLE/</code> end to end; it annotates every feature
|
||||
touched above in one place.</p>
|
||||
|
||||
File diff suppressed because one or more lines are too long
+27
-27
@@ -2,110 +2,110 @@
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/creating-a-service/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/service-architecture/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/rest-api/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/rest-api/authentication/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/rest-api/endpoints/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/rest-api/errors/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/rest-api/job-lifecycle/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/rest-api/quickstart/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/dev/rest-api/remote-sessions/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/getting-started/configuration-file/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/getting-started/installation/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/getting-started/quickstart/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/cli-reference/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/downloading/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/drm-and-cdm/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/output-and-naming/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/proxies-and-vpn/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/subtitles/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/troubleshooting/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/guide/vaults/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/reference/configuration/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/reference/api/config/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/reference/api/drm/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/reference/api/service/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/reference/api/titles/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://docs.unshackle.dev/reference/api/tracks/</loc>
|
||||
<lastmod>2026-07-13</lastmod>
|
||||
<lastmod>2026-07-14</lastmod>
|
||||
</url>
|
||||
</urlset>
|
||||
Binary file not shown.
Reference in New Issue
Block a user