From 2883e4751328bc9162a4d5a564266e3f3dab0e5c Mon Sep 17 00:00:00 2001 From: stabbedbybrick <125766685+stabbedbybrick@users.noreply.github.com> Date: Sun, 28 Jul 2024 15:10:12 +0200 Subject: [PATCH] feat(services): Add CBS service --- services/CBS/__init__.py | 241 +++++++++++++++++++++++++++++++++++++++ services/CBS/config.yaml | 10 ++ 2 files changed, 251 insertions(+) create mode 100644 services/CBS/__init__.py create mode 100644 services/CBS/config.yaml diff --git a/services/CBS/__init__.py b/services/CBS/__init__.py new file mode 100644 index 0000000..e35e4d8 --- /dev/null +++ b/services/CBS/__init__.py @@ -0,0 +1,241 @@ +from __future__ import annotations + +import json +import re +import sys +from collections.abc import Generator +from typing import Any, Optional, Union +from urllib.parse import urljoin + +import click +from devine.core.constants import AnyTrack +from devine.core.manifests import DASH +from devine.core.search_result import SearchResult +from devine.core.service import Service +from devine.core.titles import Episode, Series, Title_T, Titles_T +from devine.core.tracks import Chapter, Chapters, Tracks +from devine.core.utils.sslciphers import SSLCiphers +from devine.core.utils.xml import load_xml +from requests import Request + + +class CBS(Service): + """ + \b + Service code for CBS.com streaming service (https://cbs.com). + Credit to @srpen6 for the tip on anonymous session + + \b + Author: stabbedbybrick + Authorization: None + Robustness: + Widevine: + L3: 2160p, DDP5.1 + + \b + Tips: + - Input should be complete URLs: + SERIES: https://www.cbs.com/shows/tracker/ + EPISODE: https://www.cbs.com/shows/video/E0wG_ovVMkLlHOzv7KDpUV9bjeKFFG2v/ + + \b + Common VPN/proxy errors: + - SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING]')) + - ConnectionError: 406 Not Acceptable, 403 Forbidden + + """ + + GEOFENCE = ("us",) + + @staticmethod + @click.command(name="CBS", short_help="https://cbs.com", help=__doc__) + @click.argument("title", type=str, required=False) + @click.pass_context + def cli(ctx, **kwargs) -> CBS: + return CBS(ctx, **kwargs) + + def __init__(self, ctx, title): + self.title = title + super().__init__(ctx) + + def search(self) -> Generator[SearchResult, None, None]: + params = { + "term": self.title, + "termCount": 50, + "showCanVids": "true", + } + results = self._request("GET", "/apps-api/v3.1/androidphone/contentsearch/search.json", params=params)["terms"] + + for result in results: + yield SearchResult( + id_=result.get("path"), + title=result.get("title"), + description=None, + label=result.get("term_type"), + url=result.get("path"), + ) + + def get_titles(self) -> Titles_T: + title_re = r"https://www\.cbs\.com/shows/(?P