Initial support for all programs A-Ö

This feature is not yet really usable since it takes a really long
time to load all programs sequentially and synchronously.
main
Micke Nordin 2 years ago
parent 564f64106a
commit 30544ac026
Signed by: micke
GPG Key ID: 0DA0A7A5708FE257

@ -162,6 +162,7 @@ class Cast(wx.Frame):
SVT.SVT("ch-svt24"), SVT.SVT("ch-svt24"),
SVT.SVT("ch-barnkanalen"), SVT.SVT("ch-barnkanalen"),
SVT.SVT("ch-kunskapskanalen"), SVT.SVT("ch-kunskapskanalen"),
SVT.SVT("allprograms"),
], ],
) )

@ -6,17 +6,17 @@ from datetime import datetime
import feedparser import feedparser
import requests import requests
import wx import wx
from bs4 import BeautifulSoup
from Channel import Channel from Channel import Channel
from Items import Item from Items import Item
from Utils import (add_video, hash_string, make_bitmap_from_url, from Utils import (add_video, get_all_svt_programs, get_svt_id, get_svt_thumbnail, hash_string, make_bitmap_from_url,
resolve_svt_channel, video_exists) resolve_svt_channel, video_exists)
default_rss_url = 'http://www.svtplay.se/rss.xml' default_rss_url = 'http://www.svtplay.se/rss.xml'
class SVT(Channel): class SVT(Channel):
def __init__(self, channel_id: str) -> None: def __init__(self, channel_id: str) -> None:
chan_dict = resolve_svt_channel(channel_id) chan_dict = resolve_svt_channel(channel_id)
logo = chan_dict['thumbnail'] logo = chan_dict['thumbnail']
@ -24,7 +24,6 @@ class SVT(Channel):
super().__init__(channel_id, 'SVT', default_rss_url, logo, name) super().__init__(channel_id, 'SVT', default_rss_url, logo, name)
def parse_feed(self) -> None: def parse_feed(self) -> None:
#self.m_items: list[Item] = list()
resolved_link = str() resolved_link = str()
description = str() description = str()
title = str() title = str()
@ -33,7 +32,7 @@ class SVT(Channel):
published_parsed: datetime = datetime.now() published_parsed: datetime = datetime.now()
video_id = str() video_id = str()
if self.m_id == 'feed' : if self.m_id == 'feed':
feed = feedparser.parse(self.get_feed()) feed = feedparser.parse(self.get_feed())
entries = feed['entries'] entries = feed['entries']
for entry in entries: for entry in entries:
@ -46,16 +45,7 @@ class SVT(Channel):
thumbnail_link = str(link['href']) thumbnail_link = str(link['href'])
break break
page = requests.get(str(entry['link'])) svt_id = get_svt_id(str(entry['link']))
soup = BeautifulSoup(page.text, 'html.parser')
for element in soup.find_all('a'):
href = element.get('href')
datart = element.get('data-rt')
if datart == 'top-area-play-button':
svt_id = href.split('=')[1].split('&')[0]
resolved_link = self.resolve_link(svt_id) resolved_link = self.resolve_link(svt_id)
description = str(entry['description']) description = str(entry['description'])
published_parsed = entry['published_parsed'] published_parsed = entry['published_parsed']
@ -67,9 +57,40 @@ class SVT(Channel):
item = Item(description, resolved_link, self.m_provider_name, item = Item(description, resolved_link, self.m_provider_name,
published_parsed, thumbnail, title) published_parsed, thumbnail, title)
self.m_items.append(item) self.m_items.append(item)
add_video(video_id, self.m_id, self.m_provider_name, description, add_video(video_id, self.m_id, self.m_provider_name,
resolved_link, published_parsed, thumbnail, title, 0) description, resolved_link, published_parsed,
thumbnail, title, 0)
elif self.m_id == 'allprograms':
entries = get_all_svt_programs()
for entry in entries:
url = entry['item']['urls']['svtplay']
video_id = hash_string(url.split('/')[1])
svt_id = str()
link = "https://svtplay.se{}".format(url)
if video_exists(video_id, 'allprograms'):
continue
thumbnail_link = get_svt_thumbnail(link)
svt_id = get_svt_id(link)
resolved_link = self.resolve_link(svt_id)
title = str(entry['heading'])
type = str(entry['item']['__typename'])
published_parsed = datetime.now()
swe_only = "no"
if entry['item']['restrictions']['onlyAvailableInSweden']:
swe_only = 'yes'
description = "{}\nOnly available in Sweden:{}\nType of program:{}".format(title, swe_only, type)
if not resolved_link:
continue
thumbnail = make_bitmap_from_url(
thumbnail_link, wx.Size(int(self.m_screen_width), 150))
item = Item(description, resolved_link, self.m_provider_name,
published_parsed, thumbnail, title, sort_key = entry['selection_name'])
self.m_items.append(item)
add_video(video_id, self.m_id, self.m_provider_name,
description, resolved_link, published_parsed,
thumbnail, title, 0)
else: else:
chan_dict = resolve_svt_channel(self.m_id) chan_dict = resolve_svt_channel(self.m_id)
resolved_link = self.resolve_link(self.m_id) resolved_link = self.resolve_link(self.m_id)
@ -83,12 +104,10 @@ class SVT(Channel):
published_parsed, thumbnail, title) published_parsed, thumbnail, title)
self.m_items.append(item) self.m_items.append(item)
def resolve_link(self, svt_id) -> str:
def resolve_link(self,svt_id) -> str:
url = 'https://api.svt.se/video/{}'.format(svt_id) url = 'https://api.svt.se/video/{}'.format(svt_id)
print(url) print(url)
api = json.loads( api = json.loads(requests.get(url).text)
requests.get(url).text)
resolved_link = '' resolved_link = ''
try: try:
@ -98,4 +117,3 @@ class SVT(Channel):
except KeyError: except KeyError:
pass pass
return resolved_link return resolved_link

@ -1,6 +1,5 @@
#/usr/bin/env python3 #/usr/bin/env python3
import threading import threading
import time
from os import path from os import path
import wx import wx

@ -1,5 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from datetime import datetime from datetime import datetime
from typing import Union
import wx import wx
@ -12,7 +13,9 @@ class Item(dict):
published: datetime, published: datetime,
thumbnail: wx.Bitmap, thumbnail: wx.Bitmap,
title: str, title: str,
watchtime: int = 0): watchtime: int = 0,
sort_key: Union[str, None] = None,
):
self.__dict__['description'] = description self.__dict__['description'] = description
self.__dict__['link'] = link self.__dict__['link'] = link
self.__dict__['provider_id'] = provider_id self.__dict__['provider_id'] = provider_id
@ -20,6 +23,7 @@ class Item(dict):
self.__dict__['thumbnail'] = thumbnail self.__dict__['thumbnail'] = thumbnail
self.__dict__['title'] = title self.__dict__['title'] = title
self.__dict__['watchtime'] = watchtime self.__dict__['watchtime'] = watchtime
self.__dict__['sort_key'] = sort_key
def __setitem__(self, key, item): def __setitem__(self, key, item):
self.__dict__[key] = item self.__dict__[key] = item

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import hashlib import hashlib
import io import io
import json
import sqlite3 import sqlite3
import time import time
from datetime import datetime from datetime import datetime
@ -9,12 +10,13 @@ from typing import Callable, Union
import requests import requests
import wx import wx
from bs4 import BeautifulSoup
from Items import Item from Items import Item
HEIGHT = int(1440 / 2) HEIGHT = int(1440 / 2)
BTN_HEIGHT = 40 BTN_HEIGHT = 40
SIZE = wx.Size(68,100) SIZE = wx.Size(68, 100)
SCREEN_WIDTH = int(720 / 2) SCREEN_WIDTH = int(720 / 2)
BASEPATH = path.join(str(environ.get("HOME")), '.config/cast') BASEPATH = path.join(str(environ.get("HOME")), '.config/cast')
DB_FILE_NAME = 'cast.db' DB_FILE_NAME = 'cast.db'
@ -67,7 +69,27 @@ def add_video(video_id: str,
con.commit() con.commit()
def get_default_logo(providerid: str = 'default', path: str = '/usr/share/cast') -> wx.Bitmap: def get_all_svt_programs() -> list:
url = 'https://www.svtplay.se/program'
res = requests.get(url)
soup = BeautifulSoup(res.text, features="lxml")
data = json.loads(
soup.find(id="__NEXT_DATA__").string)["props"]["urqlState"]
programs = list()
for key in data.keys():
temp = json.loads(data[key]["data"])
if "programAtillO" in temp.keys():
for selection in temp["programAtillO"]["selections"]:
for item in selection["items"]:
item['selection_name'] = selection['name']
programs.append(item)
return programs
def get_default_logo(providerid: str = 'default',
path: str = '/usr/share/cast') -> wx.Bitmap:
if providerid == 'SVT': if providerid == 'SVT':
return wx.Bitmap('{}/assets/SVT.png'.format(path)) return wx.Bitmap('{}/assets/SVT.png'.format(path))
else: else:
@ -140,6 +162,29 @@ def get_subscriptions(basepath: str = BASEPATH,
return subscriptions return subscriptions
def get_svt_id(link: str) -> str:
svt_id = str()
page = requests.get(link)
soup = BeautifulSoup(page.text, 'html.parser')
for element in soup.find_all('a'):
href = element.get('href')
datart = element.get('data-rt')
if datart == 'top-area-play-button':
svt_id = href.split('=')[1].split('&')[0]
return svt_id
def get_svt_thumbnail(link: str) -> str:
page = requests.get(link)
soup = BeautifulSoup(page.text, 'html.parser')
meta = soup.find(property="og:image")
image_link = meta["content"]
return image_link
def get_videos(channel_id: str, def get_videos(channel_id: str,
basepath: str = BASEPATH, basepath: str = BASEPATH,
filename: str = DB_FILE_NAME) -> list[Item]: filename: str = DB_FILE_NAME) -> list[Item]:
@ -181,7 +226,7 @@ def hash_string(string: str) -> str:
def make_sized_button(parent_pnl: wx.Panel, bitmap_or_str: Union[wx.Bitmap, def make_sized_button(parent_pnl: wx.Panel, bitmap_or_str: Union[wx.Bitmap,
str], str],
text: str, callback: Callable) -> wx.BoxSizer: text: str, callback: Callable) -> wx.BoxSizer:
btn_sizer = wx.StaticBoxSizer(wx.HORIZONTAL,parent_pnl) btn_sizer = wx.StaticBoxSizer(wx.HORIZONTAL, parent_pnl)
if type(bitmap_or_str) == type(str): if type(bitmap_or_str) == type(str):
if bitmap_or_str.startswith('http'): # type: ignore if bitmap_or_str.startswith('http'): # type: ignore
bitmap = make_bitmap_from_url(bitmap_or_str) # type: ignore bitmap = make_bitmap_from_url(bitmap_or_str) # type: ignore
@ -194,7 +239,7 @@ def make_sized_button(parent_pnl: wx.Panel, bitmap_or_str: Union[wx.Bitmap,
wx.ID_ANY, wx.ID_ANY,
bitmap, bitmap,
style=btn_style, style=btn_style,
size=wx.Size(100,68)) size=wx.Size(100, 68))
btn_logo.SetToolTip(text) btn_logo.SetToolTip(text)
btn_sizer.Add(btn_logo, 0, wx.EXPAND, 1) btn_sizer.Add(btn_logo, 0, wx.EXPAND, 1)
@ -202,8 +247,7 @@ def make_sized_button(parent_pnl: wx.Panel, bitmap_or_str: Union[wx.Bitmap,
wx.ID_ANY, wx.ID_ANY,
text, text,
style=wx.BORDER_NONE | wx.BU_AUTODRAW, style=wx.BORDER_NONE | wx.BU_AUTODRAW,
size=wx.Size(SCREEN_WIDTH - 100, size=wx.Size(SCREEN_WIDTH - 100, SIZE.GetHeight()))
SIZE.GetHeight()))
btn_text.SetToolTip(text) btn_text.SetToolTip(text)
btn_sizer.Add(btn_text, 0, wx.EXPAND, 1) btn_sizer.Add(btn_text, 0, wx.EXPAND, 1)
parent_pnl.Bind(wx.EVT_BUTTON, callback, btn_logo) parent_pnl.Bind(wx.EVT_BUTTON, callback, btn_logo)
@ -255,8 +299,7 @@ def resolve_svt_channel(svt_id: str, path: str = '/usr/share/cast') -> dict:
make_bitmap_from_file('{}/assets/SVT2.png'.format(path)) make_bitmap_from_file('{}/assets/SVT2.png'.format(path))
}, },
"ch-svt24": { "ch-svt24": {
"name": "name": "SVT 24",
"SVT 24",
"thumbnail": "thumbnail":
make_bitmap_from_file('{}/assets/SVT24.png'.format(path)) make_bitmap_from_file('{}/assets/SVT24.png'.format(path))
}, },
@ -264,14 +307,18 @@ def resolve_svt_channel(svt_id: str, path: str = '/usr/share/cast') -> dict:
"name": "name":
"Kunskapskanalen", "Kunskapskanalen",
"thumbnail": "thumbnail":
make_bitmap_from_file( make_bitmap_from_file('{}/assets/Kunskapskanalen.png'.format(path))
'{}/assets/Kunskapskanalen.png'.format(path))
}, },
"feed": { "feed": {
"name": "Senaste program", "name": "Senaste program",
"thumbnail": "thumbnail":
make_bitmap_from_file('{}/assets/SVT.png'.format(path)) make_bitmap_from_file('{}/assets/SVT.png'.format(path))
}, },
"allprograms": {
"name": "Alla program",
"thumbnail":
make_bitmap_from_file('{}/assets/SVT.png'.format(path))
},
} }
return channels[svt_id] return channels[svt_id]

Loading…
Cancel
Save