ADDED contrib/rcast.py Index: contrib/rcast.py ================================================================== --- contrib/rcast.py +++ contrib/rcast.py @@ -0,0 +1,100 @@ +# api: streamtuner2 +# title: RCast +# description: Streaming server provider and station directory +# type: channel +# category: radio +# version: 0.2 +# url: http://www.rcast.net/dir +# png: +# iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABH0lEQVR42mPgZWXkNxdhsScH87Iw8DOAGHcDBf6Tg02FmW1RDPj97cvf/0BwJ4D/HyHNGAbc9uUBawaBf0BASDOGASBNIM1fHt34BaKRFd4CGg4C +# eA0Agd9fPv255c39F90AXC6DG3ArSOwP1O9wDTc92cA23gqR/g3i3yvz/IFuMNgAeyBANx0Enk7M+Qlig5wO0wgCt1yZwepuBQj8sQUCsAG/3r74g+7k318//oWxYYaDwM/3r//A2GADsKUDGICxH7XG/wK75s8f +# cEB/vnwU7C2MdADDn2+d+4VsADCKIc72ZPsHM/zvn99/cRpw050Z7O+nvVkYUfpmx4KfMDGcBiB7A90AZIzXgJ9vX4D9eceP9x9ZBhCDwQZQmp0BVv4354bQNGwAAAAASUVORK5CYII= +# priority: extra +# extraction-method: regex +# +# RCast.net is a provider for streaming servers, that also features +# a tidy and detailed station directory. It currently hosts/lists +# around 7700 individual stations. +# +# It lists direct streaming server addresses, homepages, currently +# playing songs, bitrate etc. It's also pretty quick, but only +# returns 10 results per page. Categories have to be collected +# manually though. + + +import re +import ahttp +from config import * +from channels import * + + +# rcast.net +class rcast (ChannelPlugin): + + # settings/data + catmap = {} + categories = ["top", "pop", "dance", "holiday", "jazz", "rock", "variety", "regional", "romanian", "disco", "chillout", "and", "urban", "mixed", "various", "hip", "hop", "trance", "rap", "techno", "house", "60s", "70s", "80s", "90s", "alternative", "blues", "comedy", "folk", "funk", "indie", "jungle", "amp", "oldies", "sports", "news", "fusion", "top40", "charts", "nederlandstalig", "soft", "radio", "station", "ostuni", "edm", "freestyle", "hard", "country", "metal", "all", "musicworld", "music", "zouk", "salsa", "world", "italy", "electronic", "happy", "international", "contemporary", "misc", "reggae", "talk", "latin", "turkish", "turkce", "slow", "italian", "talkshow", "electro", "dubstep", "40pop", "adult", "soul", "rnb", "1960", "1970", "1980", "1990", "2000", "2010", "more", "lounge", "eas", "decades", "hits", "new", "first", "club", "eurodance", "dancehall", "compas", "classic", "energy", "tribal", "brasil", "clubbing", "rave", "punk", "psytrance", "punkrock", "progressive", "ambient", "drum", "bass", "chill", "handsup", "hardstyle", "manele", "petrecere", "minimal", "electronica", "garage", "speak", "futbol", "europe", "themed", "seasonal", "holidays", "smooth", "christmas", "xmas", "genres", "navidad", "festive", "weihnachten", "christian", "swing", "trip", "acoustic", "underground", "deep", "downtempo", "soulful", "real", "hiphop", "rare", "groove", "other", "afro", "central", "northern", "motown", "classique", "prog", "remixes", "spanish", "age", "soundtracks", "soca", "ska", "disckofox", "schlager", "rockabilly", "roll", "electr", "nica", "classical", "easy", "listening", "bachata", "banda", "cumbia", "mariachi", "merengue", "ranchera", "reggaeton", "mexican", "none", "party", "discofox", "volksmusik", "piraten", "80er", "90er", "european", "deutsch", "fox", "dream", "religious", "discourse", "prayers", "portuguese", "celtic", "surf", "klavier", "piano", "improvisation", "brown", "noise", "psychill", "african", "tamil", "soundtrack", "japanese", "meditation", "40s", "big", "band", "old", "time", "neo", "love", "romance", "gangsta", "naija", "school", "urbano", "wave", "eclectic", "italia", "community", "video", "greece", "athens", "greek", "hardcore", "neurofunk", "public", "gospel", "inspiration", "turntablism", "acid", "dnb", "dutch", "future", "breakbeat", "trap", "freak", "classics", "funky", "west", "coast", "texas", "east", "experimental", "mixtapes", "dub", "tech", "entertainment", "tekno", "hardtekno", "break", "kizomba", "kuduro", "tejano", "oldskool", "metalcore", "south", "africa", "modern", "goth", "mento", "calypso", "post", "art", "kraut", "grunge", "hair", "heavy", "power", "best", "gothic", "darkwave", "ebm", "industrial", "college", "choral", "impressionist", "opera", "symphony", "orchestral", "inspirational", "cool", "xtreme", "extreme", "electric", "indigenous", "rhythm", "doo", "wop", "jump", "ballads", "50s", "cover", "listen", "bits", "laugh", "thm", "zeybekler", "worldbeat", "elettronica", "turbo", "mix", "western", "americana", "hindi", "irish", "varied", "goud", "van", "oud", "neder", "tangos", "folklore", "latinos", "recuerdos", "nacionales", "internacionales", "cuartetos", "cumbias", "tropical", "etc", "spiritual", "tehno", "comercial", "romania", "info", "artists", "british", "style", "hit", "latino", "etno", "pre", "populara", "espa", "raggaeton", "mixtape", "variadades", "portugues", "italiana", "educational", "compa", "sega", "kompa", "retro", "rumba", "ndombolo", "ngwasuma", "congolais", "soukouss", "coupe", "cale", "black", "rhythmc", "sport", "our", "passion", "romantic", "everything", "between", "the", "one", "channel", "bootlegs", "128k", "ghana", "acidjazz", "caribbean", "jewish", "indian", "brandnew2016"] + titles = dict(listeners=False) + has_search = True + listformat = "srv" + base = "http://www.rcast.net/dir" + + + # use a static list for now + def update_categories(self): + self.categories = self.categories + + # get streems + def update_streams(self, cat, search=None, max_pages=10): + r = [] + + # fetch + html = "" + if search: # pretty much identical (except first page should be /dir/?action=search and POST field) + cat = search + max_pages = 1 + for i in range(1, max_pages + 1): + html += ahttp.get("%s/%s/page%s" % (self.base, cat, i)) + if not re.search('href="/dir/%s/page%s">Next' % (cat, i + 1), html): + break + + # extract + ls = re.findall(""" + .*? + .*? + ([^<>]+) .*? + ([^<>]*) .*? + ]+>([^<>]*) .*? + Genre:(.+?) .*? + \s*(\d+)\s*Kbps
\s*(audio/[\w.-]+) + """, html, re.X|re.S) + #log.DATA(re.findall("()", html)) + + # blocks + for row in ls: + try: + log.UI(row) + r.append(dict( + id = row[0], + url = row[1], + title = unhtml(row[2]), + playing = unhtml(row[3]), + homepage = unhtml(row[4]), + genre = unhtml(row[5]), + bitrate = to_int(row[6]), + format = row[7], + #listeners = to_int(listeners[5]) + )) + except: + pass #some field missing + + # done + return r + + # (disabled): collect genres + for row in r: + for c in re.findall("(\w+)", row["genre"]): + if c not in self.categories: + self.categories.append(c) + +