scrapescrobbler 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .*.swp
2
+ tmp
3
+ pkg
4
+ *.gem
5
+ *.rbc
data/CONTRIBUTORS ADDED
@@ -0,0 +1 @@
1
+ * Christopher Peplin
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ http://www.opensource.org/licenses/mit-license.php
2
+
3
+ The MIT License
4
+
5
+ Copyright (c) 2010 Christopher Peplin
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ scrapescrobbler -- A scrobbler for last.fm that scrapes radio station playlists
2
+ ===============================================================================
3
+
4
+ ## Description
5
+
6
+ Scrapescobbler is a tool to submit tracks you're listening to on an
7
+ old-fashioned radio station to last.fm.
8
+
9
+ Many radio stations offer almost real-time playlists online. For those of us who
10
+ still listen to them, scrapescrobbler will submit the tracks as they are publised
11
+ by the station to your last.fm feed. Start up scrapescrobbler when your radio is
12
+ on, and scrobble away.
13
+
14
+
15
+ ## Installation
16
+
17
+ RubyGems is the preferred method of installation:
18
+
19
+ $ [sudo] gem install scrapescrobbler
20
+
21
+ For the moment, this requires a forked version of the lastfm gem. Install it
22
+ like so:
23
+
24
+ $ git clone https://github.com/peplin/ruby-lastfm.git ruby-lastfm
25
+ $ cd ruby-lastfm
26
+ $ git checkout scrobblingv2
27
+ $ rake install
28
+
29
+ ## Running
30
+
31
+ Whenever you're listening to the radio, run scrapescrobbler with the name of the
32
+ station:
33
+
34
+ $ ss listen wyep
35
+
36
+ The station must be in the list of supported stations. To see a list of
37
+ available stations, try this:
38
+
39
+ $ ss stations
40
+
41
+ ## Configuration & Authentication
42
+
43
+ Before using scrapescrobbler, you must authenticate it with your Last.fm
44
+ account. Running the `listen` command will warn you that you are not
45
+ authenticated and spit out a URL - visit that and give scrapescrobbler the
46
+ go-ahead, and things should work fine. If you need to re-authenticate for any
47
+ reason, just run:
48
+
49
+ $ ss authenticate
50
+
51
+ ## Contributing
52
+
53
+ Favorite station not in the list? Fork the repo on GitHub:
54
+
55
+ http://github.com/peplin/scrapescrobbler
56
+
57
+ Add a file in stations/ that provides the Station API and send a pull request.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.unshift File.expand_path("../lib", __FILE__)
3
+
4
+ require 'rubygems'
5
+ require 'rubygems/specification'
6
+ require 'rake/gempackagetask'
7
+ require 'scrapescrobbler'
8
+
9
+ def gemspec
10
+ @gemspec ||= begin
11
+ file = File.expand_path('../scrapescrobbler.gemspec', __FILE__)
12
+ eval(File.read(file), binding, file)
13
+ end
14
+ end
15
+
16
+ begin
17
+ require 'rspec/core/rake_task'
18
+
19
+ task :default => :spec
20
+
21
+ desc "Run specs"
22
+ RSpec::Core::RakeTask.new do |t|
23
+ t.rspec_opts = %w(-fs --color)
24
+ end
25
+
26
+ namespace :spec do
27
+ task :clean do
28
+ if sudo?
29
+ system "sudo rm -rf #{File.expand_path('../tmp', __FILE__)}"
30
+ else
31
+ rm_rf 'tmp'
32
+ end
33
+ end
34
+
35
+ desc "Run the full spec suite"
36
+ task :full => ["clean", "spec"]
37
+ end
38
+ rescue LoadError
39
+ task :spec do
40
+ abort "Run `gem install rspec` to be able to run specs"
41
+ end
42
+ end
43
+
44
+ Rake::GemPackageTask.new(gemspec) do |pkg|
45
+ pkg.gem_spec = gemspec
46
+ end
47
+
48
+ desc "install the gem locally"
49
+ task :install => [:package] do
50
+ sh %{gem install pkg/#{gemspec.name}-#{gemspec.version}}
51
+ end
52
+
53
+ desc "validate the gemspec"
54
+ task :gemspec do
55
+ gemspec.validate
56
+ end
data/bin/dev_scrapes ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # Executable with absolute path to lib for hacking and development
3
+ require File.join('.', File.dirname(__FILE__), '..', 'lib', 'scrapescrobbler')
4
+ Scrapescrobbler::CLI.invoke
data/bin/scrapes ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ require 'scrapescrobbler'
4
+ rescue LoadError
5
+ if File.symlink? __FILE__
6
+ require File.dirname(File.readlink(__FILE__)) + '/../lib/scrapescrobbler'
7
+ else
8
+ require File.dirname(__FILE__) + '/../lib/scrapescrobbler'
9
+ end
10
+ end
11
+ Scrapescrobbler::CLI.invoke
@@ -0,0 +1,43 @@
1
+ require 'dm-core'
2
+ require 'dm-migrations'
3
+ require 'dm-validations'
4
+ require 'Getopt/Declare'
5
+ require 'active_support/all'
6
+
7
+ require File.join(File.dirname(__FILE__), 'scrapescrobbler', 'config')
8
+ require File.join(File.dirname(__FILE__), 'scrapescrobbler', 'helpers')
9
+ require File.join(File.dirname(__FILE__), 'scrapescrobbler', 'cli')
10
+ require File.join(File.dirname(__FILE__), 'scrapescrobbler', 'listener')
11
+
12
+ DB_NAME = 'sqlite://' + (defined?(TEST_MODE) ? '/tmp/db' : Scrapescrobbler::Config['database_file'])
13
+ DataMapper::Logger.new($stdout, :debug) if defined?(TEST_MODE)
14
+ DataMapper.setup(:default, DB_NAME)
15
+
16
+ Dir["#{File.dirname(__FILE__)}/scrapescrobbler/models/*.rb"].each do |path|
17
+ require path
18
+ end
19
+
20
+ Dir["#{File.dirname(__FILE__)}/scrapescrobbler/stations/*.rb"].each do |path|
21
+ require path
22
+ end
23
+
24
+ Dir["#{File.dirname(__FILE__)}/scrapescrobbler/commands/*.rb"].each do |path|
25
+ require path
26
+ end
27
+
28
+ DataMapper.finalize
29
+ DataMapper.auto_upgrade!
30
+
31
+ module Scrapescrobbler
32
+ extend self
33
+
34
+ class AlreadyRunning < StandardError
35
+ def message
36
+ "Scrapescrobbler is already running"
37
+ end
38
+ end
39
+
40
+ CLI.args = Getopt::Declare.new(<<-EOF)
41
+ #{CLI::USAGE}
42
+ EOF
43
+ end
@@ -0,0 +1,73 @@
1
+ module Scrapescrobbler
2
+ module CLI
3
+ attr_accessor :args
4
+ extend self
5
+
6
+ USAGE = <<-EOF
7
+
8
+ Scrapescrobbler - Old-Fashioned Radio Station Scrobbling
9
+
10
+ Usage: #{File.basename $0} COMMAND [OPTIONS] [ARGS...]
11
+
12
+ where COMMAND is one of:
13
+ * listen - start scrobbling a radio station's playlist
14
+ usage: ss listen [STATION]
15
+ * stations - list all available stations
16
+ usage: ss stations
17
+ * authenticate - re-authenticate with last.fm
18
+ usage: ss authenticate
19
+ * configure - write out a config file. print path to config file.
20
+
21
+ OTHER OPTIONS
22
+ -h, --help Display this help
23
+
24
+ Submit bugs and feature requests to http://github.com/peplin/scrapescrobbler/issues
25
+ EOF
26
+
27
+ def parse arguments
28
+ args.parse arguments
29
+ end
30
+
31
+ def invoke
32
+ args['-h'] ? say(USAGE) : invoke_command_if_valid
33
+ end
34
+
35
+ def commands
36
+ Scrapescrobbler::CLI::USAGE.scan(/\* \w+/).map{|s| s.gsub(/\* /, '')}
37
+ end
38
+
39
+ def say *something
40
+ puts *something
41
+ end
42
+
43
+ def invoke_command_if_valid
44
+ command = args.unused.shift
45
+ set_global_options
46
+ case (valid = commands.select{|name| name =~ %r|^#{command}|}).size
47
+ when 0 then say "Invalid command: #{command}"
48
+ when 1 then send valid[0]
49
+ else
50
+ say "Ambiguous command: #{command}" if command
51
+ say(USAGE)
52
+ end
53
+ end
54
+
55
+ # currently just sets whether output should be rounded to 15 min intervals
56
+ def set_global_options
57
+ Scrapescrobbler::Entry.round = true if args['-r']
58
+ end
59
+
60
+ private
61
+
62
+ def unused_args
63
+ args.unused.join(' ')
64
+ end
65
+
66
+ def ask_user question
67
+ return true if args['-y']
68
+ print question
69
+ $stdin.gets =~ /\Aye?s?\Z/i
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,10 @@
1
+ module Scrapescrobbler
2
+ module CLI
3
+ def authenticate
4
+ lastfm = Lastfm.new Config['api_key'], Config['api_secret']
5
+ token = lastfm.auth.get_token
6
+ say "Go to http://www.last.fm/api/auth/?api_key=#{Config['api_key']}&token=#{token} to allow scrapescrobbler to access your last.fm account."
7
+ Config.update! 'token' => token
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module Scrapescrobbler
2
+ module CLI
3
+ def listen
4
+ listener = Listener.new unused_args
5
+ listener.listen
6
+ while true
7
+ listener.update
8
+ sleep 60
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module Scrapescrobbler
2
+ module CLI
3
+ def stations
4
+ say "FOO"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,45 @@
1
+ module Scrapescrobbler
2
+ module Config
3
+ extend self
4
+ PATH = ENV['SCRAPESCROBBLER_CONFIG_FILE'] || File.join(ENV['HOME'], '.scrapescrobbler.yml')
5
+
6
+ # Application defaults.
7
+ #
8
+ # These are written to a config file by invoking:
9
+ # <code>
10
+ # t configure
11
+ # </code>
12
+ def defaults
13
+ {
14
+ # Path to the sqlite db
15
+ 'database_file' => "#{ENV['HOME']}/.scrapescrobbler.db",
16
+ 'api_key' => "73af75e07cd58bfe66d13af9371b9504",
17
+ 'api_secret' => "85b1b415e9c2b653e84bd1304d4dd9fa",
18
+ 'token' => nil
19
+ }
20
+ end
21
+
22
+ def [](key)
23
+ overrides = File.exist?(PATH) ? YAML.load(File.read(PATH)) : {}
24
+ defaults.merge(overrides)[key]
25
+ rescue => e
26
+ puts "invalid config file"
27
+ puts e.message
28
+ defaults[key]
29
+ end
30
+
31
+ def configure!
32
+ unless File.exist?(PATH)
33
+ File.open(PATH, 'w') do |fh|
34
+ fh.puts(defaults.to_yaml)
35
+ end
36
+ end
37
+ end
38
+
39
+ def update! values
40
+ File.open(PATH, 'w') do |fh|
41
+ fh.puts(defaults.update(values).to_yaml)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,13 @@
1
+ class Array
2
+ def chunk(chunk_size)
3
+ chunks = [self.length / chunk_size, 1].max.times.collect { [] }
4
+ while self.any?
5
+ chunks.each do |a_chunk|
6
+ chunk_size.times do
7
+ a_chunk << self.shift if self.any?
8
+ end
9
+ end
10
+ end
11
+ chunks
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ #require 'lastfm'
2
+ #lastfm = Lastf.new(key, secret)
3
+ #token =
@@ -0,0 +1,55 @@
1
+ require 'lastfm'
2
+
3
+ module Scrapescrobbler
4
+ class Listener
5
+ attr_accessor :lastfm, :station, :started
6
+
7
+ def initialize(station)
8
+ @lastfm = Listener.authenticate
9
+ @station = ::Scrapescrobbler::Stations.const_get(station.classify)
10
+ end
11
+
12
+ def listen
13
+ raise if @started
14
+ @started = DateTime.now
15
+ end
16
+
17
+ def update
18
+ playlist = Stations::Wyep::playlist
19
+ if playlist and playlist.length > 0 then
20
+ @now_playing = playlist.first
21
+ playlist.each do |song|
22
+ saved = song.save
23
+ self.scrobble(song) if saved
24
+ end
25
+ end
26
+ end
27
+
28
+ def scrobble song
29
+ puts "Scrobbling #{song} @ #{Time.now}"
30
+ if song.album then
31
+ @lastfm.track.scrobble song.artist, song.title, song.album, Time.now.utc.to_i
32
+ else
33
+ @lastfm.track.scrobble song.artist, song.title, Time.now.utc.to_i
34
+ end
35
+ end
36
+
37
+ def now_playing
38
+ update if not @now_playing
39
+ @now_playing
40
+ end
41
+
42
+ private
43
+
44
+ def self.authenticate
45
+ if not Config['token']
46
+ CLI.authenticate
47
+ exit
48
+ else
49
+ lastfm = Lastfm.new Config['api_key'], Config['api_secret']
50
+ lastfm.session = lastfm.auth.get_session(Config['token'])
51
+ lastfm
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,17 @@
1
+ module Scrapescrobbler
2
+ class Song
3
+ include DataMapper::Resource
4
+ property :id, Serial
5
+ property :time, DateTime, :required => true
6
+ property :artist, String, :required => true
7
+ property :title, String, :required => true
8
+ property :album, String
9
+ property :station, String, :required => true
10
+
11
+ validates_uniqueness_of :time, :scope => :station
12
+
13
+ def to_s
14
+ "#{artist} - #{title}"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module Scrapescrobbler
2
+ module Stations
3
+ class Station
4
+ def playlist count
5
+ raise NotImplementedError
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ require 'hpricot'
2
+ require 'open-uri'
3
+
4
+ module Scrapescrobbler
5
+ module Stations
6
+ class Wyep < Station
7
+ NAME = "WYEP"
8
+ FREQUENCY = "91.3"
9
+ FM = true
10
+ PLAYLIST_URL = "http://wyep.org/playlist/"
11
+
12
+ def self.playlist
13
+ doc = open(PLAYLIST_URL) { |f| Hpricot(f) }
14
+
15
+ table = doc.at("div#center_right")
16
+ breaks = table/"tr"/"td"
17
+ songs = []
18
+ [table/"td.now_playing", table/"td.odd_row" - breaks, table/"td.even_row" - breaks].each do |row|
19
+ next unless row.length != 0
20
+ playlist_entries = row.collect do |cell|
21
+ cell.inner_html
22
+ end
23
+ songs = playlist_entries.chunk(5).collect do |entry|
24
+ time = entry[0] == "NOW PLAYING" ? Time.now : Time.parse(entry[0])
25
+ Scrapescrobbler::Song.new :time => time, :artist => entry[1],
26
+ :title => entry[2], :album => entry[3], :station => Wyep::NAME
27
+ end
28
+ end
29
+ songs
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module Scrapescrobbler
2
+ VERSION = "0.1" unless defined?(::Scrapescrobbler::VERSION)
3
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require 'scrapescrobbler/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "scrapescrobbler"
9
+ s.version = Scrapescrobbler::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["Christopher Peplin"]
12
+ s.email = %q{chris.peplin@rhubarbtech.com}
13
+ s.homepage = "http://github.com/peplin/scrapescrobbler"
14
+ s.summary = %q{Radio station last.fm scrobbler}
15
+ s.description = %q{Scrapescobbler is a tool to submit tracks you're listening to on an old-fashioned radio station to last.fm.}
16
+
17
+ s.required_rubygems_version = ">= 1.3.6"
18
+
19
+ s.add_development_dependency "rspec"
20
+ s.add_development_dependency "mocha"
21
+ s.add_dependency "hpricot"
22
+ s.add_dependency "lastfm"
23
+ s.add_dependency "dm-core"
24
+ s.add_dependency "dm-sqlite-adapter"
25
+ s.add_dependency "dm-migrations"
26
+ s.add_dependency "dm-validations"
27
+ s.add_dependency "activesupport", ">= 3.0.0"
28
+
29
+ s.files = `git ls-files`.split("\n")
30
+ s.test_files = `git ls-files -- spec/*`.split("\n")
31
+ s.executables = `git ls-files bin/*`.split("\n").map{ |f| File.basename(f) }
32
+ s.default_executable = "scrapescrobble"
33
+ s.require_paths = ["lib"]
34
+ end
@@ -0,0 +1,24 @@
1
+ require 'scrapescrobbler'
2
+ require 'spec_helper'
3
+
4
+ module Scrapescrobbler
5
+ describe CLI do
6
+ include HelperMethods
7
+
8
+ describe "list" do
9
+ before :each do
10
+ mockit
11
+ end
12
+
13
+ it "should list all available stations" do
14
+ invoke 'stations'
15
+ $stdin.should include(Stations.constants.collect do |const|
16
+ station = Stations.const_get(const)
17
+ if station != Stations::Station then
18
+ station::NAME
19
+ end
20
+ end.compact)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'scrapescrobbler'
2
+ require 'spec_helper'
3
+
4
+ module Scrapescrobbler
5
+ describe CLI do
6
+ include HelperMethods
7
+
8
+ describe "listen" do
9
+ before :each do
10
+ mockit
11
+ end
12
+
13
+ it "should complain without a station"
14
+
15
+ it "should complain with more than one station"
16
+
17
+ it "should start a last.fm session"
18
+
19
+ it "should not return"
20
+
21
+ it "should enable scrobbling for the station"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,114 @@
1
+ require 'scrapescrobbler'
2
+ require 'spec_helper'
3
+ require 'lastfm'
4
+
5
+ module Scrapescrobbler
6
+ describe Listener do
7
+ include HelperMethods
8
+
9
+ describe "with an instance" do
10
+ before :each do
11
+ mockit
12
+ ::Lastfm::MethodCategory::Auth.any_instance.stubs(
13
+ :get_session).returns("A session")
14
+ ::Lastfm::MethodCategory::Auth.any_instance.stubs(
15
+ :get_token).returns("a token")
16
+ @scrobble_stub = ::Lastfm::MethodCategory::Track.any_instance.stubs(
17
+ :scrobble).returns("Good job!")
18
+ @station = "wyep"
19
+ @listener = Listener.new @station
20
+ @song = Song.new(:time => Time.now, :station => @station,
21
+ :title => "The Best Song Ever", :artist => 'Price')
22
+ end
23
+
24
+ it "should have a station" do
25
+ @listener.station.should eq(Stations::Wyep)
26
+ end
27
+
28
+ it "should have a last.fm instance" do
29
+ @listener.lastfm.should be_an_instance_of(::Lastfm)
30
+ end
31
+
32
+ describe "that is inactive" do
33
+ it "should not have a start time" do
34
+ @listener.started.should eq(nil)
35
+ end
36
+
37
+ it "should not have a last.fm session" do
38
+ @listener.lastfm.auth.should_not respond_to(:session)
39
+ end
40
+ end
41
+
42
+ describe "that is active" do
43
+ before :each do
44
+ @listener.listen
45
+ Stations::Wyep.stubs(:playlist).returns([@song])
46
+ end
47
+
48
+ it "should have a start time" do
49
+ @listener.should respond_to(:started)
50
+ @listener.started.should be_an_instance_of(DateTime)
51
+ end
52
+
53
+ it "should have a last.fm session" do
54
+ @listener.lastfm.should respond_to(:auth)
55
+ @listener.lastfm.should respond_to(:session)
56
+ end
57
+
58
+ it "should have a current song" do
59
+ @listener.should respond_to(:now_playing)
60
+ @listener.now_playing.should be_an_instance_of(Song)
61
+ end
62
+
63
+ describe "and when updated" do
64
+ it "should check the station's playlist" do
65
+ @listener.station.expects(:playlist)
66
+ @listener.update
67
+ end
68
+
69
+ describe "and there is a new song to scrobble" do
70
+
71
+ it "should create a new Song" do
72
+ proc { @listener.update }.should change(Song, :count)
73
+ song = Song.first :time => @song.time, :station => @song.station
74
+ song.title.should eq(@song.title)
75
+ end
76
+
77
+ it "should scrobble the song" do
78
+ @scrobble_stub.expects(:scrobble).with(@song.artist, @song.title)
79
+ @listener.update
80
+ end
81
+
82
+ it "should have a current song that matches the new song" do
83
+ @listener.update
84
+ @listener.now_playing.should eq(@song)
85
+ end
86
+ end
87
+
88
+ describe "and there is not a new song to scrobble" do
89
+ before do
90
+ @song.save
91
+ end
92
+
93
+ it "should not create a new Song" do
94
+ @listener.update
95
+ proc { @listener.update }.should_not change(Song, :count)
96
+ end
97
+
98
+ it "should not scrobble the song" do
99
+ @scrobble_stub.expects(:scrobble).with(@song.artist,
100
+ @song.title).never
101
+ @listener.update
102
+ end
103
+
104
+ it "should not update the current song" do
105
+ @listener.update
106
+ proc { @listener.update }.should_not change(@listener,
107
+ :now_playing)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,35 @@
1
+ require 'scrapescrobbler'
2
+
3
+ module Scrapescrobbler
4
+ describe Song do
5
+ before do
6
+ @song = Song.new :artist => "Prince", :title => "Purple Rain",
7
+ :time => Time.now
8
+ end
9
+
10
+ it "should have a time" do
11
+ @song.should respond_to :time
12
+ end
13
+
14
+ it "should have an artist" do
15
+ @song.should respond_to :artist
16
+ end
17
+
18
+ it "should have a title" do
19
+ @song.should respond_to :title
20
+ end
21
+
22
+ it "should have a station" do
23
+ @song.should respond_to :station
24
+ end
25
+
26
+ it "shouldn't save without a station" do
27
+ @song.save.should == false
28
+ end
29
+
30
+ it "should require a station" do
31
+ @song.station = "wyep"
32
+ @song.save.should == true
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ require 'scrapescrobbler'
2
+
3
+ module Scrapescrobbler
4
+ module HelperMethods
5
+ def invoke command
6
+ Scrapescrobbler::CLI.parse command
7
+ Scrapescrobbler::CLI.invoke
8
+ end
9
+
10
+ def mockit
11
+ $stdout = StringIO.new
12
+ $stdin = StringIO.new
13
+ DataMapper.auto_migrate!
14
+ end
15
+ end
16
+ end
17
+
18
+ RSpec.configure do |config|
19
+ config.mock_with :mocha
20
+ end
metadata ADDED
@@ -0,0 +1,213 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scrapescrobbler
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Christopher Peplin
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-12-06 00:00:00 -05:00
17
+ default_executable: scrapescrobble
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rspec
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: mocha
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :development
44
+ version_requirements: *id002
45
+ - !ruby/object:Gem::Dependency
46
+ name: hpricot
47
+ prerelease: false
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ type: :runtime
57
+ version_requirements: *id003
58
+ - !ruby/object:Gem::Dependency
59
+ name: lastfm
60
+ prerelease: false
61
+ requirement: &id004 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ type: :runtime
70
+ version_requirements: *id004
71
+ - !ruby/object:Gem::Dependency
72
+ name: dm-core
73
+ prerelease: false
74
+ requirement: &id005 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ type: :runtime
83
+ version_requirements: *id005
84
+ - !ruby/object:Gem::Dependency
85
+ name: dm-sqlite-adapter
86
+ prerelease: false
87
+ requirement: &id006 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ type: :runtime
96
+ version_requirements: *id006
97
+ - !ruby/object:Gem::Dependency
98
+ name: dm-migrations
99
+ prerelease: false
100
+ requirement: &id007 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ type: :runtime
109
+ version_requirements: *id007
110
+ - !ruby/object:Gem::Dependency
111
+ name: dm-validations
112
+ prerelease: false
113
+ requirement: &id008 !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ type: :runtime
122
+ version_requirements: *id008
123
+ - !ruby/object:Gem::Dependency
124
+ name: activesupport
125
+ prerelease: false
126
+ requirement: &id009 !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ segments:
132
+ - 3
133
+ - 0
134
+ - 0
135
+ version: 3.0.0
136
+ type: :runtime
137
+ version_requirements: *id009
138
+ description: Scrapescobbler is a tool to submit tracks you're listening to on an old-fashioned radio station to last.fm.
139
+ email: chris.peplin@rhubarbtech.com
140
+ executables:
141
+ - dev_scrapes
142
+ - scrapes
143
+ extensions: []
144
+
145
+ extra_rdoc_files: []
146
+
147
+ files:
148
+ - .gitignore
149
+ - CONTRIBUTORS
150
+ - LICENSE
151
+ - README.md
152
+ - Rakefile
153
+ - bin/dev_scrapes
154
+ - bin/scrapes
155
+ - lib/scrapescrobbler.rb
156
+ - lib/scrapescrobbler/cli.rb
157
+ - lib/scrapescrobbler/commands/authenticate.rb
158
+ - lib/scrapescrobbler/commands/listen.rb
159
+ - lib/scrapescrobbler/commands/stations.rb
160
+ - lib/scrapescrobbler/config.rb
161
+ - lib/scrapescrobbler/helpers.rb
162
+ - lib/scrapescrobbler/lastfm.rb
163
+ - lib/scrapescrobbler/listener.rb
164
+ - lib/scrapescrobbler/models/song.rb
165
+ - lib/scrapescrobbler/stations/base.rb
166
+ - lib/scrapescrobbler/stations/wyep.rb
167
+ - lib/scrapescrobbler/version.rb
168
+ - scrapescrobbler.gemspec
169
+ - spec/cli/list_spec.rb
170
+ - spec/cli/listen_spec.rb
171
+ - spec/listener_spec.rb
172
+ - spec/models/song_spec.rb
173
+ - spec/spec_helper.rb
174
+ has_rdoc: true
175
+ homepage: http://github.com/peplin/scrapescrobbler
176
+ licenses: []
177
+
178
+ post_install_message:
179
+ rdoc_options: []
180
+
181
+ require_paths:
182
+ - lib
183
+ required_ruby_version: !ruby/object:Gem::Requirement
184
+ none: false
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ segments:
189
+ - 0
190
+ version: "0"
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ segments:
197
+ - 1
198
+ - 3
199
+ - 6
200
+ version: 1.3.6
201
+ requirements: []
202
+
203
+ rubyforge_project:
204
+ rubygems_version: 1.3.7
205
+ signing_key:
206
+ specification_version: 3
207
+ summary: Radio station last.fm scrobbler
208
+ test_files:
209
+ - spec/cli/list_spec.rb
210
+ - spec/cli/listen_spec.rb
211
+ - spec/listener_spec.rb
212
+ - spec/models/song_spec.rb
213
+ - spec/spec_helper.rb