forked from beralt/horepg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
horepgd.py
executable file
·137 lines (121 loc) · 5.18 KB
/
horepgd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# horepgd.py
#
# This script provides a daemon which runs daily
import os
import sys
import pwd
import grp
import logging
import logging.handlers
import argparse
from horepg.horizon import *
from horepg.oorboekje import *
from horepg.tvheadend import *
from horepg.xmltvdoc import *
def switch_user(uid = None, gid = None):
# set gid first
if gid is not None:
os.setgid(gid)
if uid is not None:
os.setuid(uid)
def daemonize():
def fork_exit_parent():
try:
pid = os.fork()
if pid > 0:
# parent, so exit
sys.exit(0)
except OSError as exc:
sys.stderr.write('failed to fork parent process {:0}\n'.format(exc))
sys.exit(1)
def redirect_stream(source, target = None):
if target is None:
target_fd = os.open(os.devnull, os.O_RDWR)
else:
target_fd = target.fileno()
os.dup2(target_fd, source.fileno())
os.umask(0)
os.chdir('/')
fork_exit_parent()
os.setsid()
fork_exit_parent()
# redirect streams
sys.stdout.flush()
sys.stderr.flush()
redirect_stream(sys.stdin)
redirect_stream(sys.stdout)
redirect_stream(sys.stderr)
def run_import(wanted_channels, tvhsocket, fetch_radio=False, nr_days = 5):
with TVHXMLTVSocket(tvhsocket) as tvh_client:
# the Horizon API for TV channels
chmap = ChannelMap()
listings = Listings()
# add listings for each of the channels
for channel_id, channel in chmap.channel_map.items():
if channel['title'].lower() in (channel.lower() for channel in wanted_channels):
now = datetime.date.today().timetuple()
nr = 0
xmltv = XMLTVDocument()
# channel logo
icon = None
for asset in channel['images']:
if asset['assetType'] == 'station-logo-large':
icon = asset['url']
break
xmltv.addChannel(channel_id, channel['title'], icon)
for i in range(0, nr_days):
start = int((calendar.timegm(now) + 86400 * i) * 1000) # milis
end = start + (86400 * 1000)
nr = nr + listings.obtain(xmltv, channel_id, start, end)
debug('Adding {:d} programmes for channel {:s}'.format(nr, channel['title']))
# send this channel to tvh for processing
tvh_client.send(xmltv.document.toprettyxml(encoding='UTF-8'))
# Oorboekje for radio channels
if fetch_radio:
parser = OorboekjeParser()
for i in range(0, nr_days):
start = time.time() + i*86400 + 100
tvh_client.send(parser.get_day(start))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Fetches EPG data from the Horizon service and passes it to TVHeadend.')
parser.add_argument('-s', nargs='?', metavar='PATH', dest='tvhsocket', default='/home/hts/.hts/tvheadend/epggrab/xmltv.sock', type=str, help='path to TVHeadend XMLTV socket')
parser.add_argument('-p', nargs='?', metavar='PATH', dest='pid_filename', default='/var/run/horepgd.pid', type=str, help='path to PID file')
parser.add_argument('-u', nargs='?', metavar='USER', dest='as_user', default='hts', type=str, help='run as USER')
parser.add_argument('-g', nargs='?', metavar='GROUP', dest='as_group', default='video', type=str, help='run as GROUP')
parser.add_argument('-d', dest='daemonize', action='store_const', const=True, default=False, help='daemonize')
parser.add_argument('-1', dest='single_shot', action='store_const', const=True, default=False, help='Run once, then exit')
parser.add_argument('-nr', nargs='?', metavar='DAYS', dest='nr_days', default=5, type=int, help='Number of days to fetch')
parser.add_argument('-tvh', dest='tvh_host', metavar = 'HOST', default = 'localhost', help='the hostname of TVHeadend to fetch channels from')
parser.add_argument('-tvh_username', dest='tvh_username', metavar = 'USERNAME', type=str, default = '', help='the username used to login into TVHeadend')
parser.add_argument('-tvh_password', dest='tvh_password', metavar = 'PASSWORD', type=str, default = '', help='the password used to login into TVHeadend')
parser.add_argument('-R', dest='do_radio_epg', action='store_const', const=True, default=False, help='fetch EPG data for radio channels')
args = parser.parse_args()
logging.basicConfig(level=logging.DEBUG)
if(args.daemonize):
# switch user and do daemonization
try:
uid = pwd.getpwnam(args.as_user).pw_uid
gid = grp.getgrnam(args.as_group).gr_gid
except KeyError as exc:
debug('Unable to find the user {0} and group {1} for daemonization'.format(args.as_user, args.as_group))
sys.exit(1)
pid_fd = open(args.pid_filename, 'w')
switch_user(uid, gid)
# switch to syslog
logging.basicConfig(stream=logging.handlers.SysLogHandler())
daemonize()
else:
pid_fd = open(args.pid_filename, 'w')
pid = str(os.getpid())
pid_fd.write(pid + '\n')
pid_fd.close()
channels = tvh_get_channels(args.tvh_host, username=args.tvh_username, password=args.tvh_password)
debug('Fetching listings for {:d} channels'.format(len(channels)))
if args.single_shot:
run_import(channels, args.tvhsocket, args.do_radio_epg, args.nr_days)
else:
while True:
run_import(channels, args.tvhsocket, args.do_radio_epg, args.nr_days)
time.sleep(60*60*24)