Breaking newz! - Shoutcast in XBMC újra!

Sokat nem keresgéltem, nálam alapból nem megy fel XBMC alá a Shoutcast add-on, mert broken-ként van jelölve. Oka: API változás Shoutcast-éknál. Annyit olvastam, hogy valószínűleg nem egészen az API változott, csak tiltják az XBMC user-agent-et. Nosza, utánanéztem. Már az add-on beszerzése is gond volt, tekintve, hogy az alkalmazásból nem tölthető le, így más úton indultam.
A legújabb 1.1.1-es verzió 10.0-ás Dharma XBMC-hez: itt

Mivel ezek Python-ban vannak írva, először rendesen vakartam a fejem, de kb. 2 óra alatt, aktív Python dokumentáció olvasás mellett sikerült egy workaroundot összehakkolnom így is. A lényeg: az

urllib.Request(BASE_URL)

függvényhívás készíti el a shoutcast.com-ra küldendő HTTP kérést, ami így ebben a formában nem fog eredményt visszaadni a


  response = urllib2.urlopen(req)
  link=response.read()

hívások után. És (-sel nem kezdünk mondatot.) itt igazolódik, hogy a túloldalon van valami turpisság. Nosza, doksi. Azt írja, hogy:

class urllib2.Request(url[, data][, headers][, origin_req_host][, unverifiable])
This class is an abstraction of a URL request.

url should be a string containing a valid URL.

data may be a string specifying additional data to send to the server, or None if no such data is needed. Currently HTTP requests are the only ones that use data; the HTTP request will be a POST instead of a GET when the data parameter is provided. data should be a buffer in the standard application/x-www-form-urlencoded format. The urllib.urlencode() function takes a mapping or sequence of 2-tuples and returns a string in this format.

headers should be a dictionary, and will be treated as if add_header() was called with each key and value as arguments. This is often used to “spoof” the User-Agent header, which is used by a browser to identify itself – some HTTP servers only allow requests coming from common browsers as opposed to scripts. For example, Mozilla Firefox may identify itself as "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11", while urllib2‘s default user agent string is "Python-urllib/2.6" (on Python 2.6).

Ahha! Szóval lehet header információkat passzolni. Miután kiderítettem, hogy mi az a Dictionary Pythonban (bocsánat a Python fan-ektől, de életemben nem programoztam benne :), bevezettem egy új globális változót:


FAKEHEADER = {'User-Agent': "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.98 Safari/534.13"}

retreived via http://www.useragentstring.com/

Nosza próba! Persze nem ment. HINT:a mindenféle add-onok forrásaiban lévő log() fv. csak debug módban ír bármit is az xbmc.log-ba, helyette használjuk az xbmc.log() függvényt.
Aztat írta, hogy márpedig a Request() első paramétere string kell legyen, nem dictionary. Oké. Újra doksi. Hülyegyerek benézte a paraméterezést, mert az URL után meg lehet adni egy DATA paramétert, ami márpedig valóban string kell legyen. Kis typofix az alábbira:

req = urllib2.Request(BASE_URL, '', FAKEHEADER)

Próba... ÉS MEEEEEEEEGY!!!!!

zsírkarajszaft.

Most megyek apósomhoz ebédre, a javított default.py-t kitettem a HUP Pastebin-re GNU GPL, ahogy volt. Használathoz először be kell szerezni a régi 1.1.1-es Shoutcast add-ont, majd ~/.xbmc/addons.plugin.shoutcast/default.py tartalmát felülírni az én kódommal. Windows alatt csináltam, úgyhogy nem tudom pontosan, hogy !Win rendszereken merre vannak ezek a cuccok, csak hasraütöttem.

Használjátok egészséggel az újrafeltalált melegvizet!

P.S. Ja, tesztelve csak addig volt, amíg elindult az első random választott shoutcast állomás, szóval előfordulhatnak bugok, ha igény van, hozzászólásban jelezve javítom őket (amit tudok).

Hozzászólások

Új ficsúr.

Mivel előfordulhat, hogy az adott agent-et is előbb-utóbb bannolják, csináltam egy trükköt. :)

A http://www.user-agents.org/ oldalon van egy szép nagy XML formában is kitolt user agent gyűjtemény. Ezt lehúzva, majd a listáról minden esetben új agent-et beállítva tovább csökkenthetjük a "lebukás" veszélyét. :)

Egyébként nem értem, miért kellett bannolni az XBMC-t, hiszen maximum 3 lekérdezésből (genrelista letöltés, genre-n belüli adók listájának letöltése, konkrét adó lekérése) elindítható egy adó...

Az új kód:


import random

def MKFAKEHDR():
  xbmc.log("MKFAKEHDR() called")
  req = urllib2.Request('http://www.user-agents.org/allagents.xml');
  response = urllib2.urlopen(req)
  link=response.read()
  response.close()
  dom = xml.dom.minidom.parseString(link)
  useragents = dom.getElementsByTagName('user-agent')
  for useragent in useragents:
    dictofagents[useragent.getElementsByTagName("ID")[0].firstChild.data]=useragent.getElementsByTagName("String")[0].firstChild.data
  retval = {'User-Agent': dictofagents[random.choice(dictofagents.keys())]} 
  return retval

Majd minden helyen a


urllib2.Request(BASE_URL, '', FAKEHEADER)

javítása a következőre:


urllib2.Request(BASE_URL, '', MKFAKEHDR())

Céges tűzfal nem enged ki, úgyhogy próba majd csak otthonról... :D

SZERK:ez így f0sch, 10-ből 9 user agent-tel nem megy + a unicode konverziók elmaradtak...

--
A gyors gondolat többet ér, mint a gyors mozdulat.