Use sqlite for storage
This commit is contained in:
parent
ed4ddf1d01
commit
f6628730d6
3 changed files with 117 additions and 57 deletions
|
@ -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]
|
||||||
|
|
||||||
|
|
22
src/main.py
22
src/main.py
|
@ -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
1
src/yt_subs.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue