ejaydj 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.
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