From: Ben Beltran Date: Fri, 5 Oct 2012 06:16:08 +0000 (-0500) Subject: First Batch of Source Changes [Broken] X-Git-Url: https://git.r.bdr.sh/rbdr/lyricli.rb/commitdiff_plain/b8498f5c67d736e9724e124e85aa36a58648afef?hp=-c First Batch of Source Changes [Broken] Changing the architecture of lyricli, passing from "Experiment" to "Project". So here goes. This definitely doesn't work. So no sense even trying. I still need to transfer a lot of things, including docs and tests. Aaaaand. That's it. --- b8498f5c67d736e9724e124e85aa36a58648afef diff --git a/Gemfile b/Gemfile index 5b8fcbd..4c91c06 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,6 @@ source :rubygems -gem 'nokogiri' -gem 'multi_json' -gem 'rdio' +gem 'nokogiri', "~> 1.5.5" +gem 'multi_json', "~> 1.3.6" +gem 'rdio', "~> 0.1.0" +gem "launchy", "~> 2.1.2" diff --git a/Gemfile.lock b/Gemfile.lock index 4c016b5..a15cfa4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,10 @@ GEM remote: http://rubygems.org/ specs: + addressable (2.3.2) json (1.7.5) + launchy (2.1.2) + addressable (~> 2.3) multi_json (1.3.6) nokogiri (1.5.5) oauth (0.4.7) @@ -13,6 +16,7 @@ PLATFORMS ruby DEPENDENCIES - multi_json - nokogiri - rdio + launchy (~> 2.1.2) + multi_json (~> 1.3.6) + nokogiri (~> 1.5.5) + rdio (~> 0.1.0) diff --git a/bin/lrc b/bin/lrc new file mode 100644 index 0000000..e69de29 diff --git a/lib/lyricli.rb b/lib/lyricli.rb new file mode 100755 index 0000000..928adad --- /dev/null +++ b/lib/lyricli.rb @@ -0,0 +1,107 @@ +#!/usr/bin/env ruby -w + +require 'uri' +require 'net/http' +require 'multi_json' +require 'nokogiri' +require 'open-uri' +require 'launchy' + +# This shit causes a lot of warnings. Quick Hack. +original_verbosity = $VERBOSE +$VERBOSE = nil +require 'rdio' +$VERBOSE = original_verbosity + +class Lyricli + + # TODO: Change the whole fucking thing + def initialize + @rdio_key = "sddac5t8akqrzh5b6kg53jfm" + @rdio_secret = "PRcB8TggFr" + @token_path = File.expand_path("~/.rdio_token") + + #Expand the symlink and get the path + if File.symlink?(__FILE__) then + path = File.dirname(File.readlink(__FILE__)) + else + path = File.dirname(__FILE__) + end + + # Get the current rdio track + @rdio = init_rdio + rdio_track + + #Get the current iTunes track + current = `osascript #{path}/current_song.scpt` + if current and not current.empty? then + current = current.split("<-SEP->") + @artist ||= current[0] + @song ||= current[1] + end + end + + def init_rdio + + if File.exists?(@token_path) + f = File.new(@token_path, "r") + begin + token = MultiJson.decode(f.read) + rescue + token = create_rdio_token + end + else + token = create_rdio_token + end + + Rdio::SimpleRdio.new([@rdio_key, @rdio_secret], token) + end + + + def exit_with_error + abort "Usage: #{$0} artist song" + end + + def get_lyrics + + #Use the API to search + uri = URI("http://lyrics.wikia.com/api.php?artist=#{self.sanitize_param @artist}&song=#{self.sanitize_param @song}&fmt=realjson") + begin + res = Net::HTTP.get(uri) + res = MultiJson.decode(res) + + #Get the actual lyrics url + doc = Nokogiri::HTML(open(res['url'])) + node = doc.search(".lyricbox").first + rescue + abort "Lyrics not found :(" + end + + #Remove the rtMatcher nodes + node.search(".rtMatcher").each do |n| + n.remove + end + + #Maintain new lines + node.search("br").each do |br| + br.replace "\n" + end + + #Retrieve the lyrics + puts node.inner_text + end + + def check_params + self.exit_with_error if @artist.nil? or @artist.empty? + self.exit_with_error if @song.nil? or @song.empty? + end + + def sanitize_param(p) + URI.encode_www_form_component(p.gsub(/ /, "+")).gsub("%2B", "+") + end +end + + +lrc = Lyricli.new +lrc.check_params +lrc.get_lyrics diff --git a/lib/lyricli/config.rb b/lib/lyricli/config.rb new file mode 100644 index 0000000..da999ec --- /dev/null +++ b/lib/lyricli/config.rb @@ -0,0 +1,47 @@ +module Lyricli + class Config + + def initialize + @config_path = "~/.lyricli.conf" + @config = load_config + end + + @@instance = Config.new + + def self.instance + @@instance + end + + def [](key) + @config[key] + end + + def []=(key, value) + @config[key] = value + save_config + end + + private_class_method :new + + private + + # TODO: Apart from this, load a default yml that will be used for this. + # And just extend everything from the user's config. + def load_config + path = File.expand_path(@config_path) + if File.exists?(path) + file = File.new(path, "r") + MultiJson.decode(file.read) + else + {} + end + end + + def save_config + path = File.expand_path(@config_path) + file = File.new(path, "w") + file.print(MultiJson.encode(@config)) + file.close + end + end +end diff --git a/lib/lyricli/sources/arguments.rb b/lib/lyricli/sources/arguments.rb new file mode 100644 index 0000000..e69de29 diff --git a/lib/lyricli/sources/itunes.rb b/lib/lyricli/sources/itunes.rb new file mode 100644 index 0000000..e69de29 diff --git a/lib/lyricli/sources/rdio.rb b/lib/lyricli/sources/rdio.rb new file mode 100644 index 0000000..afb736d --- /dev/null +++ b/lib/lyricli/sources/rdio.rb @@ -0,0 +1,65 @@ +module Lyricli + module Sources + module Rdio + + # Returns the name of the source, in snake_case + def self.name + "rdio" + end + + # The enable method should run all of the tasks needed to validate + # the source. In the case of Rdio it has to authenticate with OAuth. + def self.enable + # Validation Code + @config = Lyricli::Config + unless @config[:rdio_auth_token] && !@config[:rdio_auth_token].empty? + create_auth_token + end + + end + + # Instantiates everything it needs to run. + def self.start + @rdio = Rdio::SimpleRdio.new([@config[:rdio_key], @config[:rdio_secret]], @config[:rdio_auth_token]) + end + + # The current_track method should return the name of the current + # artist and song. + # @return [Hash] A hash containing the current `:song` and `:artist`. + def self.current_track + u = @rdio.call('currentUser', {'extras' => 'lastSongPlayed'}) + artist = u["result"]["lastSongPlayed"]["artist"] + song = u["result"]["lastSongPlayed"]["name"] + {artist: artist, song: song} + end + + # The reset method resets any configurations it may have + def self.reset + # Reset Code + end + + private + + # Signs in to rdio with our credentials and requests access for a new auth + # token. + def create_auth_token + rdio = Rdio::SimpleRdio.new([@config]) + + # Request Authorization + puts "Follow this URL to authorize lyricli:" + auth_url = rdio.begin_authentication('oob') + puts auth_url + Launchy.open(auth_url) + + # Request Code, Obtain Token + print "Please type the authorization code: " + auth_code = gets.chomp + token = rdio.complete_authentication(auth_code) + + @config[:rdio_auth_token] = token + token + end + + end + end +end diff --git a/lib/lyricli/util.rb b/lib/lyricli/util.rb new file mode 100644 index 0000000..9ae9f6c --- /dev/null +++ b/lib/lyricli/util.rb @@ -0,0 +1,14 @@ +module Lyricli + module Util + def camelize(str) + str.split('_').map {|w| w.capitalize}.join + end + + def parse_class(class_name) + klass = Module.const_get(class_name) + return klass if klass.is_a?(Class) + rescue NameError + return nil + end + end +end diff --git a/lib/source_manager.rb b/lib/source_manager.rb new file mode 100644 index 0000000..834326d --- /dev/null +++ b/lib/source_manager.rb @@ -0,0 +1,47 @@ +module Lyricli + class SourceManager + + include Lyricli::Util + + def initialize + @enabled_sources = [] + @config = Lyricli::Config + end + + def enable(source_name) + if source_module = module_exists?(camelize(str)) + source_module.enable + @config[:enabled_sources] << klass.name + else + raise Lyricli::EnableSourceException + end + end + + def disable(source_name) + if source_module = module_exists?(camelize(str)) + @config[:enabled_sources].delete(klass.name) + else + raise Lyricli::DisableSourceException + end + end + + def reset(source_name) + if source_module = module_exists?(camelize(str)) + source_module.reset + disable(source_name) + else + raise Lyricli::ResetSourceException + end + end + + def start + @config[:enabled_sources].each do |source| + begin + source.start + rescue + fail "Source #{source.name} has failed to start. Please reset the source by running `#{$0} source reset #{source.name}.`" + end + end + end + end +end