Fixed some warnings.
[shell-fm.git] / scripts / lyrics.py
blob2dd5958849818f8219077ceb75527c09a3ee3448
1 #!/usr/bin/env python
4 # Copyright (C) 2009 by Silviu Grijincu <silviu.grijincu@gmail.com>.
5 # Published under the terms of the GNU General Public License (GPL).
7 # INFO
8 # lyrics.py fetches lyrics from http://lyricwiki.org/.
9 # The script is triggered by a key that is not already
10 # in use by shell-fm and must be set. (See bellow)
12 # INSTALL
13 # Save lyrics.py in the ~/.shell-fm/scripts/ directory.
14 # (if the directories do not exist please create them)
15 # To enable the plugin you must have a configuration file.
16 # 1.Create a file named shell-fm.rc in the ~/.shell-fm/ directory.
17 # 2.Put the following line in shell-fm.rc file :
18 # key0x?? = /usr/bin/python ~/.shell-fm/scripts/lyrics.py %a %t
19 # 4.Replace ?? with the ASCII hex code of the triggering key you wold like to use.
20 # for example, to use ` (backquote) as a trigger replace ?? with 60 as bellow:
21 # key0x60 = /usr/bin/python ~/.shell-fm/scripts/lyrics.py %a %t
25 from urllib2 import *
26 from sys import argv
30 class LyricSource:
31 "A lyric soruce"
32 def __init__(self, artist, title):
33 "init a Lyric source"
34 self.artist = artist
35 self.title = title
36 def get_lyrics(self):
37 "get lyrics."
38 return (False, "this is a dummy lyric source, no lyric can be found")
40 class DummyLyricSource(LyricSource):
41 def __init__(self, artist, title):
42 LyricSource.__init__(self, artist, title)
43 def get_lyrics(self):
44 return (False, "dummy error message from DummyLyricSource")
46 class LyricWiki(LyricSource):
47 def __init__(self, artist, title):
48 LyricSource.__init__(self, artist, title)
49 self.URL = 'http://lyricwiki.org/'
51 def canonical(self, str):
52 # capitalize every word after an ' ' and
53 # replace ' ' with '_'
54 return "_".join(map((lambda x : x.capitalize()), str.split(' ')))
56 def get_url(self):
57 return self.URL + self.canonical(self.artist) + ':' + self.canonical(self.title)
59 def get_html(self, url):
60 try:
61 html = urlopen(url).read()
62 return (True, html)
63 except HTTPError, e:
64 errmsg = 'The server couldn\'t fulfill the request for ' + url
65 errmsg += 'Error code: ' + str(e.code)
66 return (False, errmsg)
67 except URLError, e:
68 errmsg = 'We failed to reach the server ' + url
69 errmsg += 'Reason: ' + str(e.reason)
70 return (False, errmsg)
71 else:
72 return (False, "unexpected path reached in LyricWiki.get_html")
74 def filter_html_markers(self, html):
75 rules = ( ('<br />', '\n '),
76 ('<br>', '\n '),
77 ('&gt;', '>'),
78 ('&lt;', '<'),
79 ('&nbsp;', ' '))
80 for (x, y) in rules:
81 html = html.replace(x, y)
82 return ' ' + html
84 def parse_lyrics(self, html, url):
85 instrumental = html.find('This song is an instrumental.')
86 if instrumental <> -1:
87 return (True, 'This song is instrumental.')
89 start_marker = '<div class=\'lyricbox\' >'
90 found = html.find(start_marker)
91 if found == -1:
92 return (False, 'Lyrics not found at ' + url + '.')
94 start = found + len(start_marker)
95 end = html.find('\n', start)
96 lyrics = self.filter_html_markers(html[start:end])
97 return (True, lyrics)
99 def get_lyrics(self):
100 url = self.get_url()
101 (success, msg) = self.get_html(url)
102 if success == False:
103 return (False, msg)
104 html = msg
105 return self.parse_lyrics(html, url)
107 debug=False
109 def main(argv):
110 artist = argv[1]
111 title = argv[2]
112 # TODO: after adding a new LyricSouce class, append
113 # an object of that class here
114 lyric_sources = (LyricWiki(artist, title), DummyLyricSource(artist, title))
117 lyrics = map( (lambda x : x.get_lyrics()), lyric_sources)
119 # print the first lyrics found
120 for (success, lyric) in lyrics:
121 if success == True:
122 print lyric
123 return
125 if debug:
126 # if no lyrics found, print all error messages
127 for (success, errmsg) in lyrics:
128 print errmsg
129 else:
130 print 'Lyrics not found.'
132 if __name__ == "__main__":
133 main(argv)