ejaydj 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 05049a5b86d65ec05cd7f5a1ca0d3aebec538b94
4
+ data.tar.gz: 5470db550bcfbcea11dfc336b86539b3f9bddb93
5
+ SHA512:
6
+ metadata.gz: 9a0601efca20f9fade644fa5c1f186314b06c01430507ca5eb5974c4a394d01638b4d1bd5a21ccffff1047e24ee348791174868d495920ed93cdf2ffe7427576
7
+ data.tar.gz: 81d7b1b13d42f01f9edb07a2182fd77e918daa0cefa8a5f9b5f0aba8771a7aeb9741502862399a7cde13ebd6a0d518d0acc98aad216a6f8028223a203394205a
data/.editorconfig ADDED
@@ -0,0 +1,36 @@
1
+ # EditorConfig is awesome: http://EditorConfig.org
2
+ # top-most EditorConfig file
3
+ root = true
4
+
5
+ # Unix-style newlines with a newline ending every file
6
+ [*]
7
+ end_of_line = lf
8
+ insert_final_newline = true
9
+ indent_style = space
10
+ indent_size = 2
11
+
12
+ # 4 space indentation
13
+ [*.py]
14
+ indent_style = space
15
+ indent_size = 4
16
+
17
+ [*.js]
18
+ indent_style = space
19
+ indent_size = 4
20
+
21
+ [*.rb]
22
+ indent_style = space
23
+ indent_size = 2
24
+
25
+ [*.haml]
26
+ indent_style = space
27
+ indent_size = 2
28
+
29
+ [*.scss]
30
+ indent_style = space
31
+ indent_size = 4
32
+
33
+ # Indentation override for all JS under lib directory
34
+ [lib/**.js]
35
+ indent_style = space
36
+ indent_size = 2
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ejaydj.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ejay Canaria
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Ejaydj
2
+
3
+ [![Build Status](https://travis-ci.org/ejaypcanaria/ejaydj.svg)](https://travis-ci.org/ejaypcanaria/ejaydj)
4
+
5
+ A bot that tweets songs from your music playlists on Spotify. Implemented using Twitter and Spotify API, let your music be heard! This is where music really never stops.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'ejaydj'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install ejaydj
20
+
21
+ ## Configuration
22
+
23
+ ### Prerequisites
24
+ 1. [Twitter consumer and access token](https://developer.spotify.com/my-applications/#!/)
25
+ 2. [Spotify client id and secret](https://apps.twitter.com/)
26
+
27
+ ### Set the Spotify and Twitter credentials in your new TwitterBot DJ then add your playlists
28
+
29
+ ```ruby
30
+ dj = Ejaydj::Djs::TwitterBot.new do |config|
31
+ config.music_user_id = 'spotify_user_id'
32
+ config.music_client_id = 'spotify_client_id'
33
+ config.music_client_secret = 'spotify_client_secret'
34
+
35
+ config.twitter_consumer_key = 'twitter_consumer_key'
36
+ config.twitter_consumer_secret = 'twitter_consumer_secret'
37
+ config.twitter_access_token = 'twitter_access_token'
38
+ config.twitter_access_token_secret = 'twitter_access_token_secret'
39
+
40
+
41
+ config.morning_playlists = ["Morning Playlist 1", "Morning Playlist 2"]
42
+ config.noon_playlists = ["Noon Playlist 1", "Noon Playlist 2"]
43
+ config.night_playlists = ["Night Playlist 1", "Night Playlist 2"]
44
+ config.late_night_playlists = ["Late Night Playlist 1", "Late Night Playlist 2"]
45
+ end
46
+ ```
47
+
48
+ **NOTE: You need to provide at least 1 playlist for each time spot**
49
+
50
+ ## Tweeting Your Music
51
+ Given a `dj` object from the above configuration, tweeting your music is as simple as:
52
+ ```ruby
53
+ dj.tweet_me_a_song
54
+ ```
55
+
56
+ The tweet format will look like:
57
+ `NP: {song} by {artist} from {playlist} playlist: {playlist_url}`
58
+ Each songs is based on the provided time (default is current time). It will automatically lookup for tracks in the scheduled playlists.
59
+
60
+ ## Playlists Schedule
61
+ Playlists are group into four time spots as you have seen in the configuration earlier. These time spots are:
62
+
63
+ 1. Morning - 6:00AM - 11:59PM
64
+ 2. Noon - 12:00PM - 5:59PM
65
+ 3. Night - 6:00PM - 10:59PM
66
+ 4. Late Night - 11:PM - 5:59AM
67
+
68
+ By default, the current time used is `Time.now`. You can override it by passing a `time` parameter on the `tweet_me_a_song` method:
69
+
70
+ ```ruby
71
+ dj.tweet_me_a_song(time: Time.new(2014, 11, 20, 14, 0, 0))
72
+ ```
73
+
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it ( https://github.com/ejaypcanaria/ejaydj/fork )
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task default: :spec do
4
+ system 'rspec --color --format documentation'
5
+ end
data/ejaydj.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ejaydj/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ejaydj"
8
+ spec.version = Ejaydj::VERSION
9
+ spec.authors = ["Ejay Canaria"]
10
+ spec.email = ["ejaypcanaria@gmail.com"]
11
+ spec.summary = %q{A bot that tweets a song based on your spotify playlists}
12
+ spec.description = %q{A bot that tweets a song based on your spotify playlists}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "rest-client", "~> 1.7"
22
+ spec.add_runtime_dependency "json"
23
+ spec.add_runtime_dependency "twitter"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.6"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "pry"
29
+
30
+ end
data/lib/ejaydj.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'ejaydj/dj'
2
+ require 'ejaydj/playlist'
3
+ require 'ejaydj/track'
4
+
5
+ require 'ejaydj/djs/twitter_bot'
data/lib/ejaydj/dj.rb ADDED
@@ -0,0 +1,79 @@
1
+ require 'ejaydj/services/playlist_service'
2
+ require 'ejaydj/spotify/client'
3
+
4
+ module Ejaydj
5
+ class Dj
6
+ PLAYLIST_SCHEDULE = {
7
+ 600..1159 => :morning_playlists, # 6AM - 12PM
8
+ 1200..1759 => :noon_playlists, # 12PM - 5:59PM
9
+ 1800..2259 => :night_playlists, # 6PM - 10:59PM
10
+ 2300..2359 => :late_night_playlists, # 11PM - 11:59AM
11
+ 0..559 => :late_night_playlists # 12AM - 5:59AM
12
+ }
13
+
14
+ attr_accessor :music_client_id,
15
+ :music_client_secret,
16
+ :music_user_id,
17
+ :music_client,
18
+ :morning_playlists,
19
+ :noon_playlists,
20
+ :night_playlists,
21
+ :late_night_playlists
22
+
23
+
24
+ def initialize(attributes={})
25
+ instantiate_variables_from attributes
26
+ yield self if block_given?
27
+ end
28
+
29
+ def play_me_a_song(time: Time.now)
30
+ current_playlist(time).next_track
31
+ end
32
+
33
+ def playlists
34
+ @playlists ||= all_playlists
35
+ end
36
+
37
+ def reload!
38
+ @playlists = all_playlists
39
+ @playlists.each {|playlist| playlist.reload!}
40
+ end
41
+
42
+ private
43
+
44
+ def current_playlist(time)
45
+ playlist_name = scheduled_playlist(time.strftime('%k%M').to_i)
46
+ playlist = playlists.select do |playlist|
47
+ playlist.name == playlist_name
48
+ end.first
49
+ end
50
+
51
+ def scheduled_playlist(time)
52
+ scheduled_playlists = PLAYLIST_SCHEDULE.select do |schedule, value|
53
+ schedule.cover? time
54
+ end.values.first
55
+
56
+ send(scheduled_playlists).sample
57
+ end
58
+
59
+ def all_playlists
60
+ playlist_service.all
61
+ end
62
+
63
+ def playlist_service
64
+ @playlist_service ||= Services::PlaylistService.new(
65
+ music_client: music_client,
66
+ user_id: music_user_id)
67
+ end
68
+
69
+ def music_client
70
+ @music_client ||= Spotify::Client.new(
71
+ client_id: music_client_id,
72
+ client_secret: music_client_secret)
73
+ end
74
+
75
+ def instantiate_variables_from(attributes)
76
+ attributes.each {|key, val| instance_variable_set(:"@#{key}", val) }
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,36 @@
1
+ require 'twitter'
2
+
3
+ module Ejaydj
4
+ module Djs
5
+ class TwitterBot < Ejaydj::Dj
6
+ attr_accessor :twitter_consumer_key,
7
+ :twitter_consumer_secret,
8
+ :twitter_access_token,
9
+ :twitter_access_token_secret,
10
+ :twitter_client
11
+
12
+ def initialize(attributes={}, &block)
13
+ super(attributes, &block)
14
+ end
15
+
16
+ def tweet_me_a_song(time: Time.now)
17
+ song = play_me_a_song(time: time)
18
+ tweet = "NP: #{song.name} by #{song.artist} from #{song.playlist.name} playlist: #{song.playlist.url}"
19
+ twitter_client.update(tweet)
20
+
21
+ {message: tweet, song: song}
22
+ end
23
+
24
+ private
25
+
26
+ def twitter_client
27
+ @twitter_client ||= Twitter::REST::Client.new do |config|
28
+ config.consumer_key = @twitter_consumer_key
29
+ config.consumer_secret = @twitter_consumer_secret
30
+ config.access_token = @twitter_access_token
31
+ config.access_token_secret = @twitter_access_token_secret
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ require 'ejaydj/services/track_service'
2
+
3
+ module Ejaydj
4
+ class Playlist
5
+ attr_reader :id,
6
+ :user_id,
7
+ :name,
8
+ :url,
9
+ :number_of_tracks
10
+
11
+ def initialize(attributes={})
12
+ @id = attributes[:id]
13
+ @user_id = attributes[:user_id]
14
+ @name = attributes[:name]
15
+ @url = attributes[:url]
16
+ @number_of_tracks = attributes[:number_of_tracks]
17
+
18
+ @music_client = attributes[:music_client]
19
+ end
20
+
21
+ def next_track
22
+ reload! if tracks.empty?
23
+ track = tracks.pop
24
+ track.playlist = self
25
+ track
26
+ end
27
+
28
+ def tracks
29
+ @tracks ||= all_tracks
30
+ end
31
+
32
+ def reload!
33
+ @tracks = all_tracks
34
+ end
35
+
36
+ private
37
+
38
+ def all_tracks
39
+ track_service.all.shuffle
40
+ end
41
+
42
+ def track_service
43
+ @track_service ||= Services::TrackService.new(
44
+ music_client: @music_client,
45
+ user_id: @user_id,
46
+ playlist_id: @id)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ module Ejaydj
2
+ module Services
3
+ class PlaylistService
4
+
5
+ def initialize(music_client: nil, user_id: nil)
6
+ @music_client = music_client
7
+ @user_id = user_id
8
+ end
9
+
10
+ def all
11
+ response_items = @music_client.user_playlists(user_id: @user_id)
12
+
13
+ response_items.map do |playlist|
14
+ Playlist.new(
15
+ id: playlist["id"],
16
+ user_id: playlist["owner"]["id"],
17
+ name: playlist["name"],
18
+ url: playlist["external_urls"]["spotify"],
19
+ number_of_tracks: playlist["tracks"]["total"],
20
+
21
+ music_client: @music_client)
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ module Ejaydj
2
+ module Services
3
+ class TrackService
4
+ def initialize(music_client: nil, user_id: nil, playlist_id: nil)
5
+ @music_client = music_client
6
+ @user_id = user_id
7
+ @playlist_id = playlist_id
8
+ end
9
+
10
+ def all
11
+ response_items = @music_client.playlist_tracks(user_id: @user_id, playlist_id: @playlist_id)
12
+
13
+ response_items.map do |track|
14
+ Track.new(
15
+ id: track["track"]["id"],
16
+ name: track["track"]["name"],
17
+ album: track["track"]["album"]["name"],
18
+ artist: track["track"]["artists"][0]["name"],
19
+ duration_ms: track["track"]["duration_ms"]
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,68 @@
1
+ require 'rest_client'
2
+ require 'base64'
3
+ require 'json'
4
+
5
+ require 'pry'
6
+
7
+ module Ejaydj
8
+ module Spotify
9
+ class Client
10
+
11
+ API_URL = 'https://api.spotify.com'
12
+ ACCOUNT_API_URL = 'https://accounts.spotify.com'
13
+
14
+ def initialize(config={})
15
+ @rest_client = config[:rest_client] || RestClient
16
+ @client_id = config[:client_id]
17
+ @client_secret = config[:client_secret]
18
+ end
19
+
20
+ def user_playlists(user_id: nil)
21
+ url = "#{API_URL}/v1/users/#{user_id}/playlists?limit=50"
22
+ response = get_request(url)
23
+ fetch_items(response)
24
+ end
25
+
26
+ def playlist_tracks(user_id: nil, playlist_id: nil)
27
+ url = "#{API_URL}/v1/users/#{user_id}/playlists/#{playlist_id}/tracks"
28
+ response = get_request(url)
29
+ fetch_items(response)
30
+ end
31
+
32
+ private
33
+
34
+ def fetch_items(response)
35
+ response_items = response["items"]
36
+ next_url = response["next"]
37
+
38
+ while next_url do
39
+ response = get_request(next_url)
40
+ response_items += response["items"]
41
+
42
+ next_url = response["next"]
43
+ end
44
+
45
+ response_items
46
+ end
47
+
48
+ def get_request(url)
49
+ JSON.parse(@rest_client.get(url, headers))
50
+ end
51
+
52
+ def headers
53
+ {"Authorization" => "Bearer #{get_access_token}"}
54
+ end
55
+
56
+ def get_access_token
57
+ encoded_client_id_secret = Base64.strict_encode64("#{@client_id}:#{@client_secret}")
58
+ payload = {grant_type: 'client_credentials'}
59
+ headers = {"Authorization" => "Basic #{encoded_client_id_secret}"}
60
+
61
+ response = @rest_client.post("#{ACCOUNT_API_URL}/api/token", payload, headers)
62
+
63
+ return JSON.parse(response)["access_token"]
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,19 @@
1
+ module Ejaydj
2
+ class Track
3
+ attr_reader :name,
4
+ :album,
5
+ :artist,
6
+ :duration_ms
7
+
8
+ attr_accessor :playlist
9
+
10
+ def initialize(attributes={})
11
+ @id = attributes[:id]
12
+ @name = attributes[:name]
13
+ @album = attributes[:album]
14
+ @artist = attributes[:artist]
15
+ @playlist = attributes[:playlist]
16
+ @duration_ms = attributes[:duration_ms]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Ejaydj
2
+ VERSION = "0.0.1"
3
+ end
data/spec/dj_spec.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Ejaydj::Dj do
4
+
5
+ let(:dj) do
6
+ Ejaydj::Dj.new do |config|
7
+ config.music_user_id = 'user_1'
8
+ config.music_client_id = 'client_1'
9
+ config.music_client_secret = 'client_secret_1'
10
+ config.music_client = music_client
11
+ config.morning_playlists = ["Morning Playlist"]
12
+ config.noon_playlists = ["Noon Playlist"]
13
+ config.night_playlists = ["Night Playlist"]
14
+ config.late_night_playlists = ["Late Night Playlist"]
15
+ end
16
+ end
17
+
18
+ let(:playlist_items) do
19
+ [
20
+ {"name" => "Morning Playlist", "owner" => {"id" => 1}, "external_urls" => {"spotify" => "/playlist_morning"}, "tracks" => {"total" => 10}},
21
+ {"name" => "Noon Playlist", "owner" => {"id" => 2}, "external_urls" => {"spotify" => "/playlist_noon"}, "tracks" => {"total" => 10}},
22
+ {"name" => "Night Playlist", "owner" => {"id" => 3}, "external_urls" => {"spotify" => "/playlist_night"}, "tracks" => {"total" => 10}},
23
+ {"name" => "Late Night Playlist", "owner" => {"id" => 4}, "external_urls" => {"spotify" => "/playlist_late_night"}, "tracks" => {"total" => 10}}
24
+ ]
25
+ end
26
+
27
+ let(:track_items) do
28
+ [
29
+ {"track" => { "id" => 1,
30
+ "name" => "Track 1",
31
+ "album" => {"name" => "Album 1"},
32
+ "artists" => [{"name" => "Artist 1"}],
33
+ "playlist_id" => 1
34
+ }}
35
+ ]
36
+ end
37
+
38
+ let(:music_client) { double('MusicClient') }
39
+
40
+ before do
41
+ allow(music_client).to receive(:user_playlists).and_return(playlist_items)
42
+ allow(music_client).to receive(:playlist_tracks).and_return(track_items)
43
+ end
44
+
45
+ describe '#play_me_a_song' do
46
+ context "when played in the morning" do
47
+ it "plays the song from the morning playlists" do
48
+ song = dj.play_me_a_song(time: Time.new(2014, 11, 20, 6, 30, 0))
49
+ expect(dj.morning_playlists).to include(song.playlist.name)
50
+ end
51
+ end
52
+
53
+ context "when played in the noon" do
54
+ it "plays the song from the noon playlists" do
55
+ song = dj.play_me_a_song(time: Time.new(2014, 11, 20, 17, 45, 0))
56
+ expect(dj.noon_playlists).to include(song.playlist.name)
57
+ end
58
+ end
59
+
60
+ context "when played in night" do
61
+ it "plays the song from the night playlists" do
62
+ song = dj.play_me_a_song(time: Time.new(2014, 11, 20, 18, 0, 0))
63
+ expect(dj.night_playlists).to include(song.playlist.name)
64
+ end
65
+ end
66
+
67
+ context "when played in late night" do
68
+ it "plays the song from the late night playlists" do
69
+ song = dj.play_me_a_song(time: Time.new(2014, 11, 20, 23, 15, 0))
70
+ expect(dj.late_night_playlists).to include(song.playlist.name)
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#playlists' do
76
+ it "returns all the dj's playlists" do
77
+ expect(dj.playlists.count).to eq(playlist_items.count)
78
+ end
79
+ end
80
+
81
+ describe '#reload!' do
82
+ it "reloads the playlist" do
83
+ dj.playlists
84
+ playlist_items << {"name" => "Morning Playlist 2", "owner" => {"id" => 5}, "external_urls" => {"spotify" => "/playlist_morning_2"}, "tracks" => {"total" => 10}}
85
+ dj.reload!
86
+
87
+ expect(dj.playlists.count).to eq(playlist_items.count)
88
+ end
89
+
90
+ it "reloads the playlist's tracks" do
91
+ dj.playlists.first.tracks
92
+ track_items << { "track" => {"id" => 2,
93
+ "name" => "Track 2",
94
+ "album" => {"name" => "Album 2"},
95
+ "artists" => [{"name" => "Artist 2"}],
96
+ "playlist_id" => 2
97
+ }}
98
+ dj.reload!
99
+ expect(dj.playlists.first.tracks.count).to eq(track_items.count)
100
+ end
101
+ end
102
+
103
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Ejaydj::Djs::TwitterBot do
4
+
5
+ let(:music_client) { double('MusicClient') }
6
+ let(:twitter_client) { double('TwitterClient', update: true)}
7
+
8
+ let(:twitter_bot_dj) do
9
+ Ejaydj::Djs::TwitterBot.new do |config|
10
+ config.music_user_id = 'user_1'
11
+ config.music_client_id = 'client_1'
12
+ config.music_client_secret = 'client_secret_1'
13
+ config.music_client = music_client
14
+
15
+ config.twitter_consumer_key = 'consumer_key'
16
+ config.twitter_consumer_secret = 'consumer_secret'
17
+ config.twitter_access_token = 'access_token'
18
+ config.twitter_access_token_secret = 'token_secret'
19
+ config.twitter_client = twitter_client
20
+
21
+ config.morning_playlists = ["Morning Playlist"]
22
+ config.noon_playlists = ["Noon Playlist"]
23
+ config.night_playlists = ["Night Playlist"]
24
+ config.late_night_playlists = ["Late Night Playlist"]
25
+ end
26
+ end
27
+
28
+ let(:playlist_items) do
29
+ [
30
+ {"name" => "Morning Playlist", "owner" => {"id" => 1}, "external_urls" => {"spotify" => "/playlist_morning"}, "tracks" => {"total" => 10}}
31
+ ]
32
+ end
33
+
34
+ let(:track_items) do
35
+ [
36
+ {"track" => { "id" => 1,
37
+ "name" => "Track 1",
38
+ "album" => {"name" => "Album 1"},
39
+ "artists" => [{"name" => "Artist 1"}]
40
+ }}
41
+ ]
42
+ end
43
+
44
+ before do
45
+ allow(music_client).to receive(:user_playlists).and_return(playlist_items)
46
+ allow(music_client).to receive(:playlist_tracks).and_return(track_items)
47
+ end
48
+
49
+ describe '#tweet_me_a_song' do
50
+ it "tweets a song" do
51
+ tweet = twitter_bot_dj.tweet_me_a_song(time: Time.new(2014, 11, 20, 7, 0, 0))
52
+ song = tweet[:song]
53
+
54
+ expect(tweet[:message]).to eq("NP: #{song.name} by #{song.artist} from #{song.playlist.name} playlist: #{song.playlist.url}")
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Ejaydj::Playlist do
4
+
5
+ let(:music_client) { double('MusicClient') }
6
+ let(:playlist) do
7
+ Ejaydj::Playlist.new(
8
+ name: 'Playlist 1',
9
+ music_client: music_client)
10
+ end
11
+
12
+ let(:track_items) do
13
+ [
14
+ {"track" => { "id" => 1,
15
+ "name" => "Track 1",
16
+ "album" => {"name" => "Album 1"},
17
+ "artists" => [{"name" => "Artist 1"}],
18
+ "playlist_id" => 1
19
+ }}
20
+ ]
21
+ end
22
+
23
+ before do
24
+ allow(music_client).to receive(:playlist_tracks).and_return(track_items)
25
+ end
26
+
27
+ describe '#next_track' do
28
+ it "returns the next track in the playlist" do
29
+ track = playlist.next_track
30
+ expect(track.name).to eq(track_items.first["track"]["name"])
31
+ end
32
+
33
+ it "removes the returned track from the playlist" do
34
+ track = playlist.next_track
35
+ expect(playlist.tracks).to_not include(track)
36
+ end
37
+
38
+ context "when there's no track left" do
39
+ it "reloads the playlist and return a track" do
40
+ playlist.next_track
41
+
42
+ new_track = playlist.next_track
43
+ expect(new_track).to_not be_nil
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#tracks' do
49
+ it "returns all the playlist's tracks" do
50
+ expect(playlist.tracks.count).to eq(track_items.count)
51
+ end
52
+ end
53
+
54
+ describe '#reload!' do
55
+ it "reloads all the tracks" do
56
+ playlist.tracks
57
+ track_items << { "track" => {"id" => 2,
58
+ "name" => "Track 2",
59
+ "album" => {"name" => "Album 2"},
60
+ "artists" => [{"name" => "Artist 2"}],
61
+ "playlist_id" => 2
62
+ }}
63
+ playlist.reload!
64
+ expect(playlist.tracks.count).to eq(track_items.count)
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'pry'
3
+
4
+ RSpec.describe Ejaydj::Services::PlaylistService do
5
+
6
+ let(:music_client) { double('MusicClient') }
7
+ let(:playlist_service) do
8
+ Ejaydj::Services::PlaylistService.new(music_client: music_client, user_id: 1)
9
+ end
10
+
11
+ describe '#all' do
12
+ let(:response) do
13
+ [{"id" => 1, "owner" => {"id" => 1}, "name" => 'Playlist 1', "external_urls" => '/playlist1', "tracks" => {"total" => 10}},
14
+ {"id" => 2, "owner" => {"id" => 1}, "name" => 'Playlist 2', "external_urls" => '/playlist2', "tracks" => {"total" => 20}}]
15
+ end
16
+
17
+ before do
18
+ allow(music_client).to receive(:user_playlists).and_return(response)
19
+ end
20
+
21
+ it "returns a list of Playlists" do
22
+ playlists = playlist_service.all
23
+ expect(playlists.first.class).to eq Ejaydj::Playlist
24
+ end
25
+
26
+ it "returns all playlists of the user" do
27
+ playlists = playlist_service.all
28
+ expect(playlists.count).to eq response.count
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Ejaydj::Services::TrackService do
4
+
5
+ let(:music_client) { double('MusicClient') }
6
+ let(:track_service) do
7
+ Ejaydj::Services::TrackService.new(music_client: music_client, user_id: 1, playlist_id: 1)
8
+ end
9
+
10
+ describe '#all' do
11
+ let(:response) do
12
+ [{"track" => {"id" => 1,
13
+ "name" => "Track 1",
14
+ "album" => {"name" => "Album 1"},
15
+ "artists" => [{"name" => "Artist 1"}],
16
+ "playlist_id" => 1
17
+ }},
18
+
19
+ {"track" => {"id" => 2,
20
+ "name" => "Track 2",
21
+ "album" => {"name" => "Album 2"},
22
+ "artists" => [{"name" => "Artist 2"}],
23
+ "playlist_id" => 2
24
+ }}
25
+ ]
26
+ end
27
+
28
+ before do
29
+ allow(music_client).to receive(:playlist_tracks).and_return(response)
30
+ end
31
+
32
+ it "returns a list of Tracks" do
33
+ tracks = track_service.all
34
+ expect(tracks.first.class).to eq Ejaydj::Track
35
+ end
36
+
37
+ it "returns all the tracks of the playlist" do
38
+ tracks = track_service.all
39
+ expect(tracks.count).to eq response.count
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1 @@
1
+ require 'ejaydj'
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Ejaydj::Spotify::Client do
4
+
5
+ let(:rest_client) { double('RestClient') }
6
+ let(:spotify_client) do
7
+ Ejaydj::Spotify::Client.new(rest_client: rest_client,
8
+ client_id: 'client_1',
9
+ client_secret: 'client_secret_1')
10
+ end
11
+
12
+ before do
13
+ allow(rest_client).to receive(:get).and_return(response)
14
+ allow(rest_client).to receive(:post).with(
15
+ "#{Ejaydj::Spotify::Client::ACCOUNT_API_URL}/api/token", anything(), anything())
16
+ .and_return('{"access_token": "token_1"}')
17
+ end
18
+
19
+ describe '#user_playlists' do
20
+ let(:response) do
21
+ '{ "items": [
22
+ {"name": "Playlist 1"},
23
+ {"name": "Playlist 2"}
24
+ ]
25
+ }'
26
+ end
27
+
28
+ it "returns the given user playlists as an array of JSON" do
29
+ response_items = spotify_client.user_playlists(user_id: 1)
30
+ expect(response_items.first.class).to eq(Hash)
31
+ end
32
+ end
33
+
34
+ describe '#playlist_tracks' do
35
+ let(:response) do
36
+ '{ "items": [
37
+ {"name": "Track 1"},
38
+ {"name": "Track 2"}
39
+ ]
40
+ }'
41
+ end
42
+
43
+ it "returns the the given playlist's tracks as an array of JSON" do
44
+ response_items = spotify_client.playlist_tracks(user_id: 1, playlist_id: 1)
45
+ expect(response_items.first.class).to eq(Hash)
46
+ end
47
+ end
48
+
49
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ejaydj
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ejay Canaria
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: twitter
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A bot that tweets a song based on your spotify playlists
112
+ email:
113
+ - ejaypcanaria@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".editorconfig"
119
+ - ".gitignore"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - ejaydj.gemspec
126
+ - lib/ejaydj.rb
127
+ - lib/ejaydj/dj.rb
128
+ - lib/ejaydj/djs/twitter_bot.rb
129
+ - lib/ejaydj/playlist.rb
130
+ - lib/ejaydj/services/playlist_service.rb
131
+ - lib/ejaydj/services/track_service.rb
132
+ - lib/ejaydj/spotify/client.rb
133
+ - lib/ejaydj/track.rb
134
+ - lib/ejaydj/version.rb
135
+ - spec/dj_spec.rb
136
+ - spec/djs/twitter_bot_spec.rb
137
+ - spec/playlist_spec.rb
138
+ - spec/services/playlist_service_spec.rb
139
+ - spec/services/track_service_spec.rb
140
+ - spec/spec_helper.rb
141
+ - spec/spotify/client_spec.rb
142
+ homepage: ''
143
+ licenses:
144
+ - MIT
145
+ metadata: {}
146
+ post_install_message:
147
+ rdoc_options: []
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ requirements: []
161
+ rubyforge_project:
162
+ rubygems_version: 2.2.2
163
+ signing_key:
164
+ specification_version: 4
165
+ summary: A bot that tweets a song based on your spotify playlists
166
+ test_files:
167
+ - spec/dj_spec.rb
168
+ - spec/djs/twitter_bot_spec.rb
169
+ - spec/playlist_spec.rb
170
+ - spec/services/playlist_service_spec.rb
171
+ - spec/services/track_service_spec.rb
172
+ - spec/spec_helper.rb
173
+ - spec/spotify/client_spec.rb