hearken 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +14 -0
  3. data/.tool-versions +1 -0
  4. data/Gemfile +7 -1
  5. data/Gemfile.lock +95 -0
  6. data/{README.rdoc → README.md} +12 -50
  7. data/bin/console +15 -0
  8. data/bin/setup +8 -0
  9. data/exe/hearken +9 -0
  10. data/exe/hearken_index +13 -0
  11. data/hearken.gemspec +35 -35
  12. data/lib/hearken/colour.rb +3 -1
  13. data/lib/hearken/command/enqueue.rb +35 -10
  14. data/lib/hearken/command/reload.rb +18 -6
  15. data/lib/hearken/command/search.rb +31 -20
  16. data/lib/hearken/console.rb +11 -27
  17. data/lib/hearken/debug.rb +6 -6
  18. data/lib/hearken/indexing/ffmpeg_file.rb +7 -0
  19. data/lib/hearken/indexing/file.rb +3 -1
  20. data/lib/hearken/indexing/indexer.rb +32 -24
  21. data/lib/hearken/library.rb +49 -41
  22. data/lib/hearken/monkey_violence.rb +9 -7
  23. data/lib/hearken/paths.rb +13 -19
  24. data/lib/hearken/range_expander.rb +18 -13
  25. data/lib/hearken/tagged.rb +15 -11
  26. data/lib/hearken/track.rb +53 -39
  27. data/lib/hearken.rb +2 -2
  28. metadata +52 -141
  29. data/.gitignore +0 -5
  30. data/HISTORY.rdoc +0 -38
  31. data/MIT-LICENSE +0 -20
  32. data/bin/hearken +0 -7
  33. data/bin/hearken_index +0 -12
  34. data/lib/hearken/command/list.rb +0 -32
  35. data/lib/hearken/command/love.rb +0 -7
  36. data/lib/hearken/command/profile.rb +0 -7
  37. data/lib/hearken/command/recent.rb +0 -38
  38. data/lib/hearken/command/remove.rb +0 -15
  39. data/lib/hearken/command/restart.rb +0 -7
  40. data/lib/hearken/command/scrobbling.rb +0 -14
  41. data/lib/hearken/command/setup_scrobbling.rb +0 -7
  42. data/lib/hearken/command/shuffle.rb +0 -13
  43. data/lib/hearken/command/start.rb +0 -7
  44. data/lib/hearken/command/status.rb +0 -7
  45. data/lib/hearken/command/stop.rb +0 -7
  46. data/lib/hearken/command.rb +0 -35
  47. data/lib/hearken/notification/growl_notifier.rb +0 -15
  48. data/lib/hearken/player.rb +0 -126
  49. data/lib/hearken/preferences.rb +0 -30
  50. data/lib/hearken/queue.rb +0 -33
  51. data/lib/hearken/scrobbler.rb +0 -77
  52. data/lib/hearken/simple_scrobbler.rb +0 -94
  53. data/media/ice_cream.png +0 -0
  54. data/spec/hearken/command/enqueue_spec.rb +0 -24
  55. data/spec/hearken/command/list_spec.rb +0 -31
  56. data/spec/hearken/command/reload_spec.rb +0 -20
  57. data/spec/hearken/command/shuffle_spec.rb +0 -31
  58. data/spec/hearken/player_spec.rb +0 -38
  59. data/spec/hearken/range_expander_spec.rb +0 -28
  60. data/spec/spec_helper.rb +0 -5
data/HISTORY.rdoc DELETED
@@ -1,38 +0,0 @@
1
- = 0.1.1
2
-
3
- * added use of sox to play more audio file formats (now m4a and mp3 with afplay and sox for everything else)
4
- * fixed some issues with the parsing of ffmpeg output to get correct tag information
5
- * added logging of played tracks to history file
6
- * removed splat dependency (because it is just silly)
7
-
8
- = 0.1.0
9
-
10
- * removed several dependencies - simple_scrobbler and thor
11
- * split hearken command into two
12
- * added 'love' command (to mark current track as loved)
13
- * added 'profile' command (to launch last.fm profile to see track history)
14
- * replaced 'flush' with an 'rm' command that can remove tracks matches criteria
15
-
16
- = 0.0.5
17
-
18
- * fixed 'recent' command - the library is sorted on file modification date
19
- * moved 'current_song' from working directory to .hearken directory
20
- * Changed dequeue to return track instead of id - this fixed a bug where reindexing would cause player to start playing the wrong files.
21
-
22
- = 0.0.4
23
-
24
- * Partially fixed bug with growl (correctly escaping characters in message)
25
- * moved all configuration, queues and index to a .hearken directory
26
-
27
- = 0.0.3
28
-
29
- * Fixed bug in setup_scrobbling command (using $stdin directly - 'gets' seems to have been aliased by thor)
30
- * Added growl notification
31
-
32
- = 0.0.2
33
-
34
- * First functioning version - combination of features from audio_library and songbirdsh
35
-
36
- = 0.0.1
37
-
38
- * Released empty gem (to claim the name before proceeding any further)
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2011 Mark Ryall
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/hearken DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $: << File.dirname(__FILE__)+'/../lib'
4
-
5
- require 'hearken/console'
6
-
7
- Hearken::Console.new.push
data/bin/hearken_index DELETED
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $: << File.dirname(__FILE__)+'/../lib'
4
-
5
- require 'hearken/indexing'
6
-
7
- unless ARGV.size == 1
8
- puts "usage: hearken_index path_to_directory_containing_music_collection"
9
- exit
10
- end
11
-
12
- Hearken::Indexing::Indexer.new(ARGV.shift).execute
@@ -1,32 +0,0 @@
1
- require 'hearken/command'
2
- require 'hearken/colour'
3
-
4
- class Hearken::Command::List
5
- include Hearken::Command
6
- include Hearken::Colour
7
-
8
- usage '*<word>'
9
- help <<EOF
10
- lists the contents of the track queue
11
- these results can optionally be filtered by specified words
12
- when playing, approximate times for each track will be displayed
13
- EOF
14
- execute do |text|
15
- @terms = text.split(/\W/)
16
- current = @player.current
17
- if current
18
- next_start_time = Time.at current.started
19
- show next_start_time, current
20
- end
21
- next_start_time += current.time.to_i if next_start_time && current.time
22
- @player.each do |track|
23
- show next_start_time, track
24
- next_start_time += track.time.to_i if next_start_time && track.time
25
- end
26
- end
27
-
28
- def show time, track
29
- return unless @terms.empty? or @terms.all? {|term| track.search_string.include? term }
30
- puts time ? "#{c time.strftime("%H:%M:%S %d/%m/%Y"), :blue} #{track}" : track
31
- end
32
- end
@@ -1,7 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Love
4
- include Hearken::Command
5
- help 'sends love for the current track to last fm'
6
- execute {|ignored| @player.love }
7
- end
@@ -1,7 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Profile
4
- include Hearken::Command
5
- help 'launches last fm profile'
6
- execute {|ignored| @player.profile }
7
- end
@@ -1,38 +0,0 @@
1
- require 'hearken/command'
2
- require 'hearken/colour'
3
-
4
- class Hearken::Command::Recent
5
- include Hearken::Command
6
- include Hearken::Colour
7
-
8
- usage '<count>'
9
- help 'lists the specified number of recently added albums'
10
- execute do |text|
11
- @player.library.reload unless @player.library.tracks
12
- all_tracks = @player.library.tracks.sort do |a, b|
13
- tc = a.timestamp <=> b.timestamp
14
- tc == 0 ? a.id <=> b.id : tc
15
- end
16
- maximum, current_album, tracks, total_count = text.to_i, nil, [], 0
17
- all_tracks.reverse.each do |track|
18
- unless current_album
19
- current_album = track.album
20
- tracks = [track]
21
- next
22
- end
23
- if current_album==track.album
24
- tracks << track
25
- else
26
- puts "#{c extract_artist(tracks), :yellow} #{c current_album, :cyan} #{tracks.size} tracks [#{tracks.last.search_id}-#{tracks.first.search_id}]"
27
- current_album = track.album
28
- tracks = [track]
29
- total_count += 1
30
- end
31
- break if total_count >= maximum
32
- end
33
- end
34
- private
35
- def extract_artist tracks
36
- tracks.map{|t| t.artist}.uniq.size == 1 ? tracks.first.artist : 'various artists'
37
- end
38
- end
@@ -1,15 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Remove
4
- include Hearken::Command
5
- usage '*<word>'
6
- help 'removes all tracks that match the specified criteria - specifying no criteria will flush entire queue'
7
- execute do |text|
8
- @terms = text.split(/\W/)
9
- ids = []
10
- while track = @player.dequeue
11
- ids << track.id unless @terms.all? {|term| track.search_string.include? term }
12
- end
13
- ids.each {|id| @player.enqueue id }
14
- end
15
- end
@@ -1,7 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Restart
4
- include Hearken::Command
5
- help 'stops and restarts the player (which will kill the current track)'
6
- execute {|ignored| @player.restart }
7
- end
@@ -1,14 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Scrobbling
4
- include Hearken::Command
5
- usage '<on|off>'
6
- help 'turns interaction with lastfm on or off'
7
- execute do |text|
8
- scrobbling = (text == 'on')
9
- return if @player.scrobbling == scrobbling
10
- puts scrobbling ? 'Turning scrobbling on' : 'Turning scrobbling off'
11
- @player.scrobbling = scrobbling
12
- @player.restart
13
- end
14
- end
@@ -1,7 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::SetupScrobbling
4
- include Hearken::Command
5
- help 'runs through the steps required to get lastfm scrobbling working'
6
- execute {|ignored| @player.scrobbler.setup }
7
- end
@@ -1,13 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Shuffle
4
- include Hearken::Command
5
- help 'shuffles the current queue'
6
- execute do |ignored=nil|
7
- ids = []
8
- while track = @player.dequeue
9
- ids << track.id
10
- end
11
- ids.sort_by { rand }.each {|id| @player.enqueue id }
12
- end
13
- end
@@ -1,7 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Start
4
- include Hearken::Command
5
- help 'starts the player'
6
- execute {|ignored| @player.start }
7
- end
@@ -1,7 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Status
4
- include Hearken::Command
5
- help 'shows the current player status'
6
- execute {|ignored| puts @player.status }
7
- end
@@ -1,7 +0,0 @@
1
- require 'hearken/command'
2
-
3
- class Hearken::Command::Stop
4
- include Hearken::Command
5
- help 'stops the player'
6
- execute {|ignored| @player.stop }
7
- end
@@ -1,35 +0,0 @@
1
- module Hearken
2
- module Command
3
- attr_reader :usage, :help
4
-
5
- def self.included cls
6
- cls.extend ClassMethods
7
- end
8
-
9
- def self.load name, *args
10
- require "hearken/command/#{name}"
11
- classname = name.to_s.split('_').map{|s|s.capitalize}.join
12
- Hearken::Command.const_get(classname).new *args
13
- end
14
-
15
- def initialize player
16
- @player = player
17
- @usage = ''
18
- @help = ''
19
- end
20
-
21
- module ClassMethods
22
- def usage usage
23
- define_method(:usage) { usage }
24
- end
25
-
26
- def help help
27
- define_method(:help) { help }
28
- end
29
-
30
- def execute &block
31
- define_method :execute, block
32
- end
33
- end
34
- end
35
- end
@@ -1,15 +0,0 @@
1
- require 'hearken/monkey_violence'
2
-
3
- module Hearken::Notification
4
- end
5
-
6
- class Hearken::Notification::GrowlNotifier
7
- def initialize preferences
8
- @growlnotify = !`which growlnotify`.chomp.empty?
9
- @image_path = File.expand_path File.dirname(__FILE__)+'/../../../media/ice_cream.png'
10
- end
11
-
12
- def started track
13
- `growlnotify -t "Hearken unto ..." --image #{@image_path} -m \"#{track.to_short_s.escape_for_sh_quoted}\"` if @growlnotify
14
- end
15
- end
@@ -1,126 +0,0 @@
1
- require 'fileutils'
2
-
3
- require 'hearken/queue'
4
- require 'hearken/scrobbler'
5
- require 'hearken/notification/growl_notifier'
6
- require 'hearken/library'
7
- require 'hearken/colour'
8
-
9
- module Hearken
10
- class Player
11
- include Queue
12
- include Colour
13
- attr_reader :library, :scrobbler
14
-
15
- def initialize preferences
16
- @scrobbler = Scrobbler.new preferences
17
- @scrobbler.enabled = true
18
- @growl = Hearken::Notification::GrowlNotifier.new preferences
19
- @notifiers = [@scrobbler, @growl]
20
- @library = Library.new preferences
21
- @library.reload
22
- create_paths
23
- end
24
-
25
- def status
26
- if @pid
27
- track = self.current
28
- played = Time.now.to_i-track.started
29
- timing = "(#{c track.time.to_i-played, :yellow} remaining)" if track.time
30
- puts "#{c Time.at(track.started).strftime("%H:%M:%S %d/%m/%Y"), :blue}: #{track} #{timing}"
31
- else
32
- puts 'not playing'.foreground(:yellow)
33
- end
34
- end
35
-
36
- def love
37
- @scrobbler.love current
38
- end
39
-
40
- def profile
41
- @scrobbler.profile
42
- end
43
-
44
- def current
45
- in_base_dir do
46
- (@pid and File.exist?('current_song')) ? YAML.load_file('current_song') : nil
47
- end
48
- end
49
-
50
- def register track
51
- track.started = Time.now.to_i
52
- in_base_dir do
53
- File.open('current_song', 'w') {|f| f.print track.to_yaml }
54
- File.open('history', 'a') {|f| f.puts "#{track.started},#{track.path}"}
55
- end
56
- end
57
-
58
- def notify_started track
59
- @notifiers.each {|notifier| notifier.started track if notifier.respond_to? :started}
60
- end
61
-
62
- def notify_finished track
63
- @notifiers.each {|notifier| notifier.finished track if notifier.respond_to? :finished}
64
- end
65
-
66
- def scrobbling tf
67
- @scrobbler.enabled = tf
68
- end
69
-
70
- def random_track
71
- @library.row (rand * @library.count).to_i
72
- end
73
-
74
- def start
75
- return if @pid
76
- if @library.count == 0
77
- puts 'Player can not be started with an empty library'
78
- puts 'Please run "hearken_index" in another shell and then \'reload\''
79
- return
80
- end
81
- @pid = fork do
82
- player_pid = nil
83
- Signal.trap('TERM') do
84
- Process.kill 'TERM', player_pid if player_pid
85
- exit
86
- end
87
- loop do
88
- track = dequeue || random_track
89
- next unless track
90
- unless File.exist? track.path
91
- puts "skipping track as #{track.path} does not exist"
92
- next
93
- end
94
- notify_started track
95
- register track
96
- player_pid = spawn play_command track.path
97
- Process.wait player_pid
98
- notify_finished track
99
- end
100
- end
101
- end
102
-
103
- def play_command path
104
- if %w{m4a mp3}.include? path.split('.').last
105
- "afplay \"#{path.escape("\`")}\""
106
- else
107
- "play -q \"#{path.escape("\`")}\""
108
- end.tap do |command|
109
- in_base_dir do
110
- File.open('player', 'a') {|f| f.puts command }
111
- end
112
- end
113
- end
114
-
115
- def stop
116
- return unless @pid
117
- Process.kill 'TERM', @pid
118
- @pid = nil
119
- end
120
-
121
- def restart
122
- stop
123
- start
124
- end
125
- end
126
- end
@@ -1,30 +0,0 @@
1
- require 'hearken/paths'
2
- require 'hearken/monkey_violence'
3
-
4
- module Hearken
5
- class Preferences
6
- include Hearken::Paths
7
-
8
- def initialize
9
- create_paths
10
- if File.exists? preferences_path
11
- @preferences = YAML.load_file preferences_path
12
- else
13
- @preferences = {}
14
- end
15
- end
16
-
17
- def [] key
18
- @preferences[key]
19
- end
20
-
21
- def []= key, value
22
- @preferences[key] = value
23
- persist
24
- end
25
-
26
- def persist
27
- File.open(preferences_path, 'w') {|f| f.puts @preferences.to_yaml}
28
- end
29
- end
30
- end
data/lib/hearken/queue.rb DELETED
@@ -1,33 +0,0 @@
1
- require 'hearken/paths'
2
-
3
- module Hearken::Queue
4
- include Hearken::Paths
5
-
6
- def enqueue id
7
- in_queue_dir do
8
- @sequence ||= 0
9
- @library.with_track id do |track|
10
- File.open("#{Time.now.to_i}-#{@sequence.to_s.rjust(8,'0')}.song", 'w') {|f| f.print track.to_yaml }
11
- @sequence += 1
12
- end
13
- end
14
- end
15
-
16
- def each
17
- in_queue_dir do
18
- Dir.glob('*.song').sort.each do |file|
19
- yield YAML.load_file file
20
- end
21
- end
22
- end
23
-
24
- def dequeue
25
- in_queue_dir do
26
- file = Dir.glob('*.song').sort.first
27
- return nil unless file
28
- hash = YAML.load_file file
29
- FileUtils.rm file
30
- hash
31
- end
32
- end
33
- end
@@ -1,77 +0,0 @@
1
- require 'hearken/simple_scrobbler'
2
- require 'hearken/debug'
3
-
4
- # Modified version of simple_scrobbler gem from https://github.com/threedaymonk/simple_scrobbler
5
- module Hearken
6
- class Scrobbler
7
- API_KEY = '21f8c75ad38637220b20a03ad61219a4'
8
- SECRET = 'ab77019c84eef8bc16bcfd5ba8db0c5d'
9
- include Debug
10
-
11
- def initialize preferences
12
- @preferences = preferences
13
- end
14
-
15
- def enabled= tf
16
- @scrobbler = nil
17
- if @preferences['lastfm'] and tf
18
- debug "Configuring scrobbler with #{@preferences['lastfm'].inspect}"
19
- user, session = *%w{user session_key}.map{|k| @preferences['lastfm'][k]}
20
- @scrobbler = SimpleScrobbler.new API_KEY, SECRET, user, session
21
- end
22
- end
23
-
24
- def finished track
25
- return unless @scrobbler
26
- debug "Scrobbling to last fm: #{track}"
27
- send_to_scrobbler :scrobble, track
28
- end
29
-
30
- def started track
31
- return unless @scrobbler
32
- debug "Updating now listening with last fm: #{track}"
33
- send_to_scrobbler :now_playing, track
34
- end
35
-
36
- def love track
37
- return unless @scrobbler and track
38
- debug "Sending love to last fm: #{track}"
39
- send_to_scrobbler :love, track
40
- end
41
-
42
- def profile
43
- return unless @scrobbler
44
- @scrobbler.with_profile_url {|url| system "open #{url}" }
45
- end
46
-
47
- def ask question
48
- print question
49
- $stdin.gets.chomp
50
- end
51
-
52
- def setup
53
- preferences = {}
54
- preferences['user'] = ask 'What is your lastfm user name ? '
55
- @scrobbler = SimpleScrobbler.new API_KEY, SECRET, preferences['user']
56
- preferences['session_key'] = @scrobbler.fetch_session_key do |url|
57
- system "open '#{url}'"
58
- ask 'Please hit enter when you\'ve allowed this application access to your account'
59
- end
60
- @preferences['lastfm'] = preferences
61
- end
62
- private
63
- def send_to_scrobbler message, track
64
- begin
65
- debug %w{artist title time album track}.map {|k| "#{k}=#{track.send(k)}"}.join(',')
66
- @scrobbler.send message, track.artist,
67
- track.title,
68
- :duration => track.time,
69
- :album => track.album,
70
- :trackNumber => track.track.to_i,
71
- :timestamp => Time.now.to_i
72
- rescue Exception => e
73
- puts "Failed to scrobble: #{e}"
74
- end
75
- end
76
- end
77
- end
@@ -1,94 +0,0 @@
1
- require "net/http"
2
- require "digest/md5"
3
- require "uri"
4
- require "cgi"
5
- require 'nokogiri'
6
- require 'hearken/debug'
7
-
8
- module Hearken; end
9
-
10
- class Hearken::SimpleScrobbler
11
- include Hearken::Debug
12
-
13
- SCROBBLER_URL = 'http://ws.audioscrobbler.com/2.0/'
14
-
15
- SubmissionError = Class.new(RuntimeError)
16
- SessionError = Class.new(RuntimeError)
17
-
18
- def initialize api_key, secret, user, session_key=nil
19
- @api_key = api_key
20
- @secret = secret
21
- @user = user
22
- @session_key = session_key
23
- end
24
-
25
- attr_reader :user, :api_key, :secret, :session_key
26
-
27
- def session_key
28
- @session_key or raise SessionError, "The session key must be set or fetched"
29
- end
30
-
31
- def fetch_session_key
32
- doc = lfm :get, 'auth.gettoken'
33
- request_token = doc.at('token').inner_text
34
- yield "http://www.last.fm/api/auth/?api_key=#{api_key}&token=#{request_token}"
35
- doc = lfm :get, 'auth.getsession', :token => request_token
36
- @session_key = doc.at('key').inner_text
37
- @user = doc.at('name').inner_text
38
- @session_key
39
- end
40
-
41
- def with_profile_url
42
- yield "http://www.last.fm/user/#{user}" if user
43
- end
44
-
45
- # http://www.last.fm/api/show?service=443
46
- def scrobble artist, title, params={}
47
- lfm_track 'track.scrobble', artist, title, params
48
- end
49
-
50
- # See http://www.last.fm/api/show?service=454 for more details
51
- def now_playing artist, title, params={}
52
- lfm_track 'track.updateNowPlaying', artist, title, params
53
- end
54
-
55
- # http://www.last.fm/api/show?service=260
56
- def love artist, title, params={}
57
- lfm_track 'track.love', artist, title, params
58
- end
59
- private
60
- def lfm_track method, artist, title, params
61
- doc = lfm :post, method, params.merge(:sk => session_key, :artist => artist, :track => title)
62
- status = doc.at('lfm')['status']
63
- raise SubmissionError, status unless status == 'ok'
64
- end
65
-
66
- def lfm get_or_post, method, parameters={}
67
- p = signed_parameters parameters.merge :api_key => api_key, :method => method
68
- debug p.inspect
69
- xml = self.send get_or_post, SCROBBLER_URL, p
70
- debug xml
71
- Nokogiri::XML xml
72
- end
73
-
74
- def get url, parameters
75
- query_string = sort_parameters(parameters).
76
- map{ |k, v| "#{k}=#{CGI.escape(v)}" }.
77
- join("&")
78
- Net::HTTP.get_response(URI.parse(url + "?" + query_string)).body
79
- end
80
-
81
- def post url, parameters
82
- Net::HTTP.post_form(URI.parse(url), parameters).body
83
- end
84
-
85
- def signed_parameters parameters
86
- sorted = sort_parameters parameters
87
- signature = Digest::MD5.hexdigest(sorted.flatten.join + secret)
88
- parameters.merge :api_sig => signature
89
- end
90
-
91
- def sort_parameters parameters
92
- parameters.map{ |k, v| [k.to_s, v.to_s] }.sort
93
- end
94
- end
data/media/ice_cream.png DELETED
Binary file