Files
DemonEditor/app/picons/picons.py

209 lines
6.8 KiB
Python
Raw Normal View History

2018-03-04 19:37:41 +03:00
import glob
2018-01-12 14:32:36 +03:00
import os
import shutil
2018-01-15 14:56:17 +03:00
from collections import namedtuple
2018-01-12 14:32:36 +03:00
from html.parser import HTMLParser
2018-03-07 23:56:21 +03:00
import re
2018-03-04 19:37:41 +03:00
from app.commons import log, run_task
2018-01-12 14:32:36 +03:00
from app.properties import Profile
2018-02-05 14:44:42 +03:00
_ENIGMA2_PICON_KEY = "{:X}:{:X}:{:X}0000"
_NEUTRINO_PICON_KEY = "{:x}{:04x}{:04x}.png"
2018-01-28 23:10:54 +03:00
2018-02-04 18:09:37 +03:00
Provider = namedtuple("Provider", ["logo", "name", "pos", "url", "on_id", "selected"])
2018-01-15 14:56:17 +03:00
Picon = namedtuple("Picon", ["ref", "ssid", "v_pid"])
2018-01-12 14:32:36 +03:00
class PiconsParser(HTMLParser):
2018-01-15 14:56:17 +03:00
""" Parser for package html page. (https://www.lyngsat.com/packages/*provider-name*.html) """
2018-01-12 14:32:36 +03:00
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 = []
2018-01-16 01:16:03 +03:00
self.picons = []
2018-01-12 14:32:36 +03:00
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)
2018-01-16 01:16:03 +03:00
if 9 < ln < 13:
url = None
if row[0].startswith("../logo/"):
url = row[0]
elif row[1].startswith("../logo/"):
url = row[1]
ssid = row[-4]
if url and len(ssid) > 2:
self.picons.append(Picon(url, ssid, row[-3]))
2018-01-12 14:32:36 +03:00
self._current_row = []
def error(self, message):
pass
@staticmethod
2018-02-05 14:44:42 +03:00
def parse(open_path, picons_path, tmp_path, on_id, pos, picon_ids, profile=Profile.ENIGMA_2):
2018-01-12 14:32:36 +03:00
with open(open_path, encoding="utf-8", errors="replace") as f:
parser = PiconsParser()
parser.reset()
parser.feed(f.read())
2018-01-16 01:16:03 +03:00
picons = parser.picons
if picons:
2018-01-12 14:32:36 +03:00
os.makedirs(picons_path, exist_ok=True)
2018-01-16 01:16:03 +03:00
for p in picons:
try:
2018-02-05 14:44:42 +03:00
name = PiconsParser.format(p.ssid, on_id, p.v_pid, pos, picon_ids, profile)
p_name = picons_path + (name if name else os.path.basename(p.ref))
shutil.copyfile(tmp_path + "www.lyngsat.com/" + p.ref.lstrip("."), p_name)
2018-01-16 01:16:03 +03:00
except (TypeError, ValueError) as e:
2018-02-05 14:44:42 +03:00
log("Picons format parse error: {}".format(p) + "\n" + str(e))
2018-01-16 01:16:03 +03:00
print(e)
2018-01-12 14:32:36 +03:00
@staticmethod
2018-02-05 14:44:42 +03:00
def format(ssid, on_id, v_pid, pos, picon_ids, profile: Profile):
2018-01-17 01:18:02 +03:00
tr_id = int(ssid[:-2] if len(ssid) < 4 else ssid[:2])
2018-01-12 14:32:36 +03:00
if profile is Profile.ENIGMA_2:
2018-02-05 14:44:42 +03:00
return picon_ids.get(_ENIGMA2_PICON_KEY.format(int(ssid), int(on_id), int(pos)), None)
2018-01-12 14:32:36 +03:00
elif profile is Profile.NEUTRINO_MP:
2018-02-05 14:44:42 +03:00
return _NEUTRINO_PICON_KEY.format(tr_id, int(on_id), int(ssid))
2018-01-12 14:32:36 +03:00
else:
return "{}.png".format(ssid)
2018-01-15 14:56:17 +03:00
class ProviderParser(HTMLParser):
""" Parser for satellite html page. (https://www.lyngsat.com/*sat-name*.html) """
2018-03-07 23:56:21 +03:00
_POSITION_PATTERN = re.compile("at\s\d+\..*(?:E|W)']")
2018-01-15 14:56:17 +03:00
def __init__(self, entities=False, separator=' '):
HTMLParser.__init__(self)
self._ON_ID_BLACK_LIST = ("65535", "?", "0", "1")
self._parse_html_entities = entities
self._separator = separator
self._is_td = False
self._is_th = False
self._is_provider = False
self._current_row = []
self._current_cell = []
self.rows = []
self._ids = set()
2018-02-04 18:09:37 +03:00
self._positon = None
2018-01-15 14:56:17 +03:00
def handle_starttag(self, tag, attrs):
if tag == 'td':
self._is_td = True
if tag == 'tr':
self._is_th = True
if tag == "img":
if attrs[0][1].startswith("logo/"):
self._current_row.append(attrs[0][1])
if tag == "a":
if "https://www.lyngsat.com/packages/" in attrs[0][1]:
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 == 'tr':
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
2018-02-04 18:09:37 +03:00
# Satellite position
2018-03-07 23:56:21 +03:00
if not self._positon:
pos = re.findall(self._POSITION_PATTERN, str(row))
if pos:
self._positon = "".join(c for c in str(pos) if c.isdigit() or c in ".EW")
2018-02-04 18:09:37 +03:00
2018-01-15 14:56:17 +03:00
if len(row) == 12:
on_id, sep, tid = str(row[-2]).partition("-")
if tid and on_id not in self._ON_ID_BLACK_LIST and on_id not in self._ids:
2018-01-16 01:16:03 +03:00
row[-2] = on_id
2018-01-15 14:56:17 +03:00
self.rows.append(row)
self._ids.add(on_id)
2018-02-04 18:09:37 +03:00
row[0] = self._positon
2018-01-15 14:56:17 +03:00
self._current_row = []
def error(self, message):
pass
2018-02-05 14:44:42 +03:00
def reset(self):
super().reset()
2018-02-04 18:09:37 +03:00
2018-01-15 14:56:17 +03:00
def parse_providers(open_path):
2018-02-05 14:44:42 +03:00
parser = ProviderParser()
parser.reset()
2018-01-15 14:56:17 +03:00
with open(open_path, encoding="utf-8", errors="replace") as f:
parser.feed(f.read())
rows = parser.rows
if rows:
2018-02-04 18:09:37 +03:00
return [Provider(logo=r[2], name=r[5], pos=r[0], url=r[6], on_id=r[-2], selected=True) for r in rows]
2018-01-15 14:56:17 +03:00
2018-03-04 19:37:41 +03:00
@run_task
def convert_to(src_path, dest_path, profile, callback, done_callback):
""" Converts names format of picons.
Copies resulting files from src to dest and writes state to callback.
"""
pattern = "/*_0_0_0.png" if profile is Profile.ENIGMA_2 else "/*.png"
for file in glob.glob(src_path + pattern):
base_name = os.path.basename(file)
pic_data = base_name.rstrip(".png").split("_")
dest_file = _NEUTRINO_PICON_KEY.format(int(pic_data[4], 16), int(pic_data[5], 16), int(pic_data[3], 16))
dest = "{}/{}".format(dest_path, dest_file)
callback('Converting "{}" to "{}"\n'.format(base_name, dest_file))
shutil.copyfile(file, dest)
done_callback()
2018-01-12 14:32:36 +03:00
if __name__ == "__main__":
pass