spotify_rec 1.1 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rec.rb CHANGED
@@ -1,74 +1,84 @@
1
- class Rec
1
+ # frozen_string_literal: true
2
2
 
3
+ class Rec
3
4
  def initialize(user)
4
5
  @user_list = user.mylist
5
6
  @user = user
6
7
  @tracks = []
7
8
  @artists = []
8
9
  @genres = []
10
+ @prompt = TTY::Prompt.new
9
11
  end
10
12
 
13
+ # Prompts user to choose how many suggestions to generate
14
+ def amount_of_suggestions
15
+ system('clear')
16
+ puts '》 RECOMMENDATIONS 《'
17
+ amount = @prompt.ask('How many recommendations would you like to generate?'.colorize(:light_green)) do |q|
18
+ q.in '1-10'
19
+ q.messages[:range?] = 'Number must be between 1 and 10'
20
+ end
21
+ recommend(amount.to_i)
22
+ end
23
+
24
+ # Prompts user to select which recommendations to add to their playlist
25
+ def recommend(num)
26
+ system('clear')
27
+ recommendations = recommendations_generate(num)
28
+ cleaned_recs = recommendations.tracks.map { |t| "#{t.name} by #{t.artists[0].name}" }
29
+ puts '》 RECOMMENDATIONS 《'.colorize(:light_green)
30
+ puts 'Select the recommendations you want to add to your playlist!'
31
+ selections = @prompt.multi_select('Hit enter with none selected to skip.', cleaned_recs)
32
+ clean_recommendations(selections)
33
+ end
34
+
35
+ # Sorts list items into arrays to be used in generating recommendations
11
36
  def sort_my_list
12
37
  @tracks.clear
13
38
  @artists.clear
14
39
  @genres.clear
15
40
  @user_list.each do |item|
16
- @tracks << item["id"] if item["type"] == "track"
17
- @artists << item["id"] if item["type"] == "artist"
18
- @genres << item["name"].downcase if item["type"] == "genre"
41
+ @tracks << item['id'] if item['type'] == 'track'
42
+ @artists << item['id'] if item['type'] == 'artist'
43
+ @genres << item['name'].downcase if item['type'] == 'genre'
19
44
  end
20
45
  end
21
46
 
22
- def update_file
23
- updated_data = Login.load_data.each { |user| user["playlist"] = @user.playlist if user["id"] == @user.uid.to_s }
24
- File.open(userdata,"w") do |f|
25
- f.puts JSON.pretty_generate(updated_data)
26
- end
27
- puts "Sweet! Your list has been updated!".colorize(:light_green)
28
- $prompt.keypress("Press any key to return to the previous menu..")
29
- menu = Menu.new(@user)
30
- menu.menu_router
47
+ # Generates recommendations with RSpotify
48
+ def recommendations_generate(num)
49
+ sort_my_list
50
+ RSpotify::Recommendations.generate(limit: num, seed_artists: @artists, seed_genres: @genres, seed_tracks: @tracks)
31
51
  end
32
52
 
53
+ # Searches again for song selections to get the track object rather than just the name and artist
33
54
  def clean_recommendations(selections)
34
55
  selections.each do |track|
35
- details = track.split(" by ")
56
+ details = track.split(' by ')
36
57
  song = RSpotify::Track.search("#{details[0]} #{details[1]}", limit: 1).first
37
- song_details = {
38
- "name" => song.name,
39
- "id" => song.id,
40
- "artist" => song.artists[0].name }
41
- @user.playlist << song_details
58
+ song_details(song)
42
59
  end
43
60
  update_file
44
61
  end
45
62
 
46
- def recommend(num)
47
- system("clear")
48
- sort_my_list
49
- recommendations = RSpotify::Recommendations.generate(limit: num, seed_artists: @artists, seed_genres: @genres, seed_tracks: @tracks)
50
- cleaned_recs = recommendations.tracks.map { |t| "#{t.name} by #{t.artists[0].name}" }
51
- puts "》 RECOMMENDATIONS 《".colorize(:light_green)
52
- puts "Select the recommendations you want to add to your playlist!"
53
- selections = $prompt.multi_select("Hit enter with none selected to skip.", cleaned_recs)
54
- clean_recommendations(selections)
63
+ # Pulls song details from track and stores in a hash. Pushes to user playlist array
64
+ def song_details(song)
65
+ song_details = {
66
+ 'name' => song.name,
67
+ 'id' => song.id,
68
+ 'artist' => song.artists[0].name
69
+ }
70
+ @user.playlist << song_details
55
71
  end
56
72
 
57
- def amount_of_suggestions
58
- system("clear")
59
- if @user_list.length <= 0
60
- puts "Uh oh! You don't have any items in your list yet, so we can't generate any recommendations. Please add some before doing this!".colorize(:light_red)
61
- $prompt.keypress("Press any key to return to the previous menu..")
62
- menu = Menu.new(@user)
63
- menu.display_menu
64
- end
65
- puts "》 RECOMMENDATIONS 《"
66
- amount = $prompt.ask("How many recommendations would you like to generate?".colorize(:light_green)) do |q|
67
- q.in '1-10'
68
- q.messages[:range?] = "Number must be between 1 and 10"
73
+ # Updates file with current user playlist
74
+ def update_file
75
+ updated_data = Login.load_data.each { |user| user['playlist'] = @user.playlist if user['id'] == @user.uid.to_s }
76
+ File.open(userdata, 'w') do |f|
77
+ f.puts JSON.pretty_generate(updated_data)
69
78
  end
70
- recommend(amount.to_i)
79
+ puts 'Sweet! Your list has been updated!'.colorize(:light_green)
80
+ @prompt.keypress('Press any key to return to the previous menu..')
81
+ menu = Menu.new(@user)
82
+ menu.menu_router
71
83
  end
72
-
73
-
74
- end
84
+ end
@@ -0,0 +1,24 @@
1
+ require 'rspotify'
2
+ require_relative '../user'
3
+
4
+ RSpotify.authenticate('712ff89a218a4e6dbe1f169e06f949b9', 'e9e0517f405b4a01a1be8823126459b7')
5
+
6
+ describe 'Recommendations' do
7
+ it 'should generate a list of recommendations' do
8
+ genre = 'pop'
9
+ recommendations = RSpotify::Recommendations.generate(limit: 5, seed_genres: [genre])
10
+ expect(recommendations.tracks.length).to eq(5)
11
+ end
12
+
13
+ it 'should take the first recommendation and add it to the user playlist' do
14
+ name = 'user'
15
+ password = 'password123'
16
+ uid = '12345'
17
+ user = User.new(name, password, uid)
18
+ genre = 'pop'
19
+ recommendations = RSpotify::Recommendations.generate(limit: 5, seed_genres: [genre])
20
+ track = recommendations.tracks.first
21
+ user.playlist << track
22
+ expect(user.playlist.length).to eq(1)
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../user'
4
+ require 'json'
5
+ require 'tty-prompt'
6
+
7
+ describe 'User' do
8
+ it 'should create a user with a name, password and user id' do
9
+ name = 'user'
10
+ password = 'password123'
11
+ uid = '12345'
12
+ user = User.new(name, password, uid)
13
+ expect(user.username).to eq('user')
14
+ expect(user.password).to eq('password123')
15
+ expect(user.uid).to eq('12345')
16
+ end
17
+
18
+ it 'should create a user and add a track to the users MyList' do
19
+ name = 'user'
20
+ password = 'password123'
21
+ uid = '12345'
22
+ user = User.new(name, password, uid)
23
+ song = {
24
+ 'name': 'Gyalchester',
25
+ 'artist': 'Drake',
26
+ 'id': '6UjfByV1lDLW0SOVQA4NAi',
27
+ 'type': 'track'
28
+ }
29
+ user.mylist << song
30
+ expect(user.mylist.first[:name]).to eq('Gyalchester')
31
+ expect(user.mylist.first[:artist]).to eq('Drake')
32
+ expect(user.mylist.first[:id]).to eq('6UjfByV1lDLW0SOVQA4NAi')
33
+ end
34
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Contains methods to display tutorial screens
4
+ module Tutorial
5
+ @prompt = TTY::Prompt.new
6
+
7
+ def start
8
+ system('clear')
9
+ puts '》 WELCOME TO SPOTIFY REC 《'.colorize(:light_green)
10
+ puts 'This tutorial will walk you through the basics to using the app.'
11
+ puts "There are 3 main areas that you'll need to understand:"
12
+ puts '- My List'
13
+ puts '- Recommendations'
14
+ puts '- Playlist'
15
+ puts
16
+ @prompt.keypress('Press any key to continue..')
17
+ my_list
18
+ end
19
+
20
+ def my_list
21
+ system('clear')
22
+ puts '》 MY LIST 《'.colorize(:light_green)
23
+ puts 'My List is the base that your recommendations are generated from. It can consist of'
24
+ puts "up to 5 of any 'items'. An item is either a track, artist or genre. You can add and remove"
25
+ puts 'items from my list, so make sure to change them up regularly to get a range of recommendations!'
26
+ puts "Searching for an item will return the top 5 results for your keywords, so if yours doesn't show"
27
+ puts 'up, try searching again with a more specific query!'
28
+ puts
29
+ @prompt.keypress('Press any key to continue..')
30
+ recommendations
31
+ end
32
+
33
+ def recommendations
34
+ system('clear')
35
+ puts '》 RECOMMENDATIONS 《'.colorize(:light_green)
36
+ puts 'As mentioned on the previous screen, recommendations are tracks, and are generated based on the'
37
+ puts "items in your list. You can select the amount you'd like to generate, and select any number of"
38
+ puts 'the recommendations to store in your playlist. Recommendations are capped at 10 per generate,'
39
+ puts 'but you can repeat the generate step as many times as you would like.'
40
+ puts
41
+ @prompt.keypress('Press any key to continue..')
42
+ playlist
43
+ end
44
+
45
+ def playlist
46
+ system('clear')
47
+ puts '》 PLAYLIST 《'.colorize(:light_green)
48
+ puts "Your playlist stores all of the recommendations you've chosen, but you can also manually add and"
49
+ puts "remove songs as well. This can all be done from the playlist menu. At any point you'd like to look"
50
+ puts 'at your playlist outside of Spotify Rec, you can export the contents to a file on your desktop.'
51
+ puts 'This file includes a link to each song on Spotify, so you can easily go and start listening!'
52
+ puts
53
+ @prompt.keypress('Press any key to return to finish..')
54
+ exit
55
+ end
56
+ end
@@ -1,69 +1,93 @@
1
- class User
2
-
3
- attr_reader :username, :password, :uid
4
- attr_accessor :playlist, :mylist
5
-
6
- def initialize(username, password, uid, playlist=[], mylist=[])
7
- @username = username
8
- @password = password
9
- @playlist = playlist
10
- @uid = uid
11
- @mylist = mylist
12
- end
13
-
14
- def details
15
- puts "Username: #{@username.colorize(:light_green)}"
16
- puts "Password: #{@password.colorize(:light_green)}"
17
- puts "User ID: #{@uid.to_s.colorize(:light_green)}"
18
- $prompt.keypress("Press any key to continue..")
19
- menu = Menu.new(Login::user)
20
- menu.account_details
21
- end
22
-
23
- def change_username(new_name)
24
- updated_data = Login.load_data.each { |user| user["username"] = new_name if user["id"] == Login::user.uid.to_s }
25
- File.open((Login::userdata),"w") do |f|
26
- f.puts JSON.pretty_generate(updated_data)
27
- end
28
- @username = new_name
29
- puts "Success! Your new username is #{Login::user.username}".colorize(:light_green)
30
- $prompt.keypress("Press any key to continue..")
31
- menu = Menu.new(Login::user)
32
- menu.account_details
33
- end
34
-
35
- def change_password(new_password)
36
- updated_data = Login.load_data.each { |user| user["password"] = new_password if user["id"] == Login::user.uid.to_s }
37
- File.open((Login::userdata),"w") do |f|
38
- f.puts JSON.pretty_generate(updated_data)
39
- end
40
- @password = new_password
41
- puts "Success! Your password has been changed.".colorize(:light_green)
42
- $prompt.keypress("Press any key to continue..")
43
- menu = Menu.new(Login::user)
44
- menu.account_details
45
- end
46
-
47
- def delete_from_file
48
- updated_data = []
49
- Login.load_data.each { |user| updated_data << user unless user["id"] == Login::user.uid.to_s }
50
- File.open((Login::userdata),"w") do |f|
51
- f.puts JSON.pretty_generate(updated_data)
52
- end
53
- puts "Your account has been deleted. The program will now exit.".colorize(:light_red)
54
- $prompt.keypress("Press any key to continue..")
55
- exit
56
- end
57
-
58
-
59
- def delete_account
60
- puts "Woah there! Deleting your account is serious business, and cannot be undone.".colorize(:light_red)
61
- selection = $prompt.yes?("Are you sure you want to delete your account?").colorize(:light_red)
62
- unless selection
63
- menu = Menu.new(Login::user)
64
- else
65
- delete_from_file
66
- end
67
- end
68
-
69
- end
1
+ # frozen_string_literal: true
2
+
3
+ # An instance of User should be made for everyone who logs in or signs up
4
+ class User
5
+ attr_reader :username, :password, :uid
6
+ attr_accessor :playlist, :mylist
7
+
8
+ def initialize(username, password, uid, playlist = [], mylist = [])
9
+ @username = username
10
+ @password = password
11
+ @playlist = playlist
12
+ @uid = uid
13
+ @mylist = mylist
14
+ @prompt = TTY::Prompt.new
15
+ end
16
+
17
+ # Prints user details
18
+ def details
19
+ puts "Username: #{@username.colorize(:light_green)}"
20
+ puts "Password: #{@password.colorize(:light_green)}"
21
+ puts "User ID: #{@uid.to_s.colorize(:light_green)}"
22
+ @prompt.keypress('Press any key to continue..')
23
+ menu = Menu.new(self)
24
+ menu.account_details
25
+ end
26
+
27
+ # Change Username section
28
+ # Changes user name and routes back to menu
29
+ def change_username(new_name)
30
+ update_username(new_name)
31
+ @username = new_name
32
+ puts "Success! Your new username is #{@username}".colorize(:light_green)
33
+ @prompt.keypress('Press any key to continue..')
34
+ menu = Menu.new(self)
35
+ menu.account_details
36
+ end
37
+
38
+ # Updates username in file
39
+ def update_username(new_name)
40
+ updated_data = Login.load_data.each do |user|
41
+ user['username'] = new_name if user['id'] == @uid.to_s
42
+ end
43
+ File.open(Login.userdata, 'w') do |f|
44
+ f.puts JSON.pretty_generate(updated_data)
45
+ end
46
+ end
47
+
48
+ # Change password section
49
+ # Changes user name and routes back to menu
50
+ def change_password(new_password)
51
+ update_password(new_password)
52
+ @password = new_password
53
+ puts 'Success! Your password has been changed.'.colorize(:light_green)
54
+ @prompt.keypress('Press any key to continue..')
55
+ menu = Menu.new(self)
56
+ menu.account_details
57
+ end
58
+
59
+ # Updates user password in file
60
+ def update_password(new_password)
61
+ updated_data = Login.load_data.each do |user|
62
+ user['password'] = new_password if user['id'] == Login.user.uid.to_s
63
+ end
64
+ File.open(Login.userdata, 'w') do |f|
65
+ f.puts JSON.pretty_generate(updated_data)
66
+ end
67
+ end
68
+
69
+ # Delete account section
70
+ #Prompts user to confirm they would like to delete account.
71
+ def delete_account
72
+ puts 'Woah there! Deleting your account is serious business, and cannot be undone.'.colorize(:light_red)
73
+ selection = @prompt.yes?('Are you sure you want to delete your account?'.colorize(:light_red))
74
+ if selection
75
+ delete_from_file
76
+ else
77
+ menu = Menu.new(Login.user)
78
+ menu.account_details
79
+ end
80
+ end
81
+
82
+ # Deletes user data from the userfile
83
+ def delete_from_file
84
+ updated_data = []
85
+ Login.load_data.each { |user| updated_data << user unless user['id'] == Login.user.uid.to_s }
86
+ File.open(Login.userdata, 'w') do |f|
87
+ f.puts JSON.pretty_generate(updated_data)
88
+ end
89
+ puts 'Your account has been deleted. The program will now exit.'.colorize(:light_red)
90
+ @prompt.keypress('Press any key to continue..')
91
+ exit
92
+ end
93
+ end
@@ -1,13 +1 @@
1
- [
2
- {
3
- "id": "1",
4
- "username": "benahale",
5
- "password": "Tsurani7",
6
- "playlist": [
7
-
8
- ],
9
- "mylist": [
10
-
11
- ]
12
- }
13
- ]
1
+ []
metadata CHANGED
@@ -1,15 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spotify_rec
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.1'
4
+ version: '1.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Ahale
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-28 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2020-10-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tty-prompt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: terminal-table
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: rspotify
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: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
13
69
  description:
14
70
  email:
15
71
  executables:
@@ -18,12 +74,15 @@ extensions: []
18
74
  extra_rdoc_files: []
19
75
  files:
20
76
  - bin/spotify_rec
77
+ - lib/error.rb
21
78
  - lib/login.rb
22
79
  - lib/menu.rb
23
80
  - lib/my_list.rb
24
81
  - lib/playlist.rb
25
82
  - lib/rec.rb
26
- - lib/run.rb
83
+ - lib/spec/rec_spec.rb
84
+ - lib/spec/user_spec.rb
85
+ - lib/tutorial.rb
27
86
  - lib/user.rb
28
87
  - public/users.json
29
88
  homepage:
@@ -38,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
38
97
  requirements:
39
98
  - - ">="
40
99
  - !ruby/object:Gem::Version
41
- version: '0'
100
+ version: '2.4'
42
101
  required_rubygems_version: !ruby/object:Gem::Requirement
43
102
  requirements:
44
103
  - - ">="