Skip to content

Commit

Permalink
Merge branch 'broken-jtv-header' into 'master'
Browse files Browse the repository at this point in the history
Alternative JTV header and encoding support

See merge request andrey/jtv2xmltv!5
  • Loading branch information
tataranovich committed Nov 4, 2019
2 parents dec5d09 + 7989355 commit 13f7b72
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 21 deletions.
38 changes: 26 additions & 12 deletions jtv2xmltv/convert.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from __future__ import print_function
from xml.etree import ElementTree
import zipfile
import sys
from jtv2xmltv.parser import parse_schedule, parse_titles
from jtv2xmltv.utils import fix_zip_filename


def convert_jtv_to_xmltv(jtv_filename, epg_encoding="utf8", epg_timezone="UTC", epg_lang=None):
def convert_jtv_to_xmltv(jtv_filename, jtv_encoding="cp1251", xmltv_encoding="utf8", xmltv_timezone="UTC",
xmltv_lang=None):
archive = zipfile.ZipFile(jtv_filename, 'r')
xmltv_tv = ElementTree.Element('tv')
channel_id = 0
Expand All @@ -14,23 +17,34 @@ def convert_jtv_to_xmltv(jtv_filename, epg_encoding="utf8", epg_timezone="UTC",
channel_name = unicode_name[0:-4]
channel_id = channel_id + 1
xmltv_channel = ElementTree.SubElement(xmltv_tv, 'channel', id=str(channel_id))
if epg_lang is not None:
ElementTree.SubElement(xmltv_channel, 'display-name', lang=str(epg_lang)).text = channel_name
if xmltv_lang is not None:
ElementTree.SubElement(xmltv_channel, 'display-name', lang=str(xmltv_lang)).text = channel_name
else:
ElementTree.SubElement(xmltv_channel, 'display-name').text = channel_name
channel_id = 0
for filename in archive.namelist():
if filename.endswith('.pdt'):
channel_id = channel_id + 1
titles = archive.read(filename)
channel_titles = parse_titles(titles)
schedules = archive.read(filename[0:-4] + ".ndx")
channel_schedules = parse_schedule(schedules)
try:
titles_filename = filename
titles = archive.read(titles_filename)
channel_titles = parse_titles(titles, encoding=jtv_encoding)
except Exception as e:
print("Failed to process titles in {}: {}".format(titles_filename, str(e)), file=sys.stderr)
continue

try:
schedules_filename = filename[0:-4] + ".ndx"
schedules = archive.read(schedules_filename)
channel_schedules = parse_schedule(schedules)
except Exception as e:
print("Failed to process schedule in {}: {}".format(schedules_filename, str(e)), file=sys.stderr)
continue

i = 0
for curr_title in channel_titles:
if epg_timezone != "UTC":
time_format = '%Y%m%d%H%M%S ' + epg_timezone
if xmltv_timezone != "UTC":
time_format = '%Y%m%d%H%M%S ' + xmltv_timezone
else:
time_format = '%Y%m%d%H%M%S'
if i < len(channel_schedules) - 1:
Expand All @@ -42,10 +56,10 @@ def convert_jtv_to_xmltv(jtv_filename, epg_encoding="utf8", epg_timezone="UTC",
xmltv_programme = ElementTree.SubElement(xmltv_tv, 'programme',
start=channel_schedules[i].strftime(time_format),
channel=str(channel_id))
if epg_lang is not None:
ElementTree.SubElement(xmltv_programme, 'title', lang=str(epg_lang)).text = curr_title
if xmltv_lang is not None:
ElementTree.SubElement(xmltv_programme, 'title', lang=str(xmltv_lang)).text = curr_title
else:
ElementTree.SubElement(xmltv_programme, 'title').text = curr_title
i = i + 1
archive.close()
return ElementTree.tostring(xmltv_tv, encoding=epg_encoding, method="xml").decode(encoding=epg_encoding)
return ElementTree.tostring(xmltv_tv, encoding=xmltv_encoding, method="xml").decode(encoding=xmltv_encoding)
4 changes: 3 additions & 1 deletion jtv2xmltv/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ def main():
parser.add_argument('-i', '--inputfile', required=True)
parser.add_argument('-o', '--outputfile', default='-')
parser.add_argument('-t', '--timezone')
parser.add_argument('-e', '--encoding', default='cp1251')
args = parser.parse_args()
jtv_filename = args.inputfile
xmltv_filename = args.outputfile
jtv_encoding = args.encoding
if args.timezone is None:
tz_format = 'UTC'
elif args.timezone[0] == '-' or args.timezone[0] == '+':
tz_format = str(args.timezone)
else:
tz_format = '+' + str(args.timezone)
xmltv_content = convert_jtv_to_xmltv(jtv_filename, epg_timezone=tz_format)
xmltv_content = convert_jtv_to_xmltv(jtv_filename, jtv_encoding=jtv_encoding, xmltv_timezone=tz_format)
if xmltv_filename is None or xmltv_filename == "-":
print(xmltv_content)
else:
Expand Down
9 changes: 4 additions & 5 deletions jtv2xmltv/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
from jtv2xmltv.utils import filetime_to_datetime


def parse_titles(data):
jtv_header = b"JTV 3.x TV Program Data\x0a\x0a\x0a"
if data[0:26] != jtv_header:
def parse_titles(data, encoding="cp1251"):
jtv_headers = [b"JTV 3.x TV Program Data\x0a\x0a\x0a", b"JTV 3.x TV Program Data\xa0\xa0\xa0"]
if data[0:26] not in jtv_headers:
raise Exception('Invalid JTV format')
data = data[26:]
titles = []
while data:
title_length = int(struct.unpack('<H', data[0:2])[0])
data = data[2:]
# TODO: epg titles encoding could be not cp1251
title = data[0:title_length].decode('cp1251')
title = data[0:title_length].decode(encoding)
data = data[title_length:]
titles.append(title)
return titles
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name="jtv2xmltv",
version="0.1.1",
version="0.2.0",
packages=find_packages(),
entry_points={
'console_scripts': [
Expand All @@ -14,7 +14,7 @@
author_email="tataranovich@gmail.com",
description="JTV to XMLTV converter",
long_description="JTV to XMLTV converter",
license="GPL-3",
license="MIT",
keywords="epg xmltv jtv",
url="https://github.com/tataranovich/jtv2xmltv/",
)
7 changes: 6 additions & 1 deletion tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ def test_correct_jtv_header():
assert parse_titles(data) == []


def test_incorrect_jtv_header():
def test_alternative_jtv_header():
data = b'JTV 3.x TV Program Data\xA0\xA0\xA0'
assert parse_titles(data) == []


def test_incorrect_jtv_header():
data = b'JTV 3.x TV Program Data\xFF\xFF\xFF'
with pytest.raises(Exception):
parse_titles(data)

Expand Down

0 comments on commit 13f7b72

Please sign in to comment.