1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | # encoding: UTF-8
# api: streamtuner2
# title: Xiph.org
# description: ICEcast radios. Scans per JSON API, slow XML, or raw directory.
# type: channel
# url: http://dir.xiph.org/
# version: 0.7
# category: radio
# config:
# { name: xiph_source, value: buffy, type: select, select: "cache=JSON cache srv|xml=Clunky XML blob|buffy=Buffy YP.XML|web=Forbidden fruits", description: "Source for station list extraction." }
# priority: standard
# png:
# iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAg5JREFUOI2lk1tIE2AUx3+7CG1tlmlG1rSEHrKgEUF7yO40taQiRj10I4qKkOaT4hIUItuTkC8hpJAQtJCICrFpzEKw
# h61eQorGNBOTzbEt16ZrnR5Wq3mZD/3heziX//983znngyyov+eSbHEA5WKBhs4BKVy9gsqajqwiCwo0dA5IQX5u2s4moliMPPV1nCeDzxgNBFDHE2wsKMPzsGVefobjcnO7RMfeMuL341ZBrNEGRmPqqjdvsbbf
# w7irO4Oj+rdywNNNucmERsLUVndR8uYRU13PCew6hpgP8W02xMpIsik++qk5oweW6y3yob8WnXacZDKJWh1Cp4OtRUHsh19TUlUGViv09RGqKAenU5QnLKm+rK88LjgcUnxmr/h8iNO5XYJBRAQZ/qiVeptGWjty
# 5cClDWLwugQRIRiU5UdPCoD6S89jhV6pks9WG6fuwtBtF5v72vC1v+B86SsM+jD56hjnyiM0lRrAbofeXjQJLdE/78jbXSU5166I6f5VeeDdKdq6GtlSd0QkVU+8XsQhlt9W6izbZ5aMKWgtp2WT/yUHd0xSYU7i
# dsPQ+1WMKIsJD08wEV2HGLeRyNMjawqRxhuKBfdgz1m7fI/4mVX+ZGxmgniOoJv+QZHGAMC7p60ZnHkC8HfzZmLTBCd9af9ccnqMc9HTdmFe4kLkJbH/4h0xVtcu+SP/C78AL6btab6woPcAAAAASUVORK5CYII= |
|
>
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | # encoding: UTF-8
# api: streamtuner2
# title: Xiph.org
# description: ICEcast radios. Scans per JSON API, slow XML, or raw directory.
# type: channel
# url: http://dir.xiph.org/
# version: 0.8
# category: radio
# config:
# { name: xiph_source, value: buffy, type: select, select: "cache=JSON cache srv|xml=Clunky XML blob|buffy=Buffy YP.XML|web=Forbidden fruits", description: "Source for station list extraction." }
# { name: xiph_filter, value: 1, type: bool, description: "Filter duplicate stations from list." }
# priority: standard
# png:
# iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAg5JREFUOI2lk1tIE2AUx3+7CG1tlmlG1rSEHrKgEUF7yO40taQiRj10I4qKkOaT4hIUItuTkC8hpJAQtJCICrFpzEKw
# h61eQorGNBOTzbEt16ZrnR5Wq3mZD/3heziX//983znngyyov+eSbHEA5WKBhs4BKVy9gsqajqwiCwo0dA5IQX5u2s4moliMPPV1nCeDzxgNBFDHE2wsKMPzsGVefobjcnO7RMfeMuL341ZBrNEGRmPqqjdvsbbf
# w7irO4Oj+rdywNNNucmERsLUVndR8uYRU13PCew6hpgP8W02xMpIsik++qk5oweW6y3yob8WnXacZDKJWh1Cp4OtRUHsh19TUlUGViv09RGqKAenU5QnLKm+rK88LjgcUnxmr/h8iNO5XYJBRAQZ/qiVeptGWjty
# 5cClDWLwugQRIRiU5UdPCoD6S89jhV6pks9WG6fuwtBtF5v72vC1v+B86SsM+jD56hjnyiM0lRrAbofeXjQJLdE/78jbXSU5166I6f5VeeDdKdq6GtlSd0QkVU+8XsQhlt9W6izbZ5aMKWgtp2WT/yUHd0xSYU7i
# dsPQ+1WMKIsJD08wEV2HGLeRyNMjawqRxhuKBfdgz1m7fI/4mVX+ZGxmgniOoJv+QZHGAMC7p60ZnHkC8HfzZmLTBCd9af9ccnqMc9HTdmFe4kLkJbH/4h0xVtcu+SP/C78AL6btab6woPcAAAAASUVORK5CYII= |
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 | # uncover station homepages.
#@use_rx
def from_raw_html(self, cat, search=None, use_rx=False):
# Build request URL
by_format = {t.lower(): t for t in self.categories[-1]}
if search:
url = "http://dir.xiph.org/search?search={}".format(search)
cat = "search"
elif by_format.get(cat):
url = "http://dir.xiph.org/codecs/{}".format(by_format[cat].title())
elif cat:
url = "http://dir.xiph.org/genres/{}".format(cat.title())
# Collect all result pages
html = ahttp.get(url)
for i in range(1,5):
m = re.search('href="[?]cursor=(\w+)">Next</a>', html)
if not m:
break
self.status(i/5.1)
html += ahttp.get(url, {"cursor": m.group(1)})
try:
html = html.encode("raw_unicode_escape").decode("utf-8") |
|
|
| 186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 | # uncover station homepages.
#@use_rx
def from_raw_html(self, cat, search=None, use_rx=False):
# Build request URL
by_format = {t.lower(): t for t in self.categories[-1]}
if search:
url = "http://dir.xiph.org/search?q={}".format(search)
cat = "search"
elif by_format.get(cat):
url = "http://dir.xiph.org/codecs/{}".format(by_format[cat].title())
elif cat:
url = "http://dir.xiph.org/genres/{}".format(cat.title())
# Collect all result pages
html = ahttp.get(url)
for i in range(1,9):
m = re.search('href="[?]cursor=(\w+)">Next</a>', html)
if not m:
break
self.status(i/5.1)
html += ahttp.get(url, {"cursor": m.group(1)})
try:
html = html.encode("raw_unicode_escape").decode("utf-8") |
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254 | listformat = "srv",
listeners = to_int(ls["listeners"]),
bitrate = 0, #bitrate(ls["bits"]),
format = mime_fmt(guess_format(ls["fmt"])),
tags = unhtml(ls["tags"])
))
#log.DATA(r)
return r
# Regex dict
def rx_all(self, fields, src, flags=re.X):
row = {}
for k, v in fields.items():
m = re.search(v, src, flags)
if m: |
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
| 241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 | listformat = "srv",
listeners = to_int(ls["listeners"]),
bitrate = 0, #bitrate(ls["bits"]),
format = mime_fmt(guess_format(ls["fmt"])),
tags = unhtml(ls["tags"])
))
#log.DATA(r)
return self.filter_duplicates(r)
# strip entries by title+playing from Xiph BETA result list
def filter_duplicates(self, entries):
if "xiph_filter" not in conf or not int(conf.xiph_filter):
return entries
seen = []
filt_r = filter(lambda row: row["title"] not in seen and not seen.append(row["title"]), entries)
return filt_r
for row in entries:
curr = (row["title"], row["playing"])
if not curr in seen:
filt_r.append(row)
seen.append(curr)
return filt_r
# Regex dict
def rx_all(self, fields, src, flags=re.X):
row = {}
for k, v in fields.items():
m = re.search(v, src, flags)
if m: |