Use sqlite for storage

This commit is contained in:
Micke Nordin 2022-01-07 18:16:13 +01:00
parent ed4ddf1d01
commit f6628730d6
Signed by untrusted user who does not match committer: micke
GPG key ID: 0DA0A7A5708FE257
3 changed files with 117 additions and 57 deletions

View file

@ -1,15 +1,40 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import io import io
from os import path import json
from posixpath import relpath import sqlite3
from os import environ, makedirs, path
from typing import Callable, Union
from urllib.parse import urlparse
import requests import requests
import wx import wx
from typing import Union, Callable
SIZE = wx.Size(100,68) SIZE = wx.Size(100, 68)
MYPATH = path.dirname(path.abspath(__file__)) MYPATH = path.dirname(path.abspath(__file__))
SCREEN_WIDTH = 720 /2 SCREEN_WIDTH = int(720 / 2)
BASEPATH = path.join(str(environ.get("HOME")), '.config/cast')
DB_FILE_NAME = 'cast.db'
SUB_TABLE = 'subscriptions'
def add_subscription(channel_id: str,
name: str,
basepath: str = BASEPATH,
filename: str = DB_FILE_NAME) -> None:
fullpath = path.join(basepath, filename)
if not path.isdir(basepath):
makedirs(basepath)
con = sqlite3.connect(fullpath)
cur = con.cursor()
create_query: str = '''CREATE TABLE IF NOT EXISTS {}
(channel_id TEXT PRIMARY KEY, channel_name TEXT)'''.format(SUB_TABLE)
cur.execute(create_query)
con.commit()
upsert_query: str = '''INSERT INTO {} (channel_id, channel_name)
VALUES('{}',"{}") ON CONFLICT(channel_id) DO NOTHING'''.format(SUB_TABLE, channel_id, name)
cur.execute(upsert_query)
con.commit()
def get_default_logo(providerid: str = 'default') -> wx.Bitmap: def get_default_logo(providerid: str = 'default') -> wx.Bitmap:
if providerid == 'SVT': if providerid == 'SVT':
@ -19,32 +44,65 @@ def get_default_logo(providerid: str = 'default') -> wx.Bitmap:
else: else:
return wx.Bitmap('{}/assets/Default.png'.format(MYPATH)) return wx.Bitmap('{}/assets/Default.png'.format(MYPATH))
def make_sized_button(parent_pnl: wx.Panel, bitmap_or_str: Union[wx.Bitmap,str], text: str, callback: Callable) -> wx.BoxSizer:
btn_sizer = wx.BoxSizer(wx.HORIZONTAL) def get_subscriptions(basepath: str = BASEPATH,
if type(bitmap_or_str) == type(str): filename: str = DB_FILE_NAME) -> list[tuple[str, str]]:
if bitmap_or_str.startswith('http'): # type: ignore subscriptions = list()
bitmap = make_bitmap_from_url(bitmap_or_str) # type: ignore fullpath = path.join(basepath, filename)
else: con = sqlite3.connect(fullpath)
bitmap = wx.Bitmap(bitmap_or_str, wx.BITMAP_TYPE_ANY) cur = con.cursor()
select_query = '''SELECT * FROM {}'''.format(SUB_TABLE)
cur.execute(select_query)
for result in cur.fetchall():
print(result)
subscriptions.append(result)
return subscriptions
def import_from_newpipe(filename) -> None:
if path.isfile(filename):
with open(filename, 'r') as subs:
sub_data = json.loads(subs.read())
for channel in sub_data['subscriptions']:
if channel['service_id'] == 0:
channel_id = urlparse(channel['url']).path.split('/').pop()
add_subscription(channel_id, channel['name'])
def make_sized_button(parent_pnl: wx.Panel, bitmap_or_str: Union[wx.Bitmap,
str],
text: str, callback: Callable) -> wx.BoxSizer:
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
if type(bitmap_or_str) == type(str):
if bitmap_or_str.startswith('http'): # type: ignore
bitmap = make_bitmap_from_url(bitmap_or_str) # type: ignore
else: else:
bitmap = bitmap_or_str bitmap = wx.Bitmap(bitmap_or_str, wx.BITMAP_TYPE_ANY)
btn_style = wx.BORDER_NONE | wx.BU_AUTODRAW | wx.BU_EXACTFIT | wx.BU_NOTEXT else:
btn_logo = wx.BitmapButton(parent_pnl, wx.ID_ANY, bitmap , style=btn_style) bitmap = bitmap_or_str
btn_logo.SetMinSize(SIZE) btn_style = wx.BORDER_NONE | wx.BU_AUTODRAW | wx.BU_EXACTFIT | wx.BU_NOTEXT
btn_logo.SetToolTip(text) btn_logo = wx.BitmapButton(parent_pnl, wx.ID_ANY, bitmap, style=btn_style)
btn_sizer.Add(btn_logo, 0, wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.TOP, 1) btn_logo.SetMinSize(SIZE)
btn_logo.SetToolTip(text)
btn_sizer.Add(btn_logo, 0, wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.TOP, 1)
btn_text = wx.Button(parent_pnl, wx.ID_ANY, text, style=wx.BORDER_NONE | wx.BU_AUTODRAW) btn_text = wx.Button(parent_pnl,
btn_text.SetMinSize(wx.Size(SCREEN_WIDTH - SIZE.GetWidth(),SIZE.GetHeight())) wx.ID_ANY,
btn_text.SetToolTip(text) text,
btn_sizer.Add(btn_text, 0, wx.BOTTOM | wx.RIGHT | wx.TOP | wx.EXPAND, 1) style=wx.BORDER_NONE | wx.BU_AUTODRAW)
parent_pnl.Bind(wx.EVT_BUTTON, callback, btn_logo) btn_text.SetMinSize(
parent_pnl.Bind(wx.EVT_BUTTON, callback, btn_text) wx.Size(SCREEN_WIDTH - SIZE.GetWidth(), SIZE.GetHeight()))
btn_text.SetToolTip(text)
btn_sizer.Add(btn_text, 0, wx.BOTTOM | wx.RIGHT | wx.TOP | wx.EXPAND, 1)
parent_pnl.Bind(wx.EVT_BUTTON, callback, btn_logo)
parent_pnl.Bind(wx.EVT_BUTTON, callback, btn_text)
return btn_sizer return btn_sizer
def make_bitmap_from_url(logo_url: str, size: wx.Size = SIZE ) -> wx.Bitmap: def make_bitmap_from_url(logo_url: str, size: wx.Size = SIZE) -> wx.Bitmap:
res = requests.get(logo_url) res = requests.get(logo_url)
content = res.content content = res.content
content_bytes = io.BytesIO(content) content_bytes = io.BytesIO(content)
@ -52,53 +110,58 @@ def make_bitmap_from_url(logo_url: str, size: wx.Size = SIZE ) -> wx.Bitmap:
scale_factor = image.GetWidth() / SCREEN_WIDTH scale_factor = image.GetWidth() / SCREEN_WIDTH
size.SetWidth(SCREEN_WIDTH) size.SetWidth(SCREEN_WIDTH)
height = image.GetHeight() height = image.GetHeight()
size.SetHeight(height/scale_factor) size.SetHeight(height / scale_factor)
image.Rescale(size.GetWidth(), size.GetHeight() ) image.Rescale(size.GetWidth(), size.GetHeight())
return wx.Bitmap(image) return wx.Bitmap(image)
def make_bitmap_from_file(path, size: wx.Size = SIZE) -> wx.Bitmap: def make_bitmap_from_file(path, size: wx.Size = SIZE) -> wx.Bitmap:
image = wx.Image(path, type=wx.BITMAP_TYPE_ANY, index=-1) image = wx.Image(path, type=wx.BITMAP_TYPE_ANY, index=-1)
# scale_factor = image.GetWidth() / SCREEN_WIDTH # scale_factor = image.GetWidth() / SCREEN_WIDTH
# size.SetWidth(SCREEN_WIDTH) # size.SetWidth(SCREEN_WIDTH)
# height = image.GetHeight() # height = image.GetHeight()
# size.SetHeight(height/scale_factor) # size.SetHeight(height/scale_factor)
# image.Rescale(size.GetWidth(), size.GetHeight() ) # image.Rescale(size.GetWidth(), size.GetHeight() )
return wx.Bitmap(image) return wx.Bitmap(image)
def resolve_svt_channel(svt_id: str) -> dict: def resolve_svt_channel(svt_id: str) -> dict:
channels = { channels = {
"ch-barnkanalen": { "ch-barnkanalen": {
"name": "name":
"Barnkanalen", "Barnkanalen",
"thumbnail": make_bitmap_from_file('{}/assets/Barnkanalen.png'.format(MYPATH)) "thumbnail":
make_bitmap_from_file('{}/assets/Barnkanalen.png'.format(MYPATH))
}, },
"ch-svt1": { "ch-svt1": {
"name": "name": "SVT 1",
"SVT 1", "thumbnail":
"thumbnail": make_bitmap_from_file('{}/assets/SVT1.png'.format(MYPATH)) make_bitmap_from_file('{}/assets/SVT1.png'.format(MYPATH))
}, },
"ch-svt2": { "ch-svt2": {
"name": "name": "SVT 2",
"SVT 2", "thumbnail":
"thumbnail": make_bitmap_from_file('{}/assets/SVT2.png'.format(MYPATH)) make_bitmap_from_file('{}/assets/SVT2.png'.format(MYPATH))
}, },
"ch-svt24": { "ch-svt24": {
"name": "name":
"SVT 24", "SVT 24",
"thumbnail": make_bitmap_from_file('{}/assets/SVT24.png'.format(MYPATH)) "thumbnail":
make_bitmap_from_file('{}/assets/SVT24.png'.format(MYPATH))
}, },
"ch-kunskapskanalen": { "ch-kunskapskanalen": {
"name": "name":
"Kunskapskanalen", "Kunskapskanalen",
"thumbnail": make_bitmap_from_file('{}/assets/Kunskapskanalen.png'.format(MYPATH)) "thumbnail":
make_bitmap_from_file(
'{}/assets/Kunskapskanalen.png'.format(MYPATH))
}, },
"feed": { "feed": {
"name": "Senaste program", "name": "Senaste program",
"thumbnail": make_bitmap_from_file('{}/assets/SVT.png'.format(MYPATH)) "thumbnail":
make_bitmap_from_file('{}/assets/SVT.png'.format(MYPATH))
}, },
} }
return channels[svt_id] return channels[svt_id]

View file

@ -13,10 +13,10 @@ import wx.media
from Channel import SVT, YouTube from Channel import SVT, YouTube
from ChannelProvider import ChannelProvider from ChannelProvider import ChannelProvider
from Utils import make_sized_button from Utils import get_subscriptions, import_from_newpipe, make_sized_button
WIDTH = 720 / 2 WIDTH = int(720 / 2)
HEIGHT = 1440 / 2 HEIGHT = int(1440 / 2)
BTN_HEIGHT = 40 BTN_HEIGHT = 40
SPACER_HEIGHT = 10 SPACER_HEIGHT = 10
SCROLL_RATE = 5 SCROLL_RATE = 5
@ -91,15 +91,11 @@ class Cast(wx.Frame):
subfile = 'yt_subs.json' subfile = 'yt_subs.json'
if os.path.isfile(subfile): if os.path.isfile(subfile):
with open(subfile, 'r') as subs: import_from_newpipe(subfile)
janson = json.loads(subs.read()) subscriptions = get_subscriptions()
for channel in subscriptions:
for channel in janson['subscriptions']: print(channel)
if channel['service_id'] == 0: youtube.append_channel(YouTube.YouTube(channel[0], channel[1]))
channel_id = urlparse(
channel['url']).path.split('/').pop()
youtube.append_channel(
YouTube.YouTube(channel_id, channel['name']))
providers.append(youtube) providers.append(youtube)
@ -217,7 +213,7 @@ class Cast(wx.Frame):
inner_sizer = wx.GridBagSizer() inner_sizer = wx.GridBagSizer()
self.m_control = wx.media.MediaCtrl( self.m_control = wx.media.MediaCtrl(
self.m_panel, self.m_panel,
size=(WIDTH, HEIGHT / 2), size=(WIDTH, int(HEIGHT / 2)),
style=wx.SIMPLE_BORDER, style=wx.SIMPLE_BORDER,
szBackend=wx.media.MEDIABACKEND_GSTREAMER, szBackend=wx.media.MEDIABACKEND_GSTREAMER,
) )

1
src/yt_subs.json Normal file

File diff suppressed because one or more lines are too long