From ba8d2c63a57873f18a84fd9a57d75622745e777e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Mazi=C3=A8re?= Date: Tue, 27 Aug 2013 17:30:56 +0200 Subject: [PATCH] RockRadio.com backend --- modules/rockradio/__init__.py | 24 +++++++ modules/rockradio/backend.py | 120 ++++++++++++++++++++++++++++++++++ modules/rockradio/favicon.png | Bin 0 -> 9252 bytes modules/rockradio/test.py | 43 ++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 modules/rockradio/__init__.py create mode 100644 modules/rockradio/backend.py create mode 100644 modules/rockradio/favicon.png create mode 100644 modules/rockradio/test.py diff --git a/modules/rockradio/__init__.py b/modules/rockradio/__init__.py new file mode 100644 index 00000000..2f71282f --- /dev/null +++ b/modules/rockradio/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Pierre Mazière +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from .backend import RockRadioBackend + + +__all__ = ['RockRadioBackend'] diff --git a/modules/rockradio/backend.py b/modules/rockradio/backend.py new file mode 100644 index 00000000..61b9c381 --- /dev/null +++ b/modules/rockradio/backend.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Pierre Mazière +# +# Based on somafm backend +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +import lxml.html +from weboob.capabilities.radio import ICapRadio, Radio, Stream, Emission +from weboob.capabilities.collection import ICapCollection +from weboob.tools.backend import BaseBackend +from weboob.tools.browser import StandardBrowser +from weboob.tools.parsers.iparser import IParser + + +__all__ = ['RockRadioBackend'] + + +class LxmlParser(IParser): + def parse(self, data, encoding=None): + return lxml.html.fromstring(data.read()) + + +class RockRadioBackend(BaseBackend, ICapRadio, ICapCollection): + NAME = 'rockradio' + MAINTAINER = u'Pierre Mazière' + EMAIL = 'pierre.maziere@gmx.com' + VERSION = '0.h' + DESCRIPTION = u'Rock Music Internet Radio' + LICENSE = 'AGPLv3+' + BROWSER = StandardBrowser + + ALLINFO = 'http://www.rockradio.com' + # FIXME + # + # MPlayer does not like the pls file sent from this site. + + def create_default_browser(self): + return self.create_browser(parser=LxmlParser()) + + def _parse_current(self, data): + current = data.split(' - ') + if len(current) == 2: + return current + else: + return (u'Unknown', u'Unknown') + + def _fetch_radio_list(self): + radios = [] + + document = self.browser.location(self.ALLINFO) + for channel in document.iter('div'): + if ("shadow"!=channel.get('class')): + continue + url=u''+channel.find('a').get('href') + radio = Radio(url[(url.rfind('/')+1):].replace('.pls','')) + radio.title = u''+channel.getprevious().text + radio.description = u"" + + current_data = u"" + current = Emission(0) + current.artist, current.title = self._parse_current(current_data) + radio.current = current + + radio.streams = [] + stream_id = 0 + stream = Stream(stream_id) + stream.title = radio.title + stream.url = url + radio.streams.append(stream) + + radios.append(radio) + + return radios + + def iter_radios_search(self, pattern): + radios = self._fetch_radio_list() + + pattern = pattern.lower() + for radio in radios: + if pattern in radio.title.lower() or pattern in radio.description.lower(): + yield radio + + def iter_resources(self, objs, split_path): + radios = self._fetch_radio_list() + + if Radio in objs: + self._restrict_level(split_path) + + for radio in radios: + yield radio + + def get_radio(self, radio_id): + radios = self._fetch_radio_list() + for radio in radios: + if radio_id == radio.id: + return radio + + def fill_radio(self, radio, fields): + if 'current' in fields: + if not radio.current: + radio.current = Emission(0) + radio.current.artist, radio.current.title = self.get_current(radio.id) + return radio + diff --git a/modules/rockradio/favicon.png b/modules/rockradio/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7273721bde356bc51a01d45eaa5e17079b577ab4 GIT binary patch literal 9252 zcmWlfbx>4aAI4WuI$RJ~8fj@nU}@n8EZyCWvPgF=-664rbV*5rbf-vnBi$_B@$Ngf zX3m^H?w$LM=lPryp`rxA#UjH3006kMGLmY@=jZ=l7--0Q=~u^9tD8i1^%xQ54KTZ?YA z<$~+aoAS0Xmw`s^U14o2O{-Z02I4;(8Ws_X5eYK&uLEtO(8vg;(W0e${Ef-DOm4f- z7X7}|8I%1c51l#Dl3yYIAVA9Kc&8t)(S}2TzNS=Y}jdZZ_>6wLMnZFAwLD zsp#?f1bn99p&ebYKCXYcs(dkqxK)biLi?{cb9ORxUI?|Dmq3x-cWp9xsM1@QKrf}I zn)^LW@)ksTP*jTKv&x;2-?SK&bJ^W@^_|{>Qj)fBw4|x3V!S8}6ZUqN^$C#>^;bJU)bWUawvKJn@<&VC{G>En1l6 zO6R4CwOAUH=Wtc#xa8t;{4c8JcA3MU<)c|YMuf73=8G7v|IKq1_jR6EEH;IzOYA6JI4OS~dt^D|u(5rV!Ocrax?O{7 zF7HSP#zhiH4&e%ThhZ6PS3G2wM)IO?Rl7#yx$5{Z#ia0oNmG{t{l++oWsD@zR&DF% zCFQ|7%da4feeDGAWf#^YICvvSrkf4B2pfGVe^q6sSE>;M#8zuLv?ek?!-zCfDe%0&x6Si_SKyx7{iJ=pI^XG1f9&`< z-&%~w_px^(QnP9lT1wTM<4BKPx`p;2Rnek-PM%%2x=@L|L&|NC%>F{se18e$IIL`k z%`mLpKTZ6nX%4&Daq_hN)E z`$3E;bEqmox`mtIsFhv>QM}HK@KMHHsP2i~KN37$XuD~&!DovxBC?XHJ8*SMSmDdX z+RN@P%;!wvxIf>R*{(*^^?tVeykuQPOoTsu7#EVoI(Ki-ylie=S@45Y!2PGySa!Mg zWU94%zI`77d7qzVa1>(#gnP%4-s|tq!sH#QpNr3s@saCOB~wKCPRLxG$ZSo1w*d4` z>^U9gwrwwlQktL->}Zd_(B`yt{#r5+qyOKcccI73w0Dfn%%G@GJBRVZ4C;1TA}?w} zpx;mwsJe!Rc6W|HatD6+YJxx^VP zQJOnj#{Ydg>ps_1H_bFg+283~WaG2RkAHqtWUZtJg=uq}fVJOQ9720+tsB1JIKzHw z@vbBeu+Rm4n&pR#!0R(6#q+HMyqn25N12?IK{OjY(Y!0|iSqKkewT@c6-LzG<62cU zr}mo%LF-oyLYB!tu3qjtgh?L~1b}I8?xf5kw6rd6h1S;ojlDSWw6_a?_795EecZO* z#q+z8$3`zI%Jb}fA#%`?+OxxDPWHE0~RZM8N90|5i3Q8r{v)sXwmTQ&05K z!M#z%U2DSMN70$OidgU4WV;p7D~9B$NQa;dU2O;4T^rkK_#MvS@1XCf69LU};3Ffz zwfj*r*!>gksz*c5fmdhI0bDfG=udSIsqyXQQHFY~E}buTUdwSH;>96~#OUkP30P0D zOB*gNV)n4}ow~iX2fOmf>BxcDy5todPG}bY>dEQKZo?o1&%g3$I7-`Nzn)K9^k|CO zE6b}+s-8@oy}1YgqT5OJs$t_TDCt7Yj~|HST8jKS%??FSsaD>mTG*Dsi00&gGO~|Gx0imZq&wpr515`ocyF zLamQ9j|l?r;Uig zgNQDyur|4wcScqI_Phz=2*V#1wu;foRZk(a*_%8?ub$RK+y!F7+Bs|c|LFvrs!`~{x*}(dLZDujwe@aULXsA6~CEBdM zAczcFxVfGJcx27GIRO2Er8nVV6_r9ZO|+h>ZhGP$G2zl9lfNL6T7zmqH*%`Xk%0k9 zV~%${qWpH-TTLH9U@d;>U%$3>u%n#0<3#6aWN}KJ#y}>mH-?%S7&?TV&}Jg_KWt9{ z*3cG{2E&>r^^Yv@w32z6j}_IX)mTTal$mz>8XsbS2{P9uEJDYVo|T26f!$ppNefy& z)F@(1=!;RJwMLKWw^;n-a7+xlS2^M(cmaMhSJhK&F0tUC}SnD5nGiDF1 z((O~Q)pUX=kQk&F8uhp7+h}F!zC~!vHaJ~3+ZlWuh=Ew$_9n8AW>o+OLWOTA^c1SJ z81c=^Rm$~3>Bf{={`G9X8vQV$*W331Er?jC95p%N29&aq(OIQ>FJ=-*?zzb)S6p}N zQmnPkL<{(q%GEpV4y}gO6mAlghSKw+ay|? zqg%fWKG1Qwgy;$j#Hs_`!^fg( z(^>Dh?N|Nnj%~L>RpTRMoeB+iDWS(q;wW(VLB>*&!}9+Kv<#)^n}!0>iOrWcx6=s#<-uW{1HInYV-}rr*F=qhE`+(@ZP% z&%4XMQ8lj#?9N2wgv;>OzM|`gTV!u`+}VY}uFxCizok$Jem__C+XdfbmYUh->=&wE zH^;7aCiY9HdL{I7&D7N`y_vJe0lSw9HeI)w`hR4gm8PGb-JZ#?TgxXi11$*gW@cmC zg83vWwI`2-q(dO|{^_JaE7x{^xZM3Rj=9i2n$yJQXvKt^2i;WFBwvt>*`Kv_tZs0^ z>PAN3{^t+;JOmCo%t>tZ83MZN(-ByX7R7UP9I*K!X5J(v@5)#H-&9n_n z0jj`Nn)~bL^-O;g0hdnq^1G*~!DyQw_Xdc%JVCKZ6U_f2Qd`W5&^5lEF#yk^N1IkUsiqF-)aa6Hv`Z$7r5utWTyHBBb*{xcZVPNv>KfJv zu6Byk0KpU|a-&K0R9RLk$PrZZ5vHbmKUMiZ9RkCM)uVA)<;`*vR&VS=bFwQMoy&*V^2|W|lrRHQem=7#dSEG0RBB5Q`;n{sA|*r=i|y1r zPVwyYPOv9;wK1ed3#y;t7v=Zq4R||B8^6tjC3nh(SJa2O- z3r`n#RleeyU41uCysn~JifnUxU^x5~AhrJ$0SBS#3-wt5Wz9Sv*FQXOMhO*P%M$e9 z!zLN2J^9?RHgr-mV?8gse#X$MY8r?0T<_&7C{g^;XC)IQ8X%pT@X!1k2N$jNj+z-Y2f_(xE z)ShUl%58T0*A$$sHTiAr>Y7&=_nm2_tL}MuF+aAEX`47uQ#}rh?dMS*8{8G;rc&1Og67u=60L#bhz$KHb{6VU6J$*Q0)5j#GMVbUKSp-*)CteMGuI*y9_a8*h1 z&zjmLg0N>jh!j42ddBo~?}iei?k6pB`U1}Y6o0?m+A7mspO2L7?}l>dO9>$S#P1{! zu?Wi@Vrpe#mB)Qt#!!9tU0ZX&gJ!dPOI#P_X^zo~1U`0j)TnIuTqV{q$9{v%-QT;` zn{tH&>;-A{#XF;SFGhmiFNr0ZC(Z;f`2B;snhg8+6v(vh8jokpZJ#S8Ms$Ia71?g%kcK3tYsn(7CE=Drf{}8G>PnBwim8;LTS9GNBz@g?p{U9{TQCW~v|G{GAxm zd)}E_E+ATN(wQv*ci=hib3+L;?-g)M&_l!Qn6SE4UK3l-z%qV z#Y6nY^laZ1X8XbFU4Euljee{z=lh9*`Z4`Zq0A4%kdxVhPp2qXk?uI<>jeDCrUvV z#Uyx?qB_1@5e(QwbeGqJ91g}S5p?>5xeu6+CQ0q;s~A8sYG zF%hNMemP9R6syJ6uR-*LBF85}r0ZW;CgS&dI$sROo ztvY#n$W!eupT|QRo(%KX(KlA4y6fFdg4y0)p$}uzfy7@zu3{edkq+}=yx&bcAzZ|b zd2{&BLAS{sRq;%oO}QDeAGV$zaI8I^kfkJhAr-qA`Nfg-&h5dP{=fP7U+W^fmqF?g z8Et|n;bbuw<~U2o33F?Un*&I{iWK=h!k=iL+L>a5sXHdEQic2w4RNvz8Uc%b$3y`n z#?Xt(=N0x@K50+@nA_((f|z7`dw(!O~c zAB_}2FMH&W)J&z%!8aT?wJ*o`S~c3M%TqRedzDWct&gMjlxZZU&1~V$hj(4_LXQt( z`kQwo4Nab`*%_->BY`E-z1py^xvRg@)isFq9b73phsSy)i6

*2o;6X8pUy6ARt) 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 DOxav% literal 0 HcmV?d00001 diff --git a/modules/rockradio/test.py b/modules/rockradio/test.py new file mode 100644 index 00000000..361f5a6b --- /dev/null +++ b/modules/rockradio/test.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Pierre Mazière +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.tools.test import BackendTest +from weboob.capabilities.radio import Radio + + +class RockRadioTest(BackendTest): + BACKEND = 'rockradio' + + def test_rockradio(self): + ls = list(self.backend.iter_resources((Radio, ), [])) + self.assertTrue(len(ls) > 0) + + search = list(self.backend.iter_radios_search('classic')) + self.assertTrue(len(search) > 0) + self.assertTrue(len(search) < len(ls)) + + radio = self.backend.get_radio('classicrock') + self.assertTrue(radio.title) + self.assertFalse(radio.description) + self.assertTrue(radio.current.title) + self.assertTrue(radio.current.artist) + self.assertTrue(radio.streams[0].url) + self.assertTrue(radio.streams[0].title) +