diff --git a/app/picons/picons.py b/app/picons/picons.py new file mode 100644 index 00000000..0b32d0a6 --- /dev/null +++ b/app/picons/picons.py @@ -0,0 +1,84 @@ +import os +import shutil +from html.parser import HTMLParser + +from app.properties import Profile + + +class PiconsParser(HTMLParser): + """ Parser for html page. (https://www.lyngsat.com/) """ + + def __init__(self, entities=False, separator=' '): + + HTMLParser.__init__(self) + + self._parse_html_entities = entities + self._separator = separator + self._is_td = False + self._is_th = False + self._current_row = [] + self._current_cell = [] + self.rows = [] + + def handle_starttag(self, tag, attrs): + if tag == 'td': + self._is_td = True + if tag == 'th': + self._is_th = True + if tag == "img": + self._current_row.append(attrs[0][1]) + + def handle_data(self, data): + """ Save content to a cell """ + if self._is_td or self._is_th: + self._current_cell.append(data.strip()) + + def handle_endtag(self, tag): + if tag == 'td': + self._is_td = False + elif tag == 'th': + self._is_th = False + + if tag in ('td', 'th'): + final_cell = self._separator.join(self._current_cell).strip() + self._current_row.append(final_cell) + self._current_cell = [] + elif tag == 'tr': + row = self._current_row + ln = len(row) + if ln == 10 and row[0].startswith("../logo/"): + self.rows.append((row[0], row[-4])) + elif ln == 11: + self.rows.append((row[0] if row[0].startswith("../logo/") else row[1], row[-4])) + self._current_row = [] + + def error(self, message): + pass + + @staticmethod + def parse(open_path, picons_path, tmp_path): + with open(open_path, encoding="utf-8", errors="replace") as f: + parser = PiconsParser() + parser.reset() + parser.feed(f.read()) + rows = parser.rows + + if rows: + os.makedirs(picons_path, exist_ok=True) + for r in rows: + shutil.copyfile(tmp_path + "www.lyngsat.com/" + r[0].lstrip("."), + picons_path + PiconsParser.format(r[1], Profile.ENIGMA_2)) + + @staticmethod + def format(ssid, profile: Profile): + if profile is Profile.ENIGMA_2: + tr_id = int(ssid[:-2] if len(ssid) < 4 else ssid[:2]) + return "1_0_1_{:X}_{:X}_{}_1680000_0_0_0.png".format(int(ssid), tr_id, "70") + elif profile is Profile.NEUTRINO_MP: + return "{:x}{}{:x}".format(int(ssid[:-2]), "0070", int(ssid)) + else: + return "{}.png".format(ssid) + + +if __name__ == "__main__": + pass diff --git a/app/properties.py b/app/properties.py index bb2f8eb5..f80bd484 100644 --- a/app/properties.py +++ b/app/properties.py @@ -48,7 +48,7 @@ def get_default_settings(): "satellites_xml_path": "/etc/tuxbox/", "picons_path": "/usr/share/enigma2/picon", "data_dir_path": DATA_PATH + "enigma2/", - "picons_dir_path": DATA_PATH + "enigma2/picons"}, + "picons_dir_path": DATA_PATH + "enigma2/picons/"}, Profile.NEUTRINO_MP.value: { "host": "127.0.0.1", "port": "21", "user": "root", "password": "root", @@ -59,7 +59,7 @@ def get_default_settings(): "satellites_xml_path": "/var/tuxbox/config/", "picons_path": "/usr/share/tuxbox/neutrino/icons/logo/", "data_dir_path": DATA_PATH + "neutrino/", - "picons_dir_path": DATA_PATH + "neutrino/picons"}, + "picons_dir_path": DATA_PATH + "neutrino/picons/"}, "profile": Profile.ENIGMA_2.value} diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index 3ac9f80c..831bebea 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -587,6 +587,7 @@ True False False + Up Up True gtk-go-up @@ -602,6 +603,7 @@ True False False + Down Down True gtk-go-down @@ -740,7 +742,7 @@ True False False - Rename bouquet + Edit Edit True gtk-edit diff --git a/app/ui/picons_dialog.glade b/app/ui/picons_dialog.glade index 018eda67..8672fe8b 100644 --- a/app/ui/picons_dialog.glade +++ b/app/ui/picons_dialog.glade @@ -3,7 +3,8 @@ - 400 + 480 + True False Picons download tool False @@ -55,6 +56,143 @@ False vertical 2 + + + True + False + Satellite url (www.lyngsat.com): + 0.019999999552965164 + + + False + True + 0 + + + + + True + True + network-workgroup-symbolic + False + https://www.lyngsat.com/packages/'your-provider'.html + url + + + False + True + 1 + + + + + True + False + + + True + False + + + + + + True + True + + + + + True + False + center + True + Load providers + True + gtk-goto-bottom + + + True + True + + + + + True + False + + + + + + True + True + + + + + + True + True + 2 + + + + + 120 + True + True + out + + + True + True + + + + + + Provider + + + + + + + + + + + Select + + + + + Url + + + + + + + True + True + 3 + + + + + True + False + + + False + True + 4 + + True @@ -108,46 +246,7 @@ False True - 0 - - - - - True - False - - - False - True - 1 - - - - - True - False - Url: - 0.019999999552965164 - - - False - True - 2 - - - - - True - True - network-workgroup-symbolic - False - https://www.lyngsat.com/packages/'your-provider'.html - url - - - False - True - 3 + 5 @@ -160,7 +259,7 @@ False True - 4 + 6 @@ -174,7 +273,83 @@ False True - 5 + 7 + + + + + True + False + 2 + 2 + + + False + True + 8 + + + + + True + False + 5 + + + True + False + 5 + Picons name format: + + + False + True + 0 + + + + + Enigma2 (default) + True + True + False + 0 + True + True + radiobutton2 + + + False + True + 1 + + + + + Neutrino-MP + True + False + True + False + 0 + True + True + radiobutton1 + + + False + True + 2 + + + + + + False + True + 9 @@ -186,7 +361,7 @@ False True 2 - 6 + 10 @@ -255,7 +430,7 @@ False True - 7 + 11 @@ -292,7 +467,7 @@ False True - 8 + 12 @@ -358,7 +533,7 @@ False True - 9 + 13 @@ -369,7 +544,7 @@ False True - 10 + 14 diff --git a/app/ui/picons_dialog.py b/app/ui/picons_dialog.py index e4885117..9e4f937f 100644 --- a/app/ui/picons_dialog.py +++ b/app/ui/picons_dialog.py @@ -1,14 +1,19 @@ +import subprocess +import tempfile import time from gi.repository import GLib from app.commons import run_idle, run_task +from app.picons.picons import PiconsParser from . import Gtk, UI_RESOURCES_PATH from .main_helper import update_entry_data class PiconsDialog: def __init__(self, transient, options): + self._TMP_DIR = tempfile.gettempdir() + "/" + self._BASE_URL = "www.lyngsat.com/packages/" self._current_process = None self._picons_path = options.get("picons_dir_path", "") @@ -50,23 +55,35 @@ class PiconsDialog: def start_download(self): self._expander.set_expanded(True) self.show_info_message("Please, wait...", Gtk.MessageType.INFO) - # self._current_process = subprocess.Popen("ls", - # stdout=subprocess.PIPE, - # stderr=subprocess.PIPE, - # universal_newlines=True) - # GLib.io_add_watch(self._current_process.stderr, GLib.IO_IN, self.write_to_buffer) + url = "https://" + self._BASE_URL + "NTV-Plus.html" + self._current_process = subprocess.Popen(["wget", "-pkP", self._TMP_DIR, url], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + GLib.io_add_watch(self._current_process.stderr, GLib.IO_IN, self.write_to_buffer) + self.batch_rename() + + @run_task + def batch_rename(self): + self._current_process.wait() + path = self._TMP_DIR + self._BASE_URL + "NTV-Plus.html" + PiconsParser.parse(path, self._picons_path, self._TMP_DIR) + self.show_info_message("Done", Gtk.MessageType.INFO) - @run_idle def write_to_buffer(self, fd, condition): if condition == GLib.IO_IN: char = fd.read(1) - buf = self._text_view.get_buffer() - buf.insert_at_cursor(char) - self.scroll_to_end(buf) + self.append_output(char) return True else: return False + @run_idle + def append_output(self, char): + buf = self._text_view.get_buffer() + buf.insert_at_cursor(char) + self.scroll_to_end(buf) + def scroll_to_end(self, buf): insert = buf.get_insert() self._text_view.scroll_to_mark(insert, 0.0, True, 0.0, 1.0)