mirror of
https://github.com/vinefeeder/TwinVine.git
synced 2026-07-15 18:10:04 +02:00
updates
This commit is contained in:
@@ -136,6 +136,7 @@ def result(service: Service, profile: Optional[str] = None, **_: Any) -> None:
|
||||
result_text = f"[bold text]{result.title}[/]"
|
||||
if result.url:
|
||||
result_text = f"[link={result.url}]{result_text}[/link]"
|
||||
|
||||
if result.label:
|
||||
result_text += f" [pink]{result.label}[/]"
|
||||
if result.description:
|
||||
@@ -143,7 +144,7 @@ def result(service: Service, profile: Optional[str] = None, **_: Any) -> None:
|
||||
result_text += f"\n[bright_black]id: {result.id}[/]"
|
||||
search_results.add(result_text + "\n")
|
||||
|
||||
# update cookies
|
||||
# update cookie
|
||||
cookie_file = dl.get_cookie_path(service_tag, profile)
|
||||
if cookie_file:
|
||||
dl.save_cookies(cookie_file, service.session.cookies)
|
||||
|
||||
@@ -9,6 +9,7 @@ class SearchResult:
|
||||
description: Optional[str] = None,
|
||||
label: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
image: Optional[str] = None
|
||||
):
|
||||
"""
|
||||
A Search Result for any support Title Type.
|
||||
@@ -33,12 +34,15 @@ class SearchResult:
|
||||
raise TypeError(f"Expected label to be a {str}, not {type(label)}")
|
||||
if not isinstance(url, (str, type(None))):
|
||||
raise TypeError(f"Expected url to be a {str}, not {type(url)}")
|
||||
|
||||
if not isinstance(image, (str, type(None))):
|
||||
raise TypeError(f"Expected image to be a {str}, not {type(image)}")
|
||||
|
||||
self.id = id_
|
||||
self.title = title
|
||||
self.description = description
|
||||
self.label = label
|
||||
self.url = url
|
||||
self.image = image
|
||||
|
||||
|
||||
__all__ = ("SearchResult",)
|
||||
|
||||
@@ -22,8 +22,8 @@ class STV(Service):
|
||||
Service code for STV Player streaming service (https://player.stv.tv/).
|
||||
|
||||
\b
|
||||
Version: 1.0.3
|
||||
Author: stabbedbybrick
|
||||
Version: 1.0.4
|
||||
Author: stabbedbybrick; search corrected by Angela
|
||||
Authorization: None
|
||||
Robustness:
|
||||
L3: 1080p
|
||||
@@ -68,6 +68,7 @@ class STV(Service):
|
||||
synopsis = result['attributes']["long_description"]
|
||||
|
||||
label = result["attributes"]["subGenre"]
|
||||
#image = result["attributes"]["images"][0]["_filepath"].split("&w")[0] if result["attributes"]["images"] else None
|
||||
|
||||
yield SearchResult(
|
||||
id_= self.config["endpoints"]["prefix"].strip("/") + result["attributes"]["permalink"],
|
||||
@@ -75,6 +76,7 @@ class STV(Service):
|
||||
description=synopsis,
|
||||
label=label,
|
||||
url=url,
|
||||
#image=image
|
||||
)
|
||||
|
||||
def get_titles(self) -> Union[Movies, Series]:
|
||||
|
||||
@@ -43,10 +43,10 @@ class TPTV(Service):
|
||||
Service code for TPTVencore streaming service (https://www.TPTVencore.co.uk/).
|
||||
|
||||
\b
|
||||
version 1.1.0
|
||||
Date: June 2026
|
||||
version 1.3.0
|
||||
Date: July 2026
|
||||
Author: A_n_g_e_l_a
|
||||
Authorization: email/password for service in envied.yaml
|
||||
Authorization: email/password for service in envied.yaml
|
||||
Robustness:
|
||||
DRM free... with rare exceptions L3
|
||||
|
||||
@@ -190,8 +190,29 @@ class TPTV(Service):
|
||||
self.authorization = tokens
|
||||
|
||||
def search(self) -> Generator[SearchResult, None, None]:
|
||||
print(f"Searching not implemented in Envied for TPTVencore. Please use VineFeeder instead.")
|
||||
return None
|
||||
|
||||
search_term = self.title.replace(" ", "+")
|
||||
response = self.session.get(self.config["endpoints"]["search"].format(query=search_term))
|
||||
response.raise_for_status()
|
||||
results = json.loads(response.content.decode("utf-8"))
|
||||
|
||||
for result in results["data"]:
|
||||
url = result['video']['playback'].replace("api/core/play", "playback")
|
||||
title = result['title']
|
||||
synopsis = result['description'].replace('\n', ' ')
|
||||
label = result["subtype"]
|
||||
id = result["video"]["playback"].replace("api/core/play", "playback")
|
||||
|
||||
|
||||
yield SearchResult(
|
||||
id_= id,
|
||||
title=title,
|
||||
description=synopsis,
|
||||
label=label,
|
||||
url=url,
|
||||
)
|
||||
|
||||
|
||||
|
||||
def get_titles(self) -> Union[Movies, Series]:
|
||||
data = self.get_data(self.title)
|
||||
|
||||
@@ -178,7 +178,7 @@ class BaseLoader:
|
||||
|
||||
return
|
||||
|
||||
def add_episode(self, series_name, episode):
|
||||
def add_episode(self, series_name, episode, uhd=None):
|
||||
"""Add an episode to the series in memory.
|
||||
Episode may be Any"""
|
||||
if series_name not in self.series_data:
|
||||
@@ -246,13 +246,19 @@ class BaseLoader:
|
||||
def get_final_episode_list(self):
|
||||
return self.final_episode_data
|
||||
|
||||
def display_final_episode_list(self, final_episode_data):
|
||||
def display_final_episode_list(self, final_episode_data, check_uhd=False):
|
||||
"""Use beaupy to display episodes for a selected series."""
|
||||
# episodes = self.series_data.get(series_name, [])
|
||||
episode_list = [
|
||||
f"{ep['series_no']}, {ep['title']}, {ep['url']}, \n\t {ep['synopsis']}"
|
||||
for ep in final_episode_data
|
||||
]
|
||||
if check_uhd:
|
||||
episode_list = [
|
||||
f"{ep['series_no']}, {ep['title']}, {ep['url']}, UHD={ep['uhd']}, \n\t {ep['synopsis']}"
|
||||
for ep in final_episode_data
|
||||
]
|
||||
else:
|
||||
episode_list = [
|
||||
f"{ep['series_no']}, {ep['title']}, {ep['url']}, \n\t {ep['synopsis']}"
|
||||
for ep in final_episode_data
|
||||
]
|
||||
selected_episodes = select_multiple(
|
||||
episode_list,
|
||||
preprocessor=lambda val: prettify(val),
|
||||
|
||||
@@ -9,6 +9,7 @@ from vinefeeder.parsing_utils import extract_params_json, parse_json, split, spl
|
||||
from rich.console import Console
|
||||
import jmespath
|
||||
from scrapy.selector import Selector
|
||||
import json
|
||||
|
||||
console = Console()
|
||||
|
||||
@@ -151,7 +152,7 @@ class BbcLoader(BaseLoader):
|
||||
print(
|
||||
"Error downloading video:",
|
||||
e,
|
||||
"Is self.DOWNLOAD_ORCHESTRATOR installed correctly via 'pip install self.DOWNLOAD_ORCHESTRATOR?",
|
||||
f"Is {self.DOWNLOAD_ORCHESTRATOR} installed correctly via 'pip install {self.DOWNLOAD_ORCHESTRATOR}?",
|
||||
)
|
||||
|
||||
else:
|
||||
@@ -166,7 +167,7 @@ class BbcLoader(BaseLoader):
|
||||
print(
|
||||
"Error downloading video:",
|
||||
e,
|
||||
"Is self.DOWNLOAD_ORCHESTRATOR installed correctly via 'pip install self.DOWNLOAD_ORCHESTRATOR?",
|
||||
f"Is {self.DOWNLOAD_ORCHESTRATOR} installed correctly via 'pip install {self.DOWNLOAD_ORCHESTRATOR}?",
|
||||
)
|
||||
|
||||
return
|
||||
@@ -213,15 +214,11 @@ class BbcLoader(BaseLoader):
|
||||
def fetch_videos(self, search_term):
|
||||
"""Fetch videos from BBC using a search term."""
|
||||
|
||||
url = "https://ibl.api.bbc.co.uk/ibl/v1/new-search"
|
||||
# url = f"https://search.api.bbci.co.uk/formula/iplayer-ibl-root?q={search_term}&apikey=D2FgtcTxGqqIgLsfBWTJdrQh2tVdeaAp&seqId=0582e0f0-b911-11ee-806c-11c6c885ab56"
|
||||
params = {
|
||||
"q": search_term,
|
||||
"rights": "web",
|
||||
#'mixin': 'live'
|
||||
}
|
||||
url = f"https://ibl.api.bbc.co.uk/ibl/v1/new-search?q={search_term}&rights=mobile&size=10&sort=relevance&start=0"
|
||||
|
||||
|
||||
try:
|
||||
html = self.get_data(url, self.headers, params)
|
||||
html = self.get_data(url, self.headers)
|
||||
if "new_search" not in html:
|
||||
print("Nothing found for that search; try again.")
|
||||
return
|
||||
@@ -290,10 +287,10 @@ class BbcLoader(BaseLoader):
|
||||
parsed_data = parse_json(myhtml)
|
||||
|
||||
# testing
|
||||
#file = open("init_data.json", "w")
|
||||
#file.write(json.dumps(parsed_data))
|
||||
#file.close()
|
||||
#console.print_json(data=parsed_data)
|
||||
# file = open("init_data.json", "w")
|
||||
# file.write(json.dumps(parsed_data))
|
||||
# file.close()
|
||||
# console.print_json(data=parsed_data)
|
||||
|
||||
self.clear_series_data() # Clear existing series data
|
||||
self.options_list = split_options(self.options)
|
||||
@@ -317,6 +314,8 @@ class BbcLoader(BaseLoader):
|
||||
episodes = parsed_data.get("programme_episodes").get("elements")
|
||||
for item in episodes:
|
||||
try:
|
||||
# programme_episodes►elements►0►versions►0►uhd
|
||||
uhd = item.get("versions", [{}])[0].get("uhd", False)
|
||||
series_no = item["subtitle"].split(":")[0].split(" ")[1]
|
||||
if int(series_no):
|
||||
pass
|
||||
@@ -330,21 +329,23 @@ class BbcLoader(BaseLoader):
|
||||
], # .split(' ')[-1] or '01',
|
||||
"url": "https://www.bbc.co.uk/iplayer/episode/" + item["id"],
|
||||
"synopsis": item["synopses"]["small"] or None,
|
||||
"uhd": uhd or False,
|
||||
}
|
||||
except Exception:
|
||||
try:
|
||||
episode = {
|
||||
"series_no": 100, # special or one-off'
|
||||
"series_no": int(100), # special or one-off'
|
||||
# 'title' is episode number here, some services use descriptive text
|
||||
"title": item["subtitle"], # could be date
|
||||
"url": "https://www.bbc.co.uk/iplayer/episode/"
|
||||
+ item["id"],
|
||||
"synopsis": item["synopses"]["small"] or None,
|
||||
"uhd": item.get("versions", [{}])[0].get("uhd", False) or False,
|
||||
}
|
||||
except KeyError as e:
|
||||
print(f"Error: {e}")
|
||||
continue # Skip any episode that doesn't have the required information
|
||||
self.add_episode(series_name, episode)
|
||||
self.add_episode(series_name, episode, uhd=uhd)
|
||||
|
||||
# Single episode expedite download
|
||||
else:
|
||||
@@ -356,6 +357,9 @@ class BbcLoader(BaseLoader):
|
||||
self.AVAILABLE_HLG = True
|
||||
break
|
||||
# self.options_list = split_options(self.options)
|
||||
|
||||
|
||||
|
||||
try:
|
||||
if BbcLoader.HLG and self.AVAILABLE_HLG:
|
||||
command = (
|
||||
@@ -378,7 +382,7 @@ class BbcLoader(BaseLoader):
|
||||
print(
|
||||
"Error downloading video:",
|
||||
e,
|
||||
"Is self.DOWNLOAD_ORCHESTRATOR installed correctly via 'pip install self.DOWNLOAD_ORCHESTRATOR?",
|
||||
f"Is {self.DOWNLOAD_ORCHESTRATOR} installed correctly via 'pip install {self.DOWNLOAD_ORCHESTRATOR}'?",
|
||||
)
|
||||
return
|
||||
|
||||
@@ -386,17 +390,22 @@ class BbcLoader(BaseLoader):
|
||||
series_name
|
||||
) # creates list of series; allows user selection of wanted series prepares an episode list over chosen series
|
||||
selected_final_episodes = self.display_final_episode_list(
|
||||
self.final_episode_data
|
||||
self.final_episode_data, check_uhd=True
|
||||
)
|
||||
|
||||
# specific to BBC
|
||||
# self.options_list = split_options(self.options)
|
||||
for item in selected_final_episodes:
|
||||
# check for UHD content
|
||||
for hlg_item in self.uhd_list:
|
||||
if series_name.lower() in hlg_item:
|
||||
self.AVAILABLE_HLG = True
|
||||
break
|
||||
#print(type(item))
|
||||
#print(item)
|
||||
for part in item.split(","):
|
||||
if "UHD" in part:
|
||||
uhd = part.split("UHD=")[1].strip()
|
||||
# Sanity check for UHD content
|
||||
if uhd=="True":
|
||||
self.AVAILABLE_HLG = True
|
||||
else:
|
||||
self.AVAILABLE_HLG = False
|
||||
for part in item.split(","):
|
||||
if "https" in part:
|
||||
url = part.strip()
|
||||
@@ -419,7 +428,7 @@ class BbcLoader(BaseLoader):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
beaupylist = []
|
||||
#beaupylist = []
|
||||
|
||||
req = self.client.get(browse_url, headers=self.headers)
|
||||
init_data = extract_params_json(req.content.decode(), "__IPLAYER_REDUX_STATE__")
|
||||
|
||||
Reference in New Issue
Block a user