Index: channels/xiph.py ================================================================== --- channels/xiph.py +++ channels/xiph.py @@ -34,10 +34,13 @@ # # → "Forbidden Fruits" extracts from dir.xiph.org HTML pages, # with homepages and listener/max infos available. Search # is also possible. # +# The bitrate filter can strip any low-quality entries, but +# retains `0` entries (which just lack meta information and +# aren't necessarily low-bitrate.) from config import * from uikit import uikit import ahttp @@ -72,19 +75,28 @@ # Switch to JSON, XML or HTML extractor def update_streams(self, cat=None, search=None): if cat: cat = cat.lower() + + # retrieval module if conf.xiph_source in ("cache", "json"): log.PROC("Xiph mode: processing api.dir.xiph.org JSON (via api.include-once.org cache)") - return self.from_json_cache(cat, search) + r = self.from_json_cache(cat, search) elif conf.xiph_source in ("xml", "buffy"): log.PROC("Xiph mode: xml.dom.minidom to traverse yp.xml") - return self.from_yp_xml(cat, search) + r = self.from_yp_xml(cat, search) else: log.PROC("Xiph mode: extract from dir.xiph.org HTML listings") - return self.from_raw_html(cat, search) + r = self.from_raw_html(cat, search) + + # filter bitrate + if conf.xiph_min_bitrate: + r = [row for row in r if row.get("bitrate", 0) <= 10 or row.get("bitrate", 0) >= int(conf.xiph_min_bitrate)] + + return r + # Retrieve partial stream list from api.include-once.org cache / JSON API wrapper # @@ -104,24 +116,22 @@ #-- extract l = [] data = json.loads(data) for e in data: #log.DATA(e) - bitrate = int(e["bitrate"]) - if conf.xiph_min_bitrate and bitrate and bitrate >= int(conf.xiph_min_bitrate): - if not len(l) or l[-1]["title"] != e["stream_name"]: - l.append({ - "title": e["stream_name"], - "url": e["listen_url"], - "format": e["type"], - "bitrate": bitrate, - "genre": e["genre"], - "playing": e["current_song"], - "listeners": 0, - "max": 0, - "homepage": (e["homepage"] if ("homepage" in e) else ""), - }) + if not len(l) or l[-1]["title"] != e["stream_name"]: + l.append({ + "title": e["stream_name"], + "url": e["listen_url"], + "format": e["type"], + "bitrate": int(e["bitrate"]), + "genre": e["genre"], + "playing": e["current_song"], + "listeners": 0, + "max": 0, + "homepage": (e["homepage"] if ("homepage" in e) else ""), + }) # send back the list return l @@ -139,25 +149,23 @@ # Get XML blob yp = ahttp.get(self.xml_url, statusmsg="Brace yourselves, still downloading the yp.xml blob.") log.DATA("returned") self.status("Yes, XML parsing isn't much faster either.", timeout=20) for entry in xml.dom.minidom.parseString(yp).getElementsByTagName("entry"): - bits = bitrate(x(entry, "bitrate")) - if bits and conf.xiph_min_bitrate and bits >= int(conf.xiph_min_bitrate): - buffy.append({ - "title": x(entry, "server_name"), - "url": x(entry, "listen_url"), - "format": self.mime_fmt(x(entry, "server_type")[6:]), - "bitrate": bits, - "channels": x(entry, "channels"), - "samplerate": x(entry, "samplerate"), - "genre": x(entry, "genre"), - "playing": x(entry, "current_song"), - "listeners": 0, - "max": 0, - "homepage": "", - }) + buffy.append({ + "title": x(entry, "server_name"), + "url": x(entry, "listen_url"), + "format": self.mime_fmt(x(entry, "server_type")[6:]), + "bitrate": bitrate(x(entry, "bitrate")), + "channels": x(entry, "channels"), + "samplerate": x(entry, "samplerate"), + "genre": x(entry, "genre"), + "playing": x(entry, "current_song"), + "listeners": 0, + "max": 0, + "homepage": "", + }) self.status("This. Is. Happening. Now.") # Filter out a single subtree l = [] if cat: @@ -215,11 +223,10 @@ .*? Tags: (.*?) .*? href="(/listen/\d+/listen.xspf)" .*? class="format"\s+title="([^"]+)" .*? /by_format/([^"]+) """, html, re.X|re.S) - print ls # Assemble for homepage, title, listeners, playing, tags, url, bits, fmt in ls: r.append(dict( genre = unhtml(tags), @@ -245,20 +252,20 @@ "schlager", ], "rock", [ "alternative", "electro", "country", "mixed", "metal", - "eclectic", "folk", "anime", "hardcore", "pure" "jrock" + "eclectic", "folk", "anime", "hardcore", "pure", "jrock" ], "dance", [ - "electronic", "deephouse", "dancefloor", "elektro" "eurodance" + "electronic", "deephouse", "dancefloor", "elektro", "eurodance", "rnb", ], "hits", [ - "russian" "hit", "star" + "russian", "hit", "star" ], "radio", [ "live", "community", "student", "internet", "webradio", ], @@ -267,11 +274,11 @@ "classical", "ebu", "vivaldi", "piano", "opera", "classix", "chopin", "renaissance", "classique", ], "talk", [ - "news", "politics", "medicine", "health" "sport", "education", + "news", "politics", "medicine", "health", "sport", "education", "entertainment", "podcast", ], "various", [ "hits", "ruhit", "mega" @@ -330,11 +337,11 @@ "france", "greek", "german", "westcoast", "bollywood", "indian", "nederlands", "europa", "italia", "brazilian", "tropical", "korea", "seychelles", "black", "japanese", "ethnic", "country", "americana", "western", "cuba", "afrique", "paris", "celtic", "ambiance", "francais", "liberte", "anglais", "arabic", - "hungary", "folklore" "latin", "dutch" "italy" + "hungary", "folklore", "latin", "dutch", "italy" ], "artist", # ARTIST NAMES [ "mozart", "beatles", "michael", "nirvana", "elvis", "britney", "abba", "madonna", "depeche", @@ -420,11 +427,11 @@ "emisora", "img", "rockabilly", "charts", [ - "best80", "70er", "80er", "60er" "chart", + "best80", "70er", "80er", "60er", "chart", ], "other", [ "varios" ],