oe1archive: Fix version
[shutils.git] / oe1archive.py
1 #!/usr/bin/env python3
2 """A simple tool to query the Ö1 7 Tage archive."""
3
4 __version__ = "1.0"
5 __author__ = "Stefan Huber"
6
7
8 import urllib.request
9 import simplejson
10 import dateutil.parser
11 import sys
12 import getopt
13 import re
14
15
16 class Archive:
17
18 def __init__(self):
19 self.json = read_json("http://audioapi.orf.at/oe1/json/2.0/broadcasts/")
20
21 def get_days(self):
22 return map(_json_to_day, self.json)
23
24 def get_broadcasts(self, day):
25 bjson = self.json[day]['broadcasts']
26 return map(_json_to_broadcast, bjson)
27
28 def get_broadcast(self, day, broadcast):
29 return _json_to_broadcast(self.json[day]['broadcasts'][broadcast])
30
31 def get_broadcast_subtitle(self, day, broadcast):
32 return self.json[day]['broadcasts'][broadcast]['subtitle']
33
34 def get_broadcast_url(self, day, broadcast):
35 date = self.json[day]['day']
36 pk = self.json[day]['broadcasts'][broadcast]['programKey']
37
38 burl = 'https://audioapi.orf.at/oe1/api/json/current/broadcast/%s/%d'
39 bjson = read_json(burl % (pk, date))
40
41 sjson = bjson['streams']
42 if len(sjson) == 0:
43 return None
44
45 sid = sjson[0]['loopStreamId']
46 surl = 'http://loopstream01.apa.at/?channel=oe1&shoutcast=0&id=%s'
47 return surl % sid
48
49 def get_broadcasts_by_regex(self, key):
50 rex = re.compile(key, re.IGNORECASE)
51
52 res = []
53 for d, djson in enumerate(self.json):
54 for b, bjson in enumerate(djson['broadcasts']):
55 if rex.search(bjson['title']) is not None:
56 res.append((d, b))
57 elif bjson['subtitle'] is not None and rex.search(bjson['subtitle']) is not None:
58 res.append((d, b))
59 return res
60
61 def _json_to_day(djson):
62 return dateutil.parser.parse(djson['dateISO'])
63
64 def _json_to_broadcast(bjson):
65 dt = dateutil.parser.parse(bjson['startISO'])
66 return (dt, bjson['title'])
67
68
69 def read_json(url):
70 with urllib.request.urlopen(url) as f:
71 dec = simplejson.JSONDecoder()
72 return dec.decode(f.read())
73
74 def input_index(prompt, li):
75 while True:
76 try:
77 idx = int(input(prompt))
78 if idx < 0 or idx >= len(li):
79 print("Out out range!")
80 else:
81 return idx
82
83 except ValueError:
84 print("Unknown input.")
85 except EOFError:
86 sys.exit(1)
87
88 def screen_help():
89 print("""Usage:
90 {0} -h, --help
91 {0} -c, --choose
92 {0} -s, --search TITLE""".format(sys.argv[0]))
93
94 def screen_choose():
95 a = Archive()
96
97 print("Choose a date:")
98 days = list(a.get_days())
99 for i, date in enumerate(days):
100 print(" [%d] %s" % (i, date.strftime("%a %d. %b %Y")))
101 day = input_index("Date: ", days)
102 print()
103
104 print("Choose a broadcast:")
105 broadcasts = list(a.get_broadcasts(day))
106 for i, b in enumerate(broadcasts):
107 date, title = b
108 print(" [%2d] %s %s" % (i, date.strftime("%H:%M:%S"), title))
109 broadcast = input_index("Broadcast: ", broadcasts)
110 print()
111
112 url = a.get_broadcast_url(day, broadcast)
113 if url is None:
114 print("No stream found.")
115 sys.exit(1)
116 print(url)
117
118 def screen_search(key):
119 a = Archive()
120
121 for d, b in a.get_broadcasts_by_regex(key):
122 date, title = a.get_broadcast(d, b)
123 print("%s %s" % (date.strftime("%a %d.%m.%Y %H:%M:%S"), title))
124 print(" %s" % a.get_broadcast_url(d, b))
125 print()
126
127 if __name__ == "__main__":
128
129 try:
130 opts, args = getopt.getopt(sys.argv[1:], "hcs:",
131 ["help", "choose", "search="])
132 except getopt.GetoptError as err:
133 print(err)
134 screen_help()
135 sys.exit(2)
136
137 for o, a in opts:
138 if o in ["-h", "--help"]:
139 screen_help()
140 if o in ["-c", "--choose"]:
141 screen_choose()
142 if o in ["-s", "--search"]:
143 screen_search(a)