play 0.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.
Files changed (54) hide show
  1. data/Gemfile +2 -0
  2. data/Gemfile.lock +87 -0
  3. data/README.md +139 -0
  4. data/Rakefile +185 -0
  5. data/bin/play +49 -0
  6. data/config.ru +10 -0
  7. data/db/migrate/01_create_schema.rb +55 -0
  8. data/lib/play.rb +73 -0
  9. data/lib/play/album.rb +6 -0
  10. data/lib/play/app.rb +118 -0
  11. data/lib/play/app/api.rb +110 -0
  12. data/lib/play/artist.rb +21 -0
  13. data/lib/play/client.rb +67 -0
  14. data/lib/play/core_ext/hash.rb +6 -0
  15. data/lib/play/history.rb +7 -0
  16. data/lib/play/library.rb +58 -0
  17. data/lib/play/office.rb +34 -0
  18. data/lib/play/song.rb +97 -0
  19. data/lib/play/templates/album_songs.mustache +5 -0
  20. data/lib/play/templates/artist_songs.mustache +5 -0
  21. data/lib/play/templates/index.mustache +18 -0
  22. data/lib/play/templates/layout.mustache +23 -0
  23. data/lib/play/templates/now_playing.mustache +5 -0
  24. data/lib/play/templates/play_history.mustache +3 -0
  25. data/lib/play/templates/profile.mustache +24 -0
  26. data/lib/play/templates/search.mustache +3 -0
  27. data/lib/play/templates/show_song.mustache +9 -0
  28. data/lib/play/templates/song.mustache +21 -0
  29. data/lib/play/user.rb +59 -0
  30. data/lib/play/views/album_songs.rb +9 -0
  31. data/lib/play/views/artist_songs.rb +9 -0
  32. data/lib/play/views/index.rb +9 -0
  33. data/lib/play/views/layout.rb +6 -0
  34. data/lib/play/views/now_playing.rb +17 -0
  35. data/lib/play/views/play_history.rb +9 -0
  36. data/lib/play/views/profile.rb +9 -0
  37. data/lib/play/views/search.rb +9 -0
  38. data/lib/play/views/show_song.rb +19 -0
  39. data/lib/play/vote.rb +7 -0
  40. data/play.gemspec +129 -0
  41. data/play.yml.example +22 -0
  42. data/public/css/base.css +129 -0
  43. data/test/helper.rb +33 -0
  44. data/test/spec/mini.rb +24 -0
  45. data/test/test_api.rb +118 -0
  46. data/test/test_app.rb +57 -0
  47. data/test/test_artist.rb +15 -0
  48. data/test/test_client.rb +11 -0
  49. data/test/test_library.rb +19 -0
  50. data/test/test_office.rb +26 -0
  51. data/test/test_play.rb +17 -0
  52. data/test/test_song.rb +78 -0
  53. data/test/test_user.rb +21 -0
  54. metadata +299 -0
@@ -0,0 +1,17 @@
1
+ module Play
2
+ module Views
3
+ class NowPlaying < Layout
4
+ def title
5
+ "now playing"
6
+ end
7
+
8
+ def artist_name
9
+ @song.artist_name
10
+ end
11
+
12
+ def song_title
13
+ @song.title
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module Play
2
+ module Views
3
+ class PlayHistory < Layout
4
+ def title
5
+ "History"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Play
2
+ module Views
3
+ class Profile < Layout
4
+ def title
5
+ @user ? @user.name : "Profile"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Play
2
+ module Views
3
+ class Search < Layout
4
+ def title
5
+ @search
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Play
2
+ module Views
3
+ class ShowSong < Layout
4
+ def title
5
+ "#{@song.title} by #{@song.artist.name}"
6
+ end
7
+
8
+ def users
9
+ @song.votes.group(:user_id).collect do |vote|
10
+ vote.user
11
+ end
12
+ end
13
+
14
+ def plays
15
+ @song.votes.count
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/play/vote.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Play
2
+ class Vote < ActiveRecord::Base
3
+ belongs_to :song
4
+ belongs_to :user
5
+ belongs_to :artist
6
+ end
7
+ end
data/play.gemspec ADDED
@@ -0,0 +1,129 @@
1
+ ## This is the rakegem gemspec template. Make sure you read and understand
2
+ ## all of the comments. Some sections require modification, and others can
3
+ ## be deleted if you don't need them. Once you understand the contents of
4
+ ## this file, feel free to delete any comments that begin with two hash marks.
5
+ ## You can find comprehensive Gem::Specification documentation, at
6
+ ## http://docs.rubygems.org/read/chapter/20
7
+ Gem::Specification.new do |s|
8
+ s.specification_version = 2 if s.respond_to? :specification_version=
9
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.rubygems_version = '1.3.5'
11
+
12
+ ## Leave these as is they will be modified for you by the rake gemspec task.
13
+ ## If your rubyforge_project name is different, then edit it and comment out
14
+ ## the sub! line in the Rakefile
15
+ s.name = 'play'
16
+ s.version = '0.0.1'
17
+ s.date = '2011-05-05'
18
+ s.rubyforge_project = 'play'
19
+
20
+ ## Make sure your summary is short. The description may be as long
21
+ ## as you like.
22
+ s.summary = "Your company's dj. ►"
23
+ s.description = "We want to play music at our office. Everyone has their own
24
+ library on their own machines, and everyone except for me plays shitty music.
25
+ Play is designed to make office music more palatable."
26
+
27
+ ## List the primary authors. If there are a bunch of authors, it's probably
28
+ ## better to set the email to an email list or something. If you don't have
29
+ ## a custom homepage, consider using your GitHub URL or the like.
30
+ s.authors = ["Zach Holman"]
31
+ s.email = 'github.com@zachholman.com'
32
+ s.homepage = 'https://github.com/holman/play'
33
+
34
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
35
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
36
+ s.require_paths = %w[lib]
37
+
38
+ ## If your gem includes any executables, list them here.
39
+ s.executables = ["play"]
40
+ s.default_executable = 'play'
41
+
42
+ ## Specify any RDoc options here. You'll want to add your README and
43
+ ## LICENSE files to the extra_rdoc_files list.
44
+ #s.rdoc_options = ["--charset=UTF-8"]
45
+ #s.extra_rdoc_files = %w[README LICENSE]
46
+
47
+ ## List your runtime dependencies here. Runtime dependencies are those
48
+ ## that are needed for an end user to actually USE your code.
49
+ s.add_dependency('rack', ["~>1.2.2"])
50
+ s.add_dependency('sinatra')
51
+ s.add_dependency('activerecord')
52
+ s.add_dependency('sqlite3')
53
+ s.add_dependency('mustache')
54
+ s.add_dependency('SystemTimer')
55
+ s.add_dependency('ruby-audioinfo')
56
+ s.add_dependency('oa-oauth')
57
+ s.add_dependency('yajl-ruby')
58
+ s.add_dependency('mysql2')
59
+
60
+ ## List your development dependencies here. Development dependencies are
61
+ ## those that are only needed during development
62
+ s.add_development_dependency('running_man')
63
+ s.add_development_dependency('mocha')
64
+
65
+ ## Leave this section as-is. It will be automatically generated from the
66
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
67
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
68
+ # = MANIFEST =
69
+ s.files = %w[
70
+ Gemfile
71
+ Gemfile.lock
72
+ README.md
73
+ Rakefile
74
+ bin/play
75
+ config.ru
76
+ db/migrate/01_create_schema.rb
77
+ lib/play.rb
78
+ lib/play/album.rb
79
+ lib/play/app.rb
80
+ lib/play/app/api.rb
81
+ lib/play/artist.rb
82
+ lib/play/client.rb
83
+ lib/play/core_ext/hash.rb
84
+ lib/play/history.rb
85
+ lib/play/library.rb
86
+ lib/play/office.rb
87
+ lib/play/song.rb
88
+ lib/play/templates/album_songs.mustache
89
+ lib/play/templates/artist_songs.mustache
90
+ lib/play/templates/index.mustache
91
+ lib/play/templates/layout.mustache
92
+ lib/play/templates/now_playing.mustache
93
+ lib/play/templates/play_history.mustache
94
+ lib/play/templates/profile.mustache
95
+ lib/play/templates/search.mustache
96
+ lib/play/templates/show_song.mustache
97
+ lib/play/templates/song.mustache
98
+ lib/play/user.rb
99
+ lib/play/views/album_songs.rb
100
+ lib/play/views/artist_songs.rb
101
+ lib/play/views/index.rb
102
+ lib/play/views/layout.rb
103
+ lib/play/views/now_playing.rb
104
+ lib/play/views/play_history.rb
105
+ lib/play/views/profile.rb
106
+ lib/play/views/search.rb
107
+ lib/play/views/show_song.rb
108
+ lib/play/vote.rb
109
+ play.gemspec
110
+ play.yml.example
111
+ public/css/base.css
112
+ test/helper.rb
113
+ test/spec/mini.rb
114
+ test/test_api.rb
115
+ test/test_app.rb
116
+ test/test_artist.rb
117
+ test/test_client.rb
118
+ test/test_library.rb
119
+ test/test_office.rb
120
+ test/test_play.rb
121
+ test/test_song.rb
122
+ test/test_user.rb
123
+ ]
124
+ # = MANIFEST =
125
+
126
+ ## Test files will be grabbed from the file list. Make sure the path glob
127
+ ## matches what you actually use.
128
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
129
+ end
data/play.yml.example ADDED
@@ -0,0 +1,22 @@
1
+ # This file should get moved to:
2
+ # ~/.play.yml
3
+ #
4
+ # Also you should fill it out.
5
+
6
+ path: /path/to/your/music/yo
7
+ gh_key: github_oauth_key
8
+ gh_secret: github_oauth_secret
9
+ office_url: http://example.com/office.macs
10
+
11
+ # Database stuffs that we'll pass on to ActiveRecord. Change if you want to. If
12
+ # you don't want to, you are probably a handsome-looking gentlemen or a
13
+ # gorgeous lady who knows what they want out of life.
14
+ db:
15
+ database: play
16
+ adapter: mysql2
17
+ user: user
18
+ password: password
19
+ reconnect: true
20
+ # db:
21
+ # database: db/play.sqlite3
22
+ # adapter: sqlite3
@@ -0,0 +1,129 @@
1
+ /*
2
+
3
+ dark: 485460
4
+ 3D72AA
5
+ 5E7894
6
+ 438FDF
7
+ D0E4FA
8
+ */
9
+
10
+ html{
11
+ font-family: Helvetica;
12
+ }
13
+ body{
14
+ margin: 0;
15
+ padding: 0;
16
+ color: #5E7894;
17
+ }
18
+ h1{
19
+ margin: 1em 10px 0 10px;
20
+ padding: 0;
21
+ letter-spacing: -3px;
22
+ color: #000;
23
+ }
24
+ a{
25
+ color: #5E7894;
26
+ text-decoration: none;
27
+ }
28
+ a:hover{
29
+ color: #000;
30
+ }
31
+
32
+ .navigation{
33
+ text-align: right;
34
+ padding: 2px 10px;
35
+ font-weight: bold;
36
+ letter-spacing: -1px;
37
+ font-size: 1.4em;
38
+ }
39
+ .navigation a{
40
+ color: #485460;
41
+ padding-left: 10px;
42
+ text-decoration: none;
43
+ }
44
+ .navigation form{
45
+ display: inline;
46
+ }
47
+ .navigation input{
48
+ vertical-align: top;
49
+ width: 250px;
50
+ }
51
+ .content{
52
+ padding: 10px;
53
+ background-color: #D0E4FA;
54
+ }
55
+ .gravatar{
56
+ -webkit-border-radius: 5px;
57
+ }
58
+
59
+ /*
60
+ * SONGS
61
+ */
62
+ .songs{
63
+
64
+ }
65
+ .song{
66
+ letter-spacing: -1px;
67
+ background-color: #D0E4FA;
68
+ border-top: 2px solid #fff;
69
+ padding: .5em 10px;
70
+ font-size: 1.25em;
71
+ font-weight: bold;
72
+ }
73
+ .song a:hover{
74
+ color: #000 !important;
75
+ }
76
+ .song .artist{
77
+ font-size: 3em;
78
+ letter-spacing: -5px;
79
+ }
80
+ .song .artist a{
81
+ color: #485460;
82
+ }
83
+ .song .title{
84
+ padding-left: 10px;
85
+ font-size: 2.2em;
86
+ letter-spacing: -4px;
87
+ }
88
+ .song .album{
89
+ margin-left: 10px;
90
+ font-size: 1.1em;
91
+ letter-spacing: -2px;
92
+ }
93
+ .song .album a{
94
+ color: #438FDF;
95
+ }
96
+ .song .controls{
97
+ float: right;
98
+ font-size: .75em;
99
+ margin: -.5em -5px;
100
+ text-transform: uppercase;
101
+ }
102
+ .votes{
103
+ background-color: #485460;
104
+ padding: 5px 5px 0px 5px;
105
+ }
106
+ .votes img{
107
+ border: 1px solid #5E7894;
108
+ }
109
+ .votes img:hover{
110
+ border: 1px solid #D0E4FA;
111
+ }
112
+
113
+ /*
114
+ * PROFILE
115
+ */
116
+ .profile_box{
117
+ margin-right: 10px;
118
+ float: left;
119
+ font-size: 1.1em;
120
+ }
121
+ .bio{
122
+ padding: 15px 0;
123
+ }
124
+ .favorite_artists{
125
+ margin: 0 15px;
126
+ }
127
+ .favorite_artists h2{
128
+ color: #485460;
129
+ }
data/test/helper.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'test/unit'
2
+
3
+ begin
4
+ require 'rubygems'
5
+ require 'redgreen'
6
+ require 'leftright'
7
+ rescue LoadError
8
+ end
9
+
10
+ require 'rack/test'
11
+ require 'mocha'
12
+ require 'spec/mini'
13
+ require 'running_man'
14
+ require 'running_man/active_record_block'
15
+
16
+ ENV['RACK_ENV'] = 'test'
17
+
18
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
19
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
20
+
21
+ require 'play'
22
+ include Play
23
+
24
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3',
25
+ :database => ":memory:")
26
+ ActiveRecord::Migration.verbose = false
27
+ ActiveRecord::Migrator.migrate("db/migrate")
28
+
29
+ RunningMan.setup_on ActiveSupport::TestCase, :ActiveRecordBlock
30
+
31
+ def parse_json(json)
32
+ Yajl.load(json, :symbolize_keys => true)
33
+ end
data/test/spec/mini.rb ADDED
@@ -0,0 +1,24 @@
1
+ ##
2
+ # test/spec/mini 5
3
+ # http://gist.github.com/307649
4
+ # chris@ozmm.org
5
+ #
6
+ def context(*args, &block)
7
+ return super unless (name = args.first) && block
8
+ require 'test/unit'
9
+ klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
10
+ def self.test(name, &block)
11
+ define_method("test_#{name.to_s.gsub(/\W/,'_')}", &block) if block
12
+ end
13
+ def self.xtest(*args) end
14
+ def self.context(*args, &block) instance_eval(&block) end
15
+ def self.setup(&block)
16
+ define_method(:setup) { self.class.setups.each { |s| instance_eval(&s) } }
17
+ setups << block
18
+ end
19
+ def self.setups; @setups ||= [] end
20
+ def self.teardown(&block) define_method(:teardown, &block) end
21
+ end
22
+ (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
23
+ klass.class_eval &block
24
+ end
data/test/test_api.rb ADDED
@@ -0,0 +1,118 @@
1
+ require 'helper'
2
+ include Rack::Test::Methods
3
+
4
+ def app
5
+ Play::App
6
+ end
7
+
8
+ context "Api" do
9
+ fixtures do
10
+ @artist = Play::Artist.create(:name => "Justice")
11
+ @album = Play::Album.create(:name => "Cross", :artist => @artist)
12
+ @song = Play::Song.create(:title => "Stress",
13
+ :artist => @artist,
14
+ :album => @album)
15
+ @user = Play::User.create(:login => 'holman', :alias => 'zach')
16
+ end
17
+
18
+ test "/api/now_playing" do
19
+ Play.expects(:now_playing).returns(@song)
20
+ get "/api/now_playing"
21
+ now_playing = parse_json(last_response.body.strip)
22
+ assert_equal @artist.name, now_playing[:artist_name]
23
+ assert_equal @song.title, now_playing[:song_title]
24
+ assert_equal @album.name, now_playing[:album_name]
25
+ end
26
+
27
+ test "/api requires user_login" do
28
+ post "/api/add_song", {}
29
+ user = parse_json(last_response.body.strip)
30
+ assert user[:error].include?("must supply a valid `user_login`")
31
+ end
32
+
33
+ test "user login check also works for aliases" do
34
+ post "/api/add_song", {:user_login => 'zach'}
35
+ user = parse_json(last_response.body.strip)
36
+ assert !user[:error].include?("must supply a valid `user_login`")
37
+ end
38
+
39
+ test "/api/add_song" do
40
+ post "/api/add_song", { :song_title => @song.title,
41
+ :artist_name => @artist.name,
42
+ :user_login => @user.login }
43
+ song = parse_json(last_response.body.strip)
44
+ assert_equal @song.title, song[:song_title]
45
+ end
46
+
47
+ test "/api/add_song without a found artist" do
48
+ post "/api/add_song", { :song_title => 'Stress',
49
+ :artist_name => "Ace of Base",
50
+ :user_login => @user.login }
51
+ resp = parse_json(last_response.body.strip)
52
+ assert resp[:error].include?("find that artist")
53
+ end
54
+
55
+ test "/api/add_song without a found song" do
56
+ post "/api/add_song", { :song_title => "I Saw the Sign",
57
+ :artist_name => @artist.name,
58
+ :user_login => @user.login }
59
+ resp = parse_json(last_response.body.strip)
60
+ assert resp[:error].include?("find that song")
61
+ end
62
+
63
+ test "/api/add_artist" do
64
+ post "/api/add_artist", { :artist_name => @artist.name,
65
+ :user_login => @user.login }
66
+ song = parse_json(last_response.body.strip)
67
+ assert_equal @artist.name, song[:artist_name]
68
+ assert_equal [@song.title], song[:song_titles]
69
+ end
70
+
71
+ test "/api/remove" do
72
+ post "/api/remove"
73
+ resp = parse_json(last_response.body.strip)
74
+ assert resp[:error].include?("hasn't been implemented")
75
+ end
76
+
77
+ test "/api/search artist" do
78
+ get "/api/search", { :q => @artist.name,
79
+ :facet => 'artist' }
80
+ resp = parse_json(last_response.body.strip)
81
+ assert resp[:song_titles].include?(@song.title)
82
+ end
83
+
84
+ test "/api/search song" do
85
+ get "/api/search", { :q => @song.title,
86
+ :facet => 'song' }
87
+ resp = parse_json(last_response.body.strip)
88
+ assert resp[:song_titles].include?(@song.title)
89
+ end
90
+
91
+ test "/api/user/add_alias" do
92
+ post "/api/user/add_alias", { :login => @user.login, :alias => 'zach' }
93
+ resp = parse_json(last_response.body.strip)
94
+ assert 'true', resp[:success]
95
+ assert_equal 'zach', User.first.alias
96
+ end
97
+
98
+ test "/api/import" do
99
+ Library.stubs(:import_songs).returns('true')
100
+ post "/api/import"
101
+ resp = parse_json(last_response.body.strip)
102
+ assert_equal 'true', resp[:success]
103
+ end
104
+
105
+ test "/api/volume" do
106
+ Play::Client.expects(:volume).with(3).returns(true)
107
+ post "/api/volume", {:level => '3'}
108
+ resp = parse_json(last_response.body.strip)
109
+ assert_equal 'true', resp[:success]
110
+ end
111
+
112
+ test "/api/pause" do
113
+ Play::Client.expects(:pause).returns(true)
114
+ post "/api/pause"
115
+ resp = parse_json(last_response.body.strip)
116
+ assert_equal 'true', resp[:success]
117
+ end
118
+ end