Skip to content

Commit de3fa1f

Browse files
committed
add features and fixes
Adds generic timezone lineups Adds station/channels icons Removes old episode data from cache
1 parent ac7f0cd commit de3fa1f

File tree

3 files changed

+64
-37
lines changed

3 files changed

+64
-37
lines changed

addon.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<addon id="script.module.zap2epg" name="zap2epg" version="0.2.1" provider-name="edit4ever">
2+
<addon id="script.module.zap2epg" name="zap2epg" version="0.3.0" provider-name="edit4ever">
33
<requires>
44
<import addon="xbmc.python" version="2.7.13"/>
55
<import addon="script.module.dateutil" version="2.4.2"/>
@@ -11,7 +11,7 @@
1111
</extension>
1212
<extension point="xbmc.addon.metadata">
1313
<summary lang="en_gb">zap2epg will generate an xmltv.xml file for USA/Canada TV lineups</summary>
14-
<description lang="en_gb">zap2epg is originally designed to be easily setup in Kodi for use as a grabber for tvheadend. It includes the ability to setup your custom channel list to reduce the amount of data downloaded and speed up the grab. It has an option for downloading extra detail information for programs. (Note: this option will generate an extra http request per episode) It also has an option to append the extra detail information to the description (plot) field, which makes displaying this information in the Kodi EPG easier on many skins.
14+
<description lang="en_gb">zap2epg is originally designed to be easily setup in Kodi for use as a grabber for tvheadend. It includes the ability to setup your custom channel list to reduce the amount of data downloaded and speed up the grab. It has an option for downloading extra detail information for programs. (Note: this option will generate an extra http request per series) It also has an option to append the extra detail information to the description (plot) field, which makes displaying this information in the Kodi EPG easier on many skins.
1515

1616
Setup:
1717
1. Install the zap2epg addon in Kodi
@@ -29,6 +29,7 @@ Setup:
2929
<email></email>
3030
<source></source>
3131
<news>
32+
v0.3.0 - adds generic timezone lineups and station/channels icons | removes old episode data from cache (2017-11-07)
3233
v0.2.1 - fix for location name and JSON file errors (2017-11-02)
3334
v0.2.0 - modified for new zap2it guide data (2017-10-27)
3435
v0.1.0 - initial test release (2017-10-24)

default.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
os.mkdir(userdata)
3535
log = os.path.join(userdata, 'zap2epg.log')
3636
Clist = os.path.join(userdata, 'channels.json')
37+
cacheDir = os.path.join(userdata, 'cache')
3738
plugin = Plugin()
3839
dialog = xbmcgui.Dialog()
3940
gridtime = (int(time.mktime(time.strptime(str(datetime.datetime.now().replace(microsecond=0,second=0,minute=0)), '%Y-%m-%d %H:%M:%S'))))
@@ -101,19 +102,23 @@ def channels():
101102

102103
@plugin.route('/location')
103104
def location():
105+
country = ['USA', 'CAN']
106+
countryNew = dialog.select('Select your country', list=country)
104107
zipcodeNew = dialog.input('Enter your zipcode', defaultt=zipcode, type=xbmcgui.INPUT_ALPHANUM)
105108
if not zipcodeNew:
106109
return
107110
zipcodeNew =re.sub(' ', '', zipcodeNew)
108111
xbmcaddon.Addon().setSetting(id='zipcode', value=zipcodeNew)
109-
if zipcodeNew.isdigit():
112+
if countryNew == 0:
110113
url = 'https://tvlistings.gracenote.com/gapzap_webapi/api/Providers/getPostalCodeProviders/USA/' + zipcodeNew
111-
else:
114+
lineupsN = ['AVAILABLE LINEUPS', 'TIMEZONE - Eastern', 'TIMEZONE - Central', 'TIMEZONE - Mountain', 'TIMEZONE - Pacific', 'TIMEZONE - Alaskan', 'TIMEZONE - Hawaiian']
115+
lineupsC = ['NONE', 'DFLTE', 'DFLTC', 'DFLTM', 'DFLTP', 'DFLTA', 'DFLTH']
116+
if countryNew == 1:
112117
url = 'https://tvlistings.gracenote.com/gapzap_webapi/api/Providers/getPostalCodeProviders/CAN/' + zipcodeNew
118+
lineupsN = ['AVAILABLE LINEUPS', 'TIMEZONE - Eastern', 'TIMEZONE - Central', 'TIMEZONE - Mountain', 'TIMEZONE - Pacific']
119+
lineupsC = ['NONE', 'DFLTEC', 'DFLTCC', 'DFLTMC', 'DFLTPC']
113120
content = urllib2.urlopen(url).read()
114121
lineupDict = json.loads(content)
115-
lineupsN = ['AVAILABLE LINEUPS']
116-
lineupsC = ['NONE']
117122
if 'Providers' in lineupDict:
118123
for provider in lineupDict['Providers']:
119124
lineupName = provider.get('name')
@@ -133,6 +138,16 @@ def location():
133138
lineupSelName = lineupsN[lineupSel]
134139
xbmcaddon.Addon().setSetting(id='lineupcode', value=lineupSelCode)
135140
xbmcaddon.Addon().setSetting(id='lineup', value=lineupSelName)
141+
if os.path.exists(cacheDir):
142+
entries = os.listdir(cacheDir)
143+
for entry in entries:
144+
oldfile = entry.split('.')[0]
145+
if oldfile.isdigit():
146+
fn = os.path.join(cacheDir, entry)
147+
try:
148+
os.remove(fn)
149+
except:
150+
pass
136151
xbmc.executebuiltin('Container.Refresh')
137152
else:
138153
xbmc.executebuiltin('Container.Refresh')

zap2epg.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import sys
2828
from os.path import dirname
2929
import xml.etree.ElementTree as ET
30+
from collections import OrderedDict
3031

3132

3233
def mainRun(userdata):
@@ -70,7 +71,7 @@ def mainRun(userdata):
7071
gridtimeStart = (int(time.mktime(time.strptime(str(datetime.datetime.now().replace(microsecond=0,second=0,minute=0)), '%Y-%m-%d %H:%M:%S'))))
7172
schedule = {}
7273

73-
def deleteOldCache(gridtime):
74+
def deleteOldCache(gridtimeStart, showList):
7475
logging.info('Checking for old cache files...')
7576
try:
7677
if os.path.exists(cacheDir):
@@ -79,22 +80,20 @@ def deleteOldCache(gridtime):
7980
oldfile = entry.split('.')[0]
8081
if oldfile.isdigit():
8182
fn = os.path.join(cacheDir, entry)
82-
if (int(oldfile) + 10800) < gridtime:
83+
if (int(oldfile) + 10800) < gridtimeStart:
84+
try:
85+
os.remove(fn)
86+
logging.info('Deleting old cache: %s', entry)
87+
except OSError, e:
88+
logging.warn('Error Deleting: %s - %s.' % (e.filename, e.strerror))
89+
elif not oldfile.isdigit():
90+
fn = os.path.join(cacheDir, entry)
91+
if oldfile not in showList:
8392
try:
8493
os.remove(fn)
8594
logging.info('Deleting old cache: %s', entry)
8695
except OSError, e:
8796
logging.warn('Error Deleting: %s - %s.' % (e.filename, e.strerror))
88-
# elif not oldfile.isdigit():
89-
# episodeSet = {j for i in schedule.values() for j in i}
90-
# episodeList = list(episodeSet)
91-
# fn = os.path.join(cacheDir, entry)
92-
# if oldfile not in episodeList:
93-
# try:
94-
# os.remove(fn)
95-
# logging.info('Deleting old cache: %s', entry)
96-
# except OSError, e:
97-
# logging.warn('Error Deleting: %s - %s.' % (e.filename, e.strerror))
9897
except Exception as e:
9998
logging.exception('Exception: deleteOldCache')
10099

@@ -155,20 +154,26 @@ def printStations(fh):
155154
stationCount = 0
156155
try:
157156
logging.info('Writing Stations to xmltv.xml file...')
158-
for station in schedule:
157+
try:
158+
scheduleSort = OrderedDict(sorted(schedule.iteritems(), key=lambda x: int(x[1]['chnum'])))
159+
except:
160+
scheduleSort = OrderedDict(sorted(schedule.iteritems(), key=lambda x: x[1]['chfcc']))
161+
for station in scheduleSort:
159162
fh.write('\t<channel id=\"' + station + '.zap2epg\">\n')
160-
if 'chnum' in schedule[station] and 'chfcc' in schedule[station]:
161-
xchnum = schedule[station]['chnum']
162-
xchfcc = schedule[station]['chfcc']
163-
fh.write('\t\t<display-name>' + xchnum + ' ' + xchfcc + '</display-name>\n')
163+
if 'chnum' in scheduleSort[station] and 'chfcc' in scheduleSort[station]:
164+
xchnum = scheduleSort[station]['chnum']
165+
xchfcc = scheduleSort[station]['chfcc']
164166
fh.write('\t\t<display-name>' + xchfcc + '</display-name>\n')
165167
fh.write('\t\t<display-name>' + xchnum + '</display-name>\n')
166-
elif 'chfcc' in schedule[station]:
167-
xchnum = schedule[station]['chfcc']
168+
fh.write('\t\t<display-name>' + xchnum + ' ' + xchfcc + '</display-name>\n')
169+
elif 'chfcc' in scheduleSort[station]:
170+
xchnum = scheduleSort[station]['chfcc']
168171
fh.write('\t\t<display-name>' + xcfcc + '</display-name>\n')
169-
elif 'chnum' in schedule[station]:
170-
xchnum = schedule[station]['chnum']
172+
elif 'chnum' in scheduleSort[station]:
173+
xchnum = scheduleSort[station]['chnum']
171174
fh.write('\t\t<display-name>' + xchnum + '</display-name>\n')
175+
if 'chicon' in scheduleSort[station]:
176+
fh.write("\t\t<icon src=\"http:" + scheduleSort[station]['chicon'] + "\" />\n")
172177
fh.write("\t</channel>\n")
173178
stationCount += 1
174179
except Exception as e:
@@ -209,14 +214,17 @@ def printEpisodes(fh):
209214
fh.write("\t\t<episode-num system=\"xmltv_ns\">" + str(int(edict['epsn'])-1) + "." + str(int(edict['epen'])-1) + ".</episode-num>\n")
210215
if edict['epyear'] is not None:
211216
fh.write('\t\t<date>' + edict['epyear'] + '</date>\n')
212-
if edict['epthumb'] is not None or edict['epimage'] is not None:
213-
if not episode.startswith("MV"):
214-
if epicon == '1':
217+
if not episode.startswith("MV"):
218+
if epicon == '1':
219+
if edict['epimage'] is not None:
215220
fh.write('\t\t<icon src="https://zap2it.tmsimg.com/assets/' + edict['epimage'] + '.jpg" />\n')
216-
if epicon == '2':
221+
else:
217222
fh.write('\t\t<icon src="https://zap2it.tmsimg.com/assets/' + edict['epthumb'] + '.jpg" />\n')
218-
else:
219-
fh.write('\t\t<icon src="https://zap2it.tmsimg.com/assets/' + edict['epthumb'] + '.jpg" />\n')
223+
if epicon == '2':
224+
if edict['epthumb'] is not None:
225+
fh.write('\t\t<icon src="https://zap2it.tmsimg.com/assets/' + edict['epthumb'] + '.jpg" />\n')
226+
if episode.startswith("MV"):
227+
fh.write('\t\t<icon src="https://zap2it.tmsimg.com/assets/' + edict['epthumb'] + '.jpg" />\n')
220228
if not any(i in ['New', 'Live'] for i in edict['epflag']):
221229
fh.write("\t\t<previously-shown ")
222230
if edict['epoad'] is not None and int(edict['epoad']) > 0:
@@ -277,10 +285,12 @@ def parseStations(content):
277285
schedule[skey] = {}
278286
schedule[skey]['chnum'] = station.get('channelNo')
279287
schedule[skey]['chfcc'] = station.get('callSign')
288+
schedule[skey]['chicon'] = station.get('thumbnail').split('?')[0]
280289
else:
281290
schedule[skey] = {}
282291
schedule[skey]['chnum'] = station.get('channelNo')
283292
schedule[skey]['chfcc'] = station.get('callSign')
293+
schedule[skey]['chicon'] = station.get('thumbnail').split('?')[0]
284294
except Exception as e:
285295
logging.exception('Exception: parseStations')
286296

@@ -293,7 +303,6 @@ def parseEpisodes(content):
293303
if skey in stationList:
294304
episodes = station.get('events')
295305
for episode in episodes:
296-
#epkeyStart = str(calendar.timegm(time.strptime(episode.get('startTime'), '%Y-%m-%dT%H:%M:%SZ')))
297306
epkey = episode['program'].get('tmsId')
298307
schedule[skey][epkey] = {}
299308
schedule[skey][epkey]['epid'] = episode['program'].get('tmsId')
@@ -322,7 +331,6 @@ def parseEpisodes(content):
322331
else:
323332
episodes = station.get('events')
324333
for episode in episodes:
325-
#epkeyStart = str(calendar.timegm(time.strptime(episode.get('startTime'), '%Y-%m-%dT%H:%M:%SZ')))
326334
epkey = episode['program'].get('tmsId')
327335
schedule[skey][epkey] = {}
328336
schedule[skey][epkey]['epid'] = episode['program'].get('tmsId')
@@ -352,13 +360,15 @@ def parseEpisodes(content):
352360
logging.exception('Exception: parseEpisodes')
353361

354362
def parseXdetails():
363+
showList = []
355364
try:
356365
for station in schedule:
357366
sdict = schedule[station]
358367
for episode in sdict:
359368
if not episode.startswith("ch"):
360369
edict = sdict[episode]
361370
EPseries = edict['epseries']
371+
showList.append(edict['epseries'])
362372
filename = EPseries + '.json'
363373
fileDir = os.path.join(cacheDir, filename)
364374
try:
@@ -421,6 +431,7 @@ def parseXdetails():
421431
#os.remove(fileDir)
422432
except Exception as e:
423433
logging.exception('Exception: parseXdetails')
434+
return showList
424435

425436
def addXDetails(edict):
426437
try:
@@ -594,9 +605,9 @@ def makeDescsortList(optList):
594605
count += 1
595606
gridtime = gridtime + 10800
596607
if xdetails == 'true':
597-
parseXdetails()
608+
showList = parseXdetails()
598609
xmltv()
599-
deleteOldCache(gridtimeStart)
610+
deleteOldCache(gridtimeStart, showList)
600611
timeRun = round((time.time() - pythonStartTime),2)
601612
logging.info('zap2epg completed in %s seconds. ', timeRun)
602613
logging.info('%s Stations and %s Episodes written to xmltv.xml file.', str(stationCount), str(episodeCount))

0 commit comments

Comments
 (0)