]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/env ruby -w | |
2 | ||
3 | require 'rubygems' | |
4 | require 'uri' | |
5 | require 'net/http' | |
6 | require 'multi_json' | |
7 | require 'nokogiri' | |
8 | require 'open-uri' | |
9 | ||
10 | # This shit causes a lot of warnings. Quick Hack. | |
11 | original_verbosity = $VERBOSE | |
12 | $VERBOSE = nil | |
13 | require 'rdio' | |
14 | $VERBOSE = original_verbosity | |
15 | ||
16 | class Lyricli | |
17 | ||
18 | def initialize | |
19 | @artist = ARGV[0] | |
20 | @song = ARGV[1] | |
21 | ||
22 | @rdio_key = "sddac5t8akqrzh5b6kg53jfm" | |
23 | @rdio_secret = "PRcB8TggFr" | |
24 | @token_path = File.expand_path("~/.rdio_token") | |
25 | ||
26 | #Expand the symlink and get the path | |
27 | if File.symlink?(__FILE__) then | |
28 | path = File.dirname(File.readlink(__FILE__)) | |
29 | else | |
30 | path = File.dirname(__FILE__) | |
31 | end | |
32 | ||
33 | # Get the current rdio track | |
34 | @rdio = init_rdio | |
35 | rdio_track | |
36 | ||
37 | #Get the current iTunes track | |
38 | current = `osascript #{path}/current_song.scpt` | |
39 | if current and not current.empty? then | |
40 | current = current.split("<-SEP->") | |
41 | @artist ||= current[0] | |
42 | @song ||= current[1] | |
43 | end | |
44 | end | |
45 | ||
46 | def init_rdio | |
47 | ||
48 | if File.exists?(@token_path) | |
49 | f = File.new(@token_path, "r") | |
50 | begin | |
51 | token = MultiJson.decode(f.read) | |
52 | rescue | |
53 | token = create_rdio_token | |
54 | end | |
55 | else | |
56 | token = create_rdio_token | |
57 | end | |
58 | ||
59 | Rdio::SimpleRdio.new([@rdio_key, @rdio_secret], token) | |
60 | end | |
61 | ||
62 | def rdio_track | |
63 | u = @rdio.call('currentUser', {'extras' => "lastSongPlayed"}) | |
64 | @artist ||= u["result"]["lastSongPlayed"]["artist"] | |
65 | @song ||= u["result"]["lastSongPlayed"]["name"] | |
66 | end | |
67 | ||
68 | def create_rdio_token | |
69 | rdio = Rdio::SimpleRdio.new([@rdio_key, @rdio_secret]) | |
70 | puts "Go To This URL To Authorize App:" | |
71 | auth_url = rdio.begin_authentication('oob') | |
72 | puts auth_url | |
73 | `open #{auth_url}` | |
74 | print "Please type the authorization code: " | |
75 | auth_code = gets.chomp | |
76 | token = rdio.complete_authentication(auth_code) | |
77 | ||
78 | f = File.new(@token_path, "w") | |
79 | f.print(MultiJson.encode(token)) | |
80 | f.close | |
81 | ||
82 | token | |
83 | end | |
84 | ||
85 | def exit_with_error | |
86 | abort "Usage: #{$0} artist song" | |
87 | end | |
88 | ||
89 | def get_lyrics | |
90 | ||
91 | #Use the API to search | |
92 | uri = URI("http://lyrics.wikia.com/api.php?artist=#{self.sanitize_param @artist}&song=#{self.sanitize_param @song}&fmt=realjson") | |
93 | begin | |
94 | res = Net::HTTP.get(uri) | |
95 | res = MultiJson.decode(res) | |
96 | ||
97 | #Get the actual lyrics url | |
98 | doc = Nokogiri::HTML(open(res['url'])) | |
99 | node = doc.search(".lyricbox").first | |
100 | rescue | |
101 | abort "Lyrics not found :(" | |
102 | end | |
103 | ||
104 | #Remove the rtMatcher nodes | |
105 | node.search(".rtMatcher").each do |n| | |
106 | n.remove | |
107 | end | |
108 | ||
109 | #Maintain new lines | |
110 | node.search("br").each do |br| | |
111 | br.replace "\n" | |
112 | end | |
113 | ||
114 | #Retrieve the lyrics | |
115 | puts node.inner_text | |
116 | end | |
117 | ||
118 | def check_params | |
119 | self.exit_with_error if @artist.nil? or @artist.empty? | |
120 | self.exit_with_error if @song.nil? or @song.empty? | |
121 | end | |
122 | ||
123 | def sanitize_param(p) | |
124 | URI.encode_www_form_component(p.gsub(/ /, "+")).gsub("%2B", "+") | |
125 | end | |
126 | end | |
127 | ||
128 | ||
129 | lrc = Lyricli.new | |
130 | lrc.check_params | |
131 | lrc.get_lyrics |