File: lyrics.py

package info (click to toggle)
shell-fm 0.7%2Bgit20100414-1
  • links: PTS
  • area: main
  • in suites: squeeze, wheezy
  • size: 444 kB
  • ctags: 305
  • sloc: ansic: 4,422; makefile: 135; python: 80; haskell: 76; sh: 67; perl: 19
file content (134 lines) | stat: -rwxr-xr-x 3,782 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python


# Copyright (C) 2009 by Silviu Grijincu <silviu.grijincu@gmail.com>.
# Published under the terms of the GNU General Public License (GPL).

# INFO
# lyrics.py fetches lyrics from http://lyricwiki.org/. 
# The script is triggered by a key that is not already 
# in use by shell-fm and must be set. (See bellow)

# INSTALL
#	Save lyrics.py in the ~/.shell-fm/scripts/ directory.
#	(if the directories do not exist please create them)
#   To enable the plugin you must have a configuration file.
#	1.Create a file named shell-fm.rc in the ~/.shell-fm/ directory.
#	2.Put the following line in shell-fm.rc file :
#		key0x?? = /usr/bin/python ~/.shell-fm/scripts/lyrics.py %a %t
#	4.Replace ?? with the ASCII hex code of the triggering key you wold like to use.
#		for example, to use ` (backquote) as a trigger replace ?? with 60 as bellow:
#		key0x60 = /usr/bin/python ~/.shell-fm/scripts/lyrics.py %a %t



from urllib2 import *
from sys import argv



class LyricSource:
	"A lyric soruce"
	def __init__(self, artist, title):
		"init a Lyric source"
		self.artist = artist
		self.title  = title
	def get_lyrics(self):
		"get lyrics."
		return (False, "this is a dummy lyric source, no lyric can be found")

class DummyLyricSource(LyricSource):
	def __init__(self, artist, title):
		LyricSource.__init__(self, artist, title)
	def get_lyrics(self):
		return (False, "dummy error message from DummyLyricSource")

class LyricWiki(LyricSource): 
	def __init__(self, artist, title):
		LyricSource.__init__(self, artist, title)
		self.URL = 'http://lyricwiki.org/'
	
	def canonical(self, str):
		# capitalize every word after an ' ' and
		# replace ' ' with '_'
		return "_".join(map((lambda x : x.capitalize()), str.split(' ')))

	def get_url(self):
		return self.URL + self.canonical(self.artist) + ':' + self.canonical(self.title)

	def get_html(self, url):
		try:
			html = urlopen(url).read()
			return (True, html)
		except HTTPError, e:
			errmsg = 'The server couldn\'t fulfill the request for ' + url
			errmsg += 'Error code: ' + str(e.code)
			return (False, errmsg)
		except URLError, e:
			errmsg = 'We failed to reach the server ' + url
			errmsg += 'Reason: ' + str(e.reason)
			return (False, errmsg)
		else:
			return (False, "unexpected path reached in LyricWiki.get_html")

	def filter_html_markers(self, html):
		rules = ( ('<br />', '\n  '),
				  ('<br>', '\n  '),
				  ('&gt;', '>'),
				  ('&lt;', '<'),
				  ('&nbsp;', ' '))
		for (x, y) in rules:
			html = html.replace(x, y)
		return '  ' + html

	def parse_lyrics(self, html, url):
		instrumental = html.find('This song is an instrumental.')
		if instrumental <> -1:
			return (True, 'This song is instrumental.')

		start_marker = '<div class=\'lyricbox\' >'
		found = html.find(start_marker)
		if found == -1:
			return (False, 'Lyrics not found at ' + url + '.')
		
		start = found + len(start_marker)
		end = html.find('\n', start)
		lyrics = self.filter_html_markers(html[start:end])
		return (True, lyrics)

	def get_lyrics(self):
		url = self.get_url()
		(success, msg) = self.get_html(url)
		if success == False:
			return (False, msg)
		html = msg
		return self.parse_lyrics(html, url)

debug=False

def main(argv):
	artist = argv[1]
	title  = argv[2]
	# TODO: after adding a new LyricSouce class, append 
	# an object of that class here
	lyric_sources = (LyricWiki(artist, title), DummyLyricSource(artist, title))


	lyrics = map( (lambda x : x.get_lyrics()), lyric_sources)
	
	# print the first lyrics found
	for (success, lyric) in lyrics:
		if success == True:
			print lyric
			return
	
	if debug:
		# if no lyrics found, print all error messages
		for (success, errmsg) in lyrics:
			print errmsg
	else:
		print 'Lyrics not found.'

if __name__ == "__main__":
	main(argv)