spotify_rec 1.4 → 1.5
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 +4 -4
- data/bin/spotify_rec +2 -2
- data/lib/login.rb +13 -10
- data/lib/menu.rb +27 -1
- data/lib/my_list.rb +14 -5
- data/lib/playlist.rb +11 -6
- data/lib/rec.rb +7 -9
- data/lib/spec/rec_spec.rb +24 -0
- data/lib/spec/user_spec.rb +34 -0
- data/lib/user.rb +12 -8
- data/public/users.json +0 -47
- metadata +61 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e297d8af48b8d8d7ab6c0636518af40d7051e794ab637c725d544ecfa68679e
|
4
|
+
data.tar.gz: 2297ec4f7c3cfe5372eb30b6b5df7cd5fcf269e56857f9a014f9d9b378a6a8c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c84dcb222e6107e57ac132796adfc3e05c6562063cfbb2f94cba521c669d095b359f49f0c1653b6395a89bd9c24bc132861b6b09fe6a454d2680a56b6fda0b92
|
7
|
+
data.tar.gz: 88a353cd4e84c0c465e4406bc899acbabe80cde04aee16ac123d019c258cb9508690ac981956b138f7f6bca2a31850c23b709bf67c80323d936cdccf8bc130a9
|
data/bin/spotify_rec
CHANGED
@@ -25,7 +25,7 @@ include Tutorial
|
|
25
25
|
|
26
26
|
RSpotify.authenticate('712ff89a218a4e6dbe1f169e06f949b9', 'e9e0517f405b4a01a1be8823126459b7')
|
27
27
|
|
28
|
-
VERSION = 1.
|
28
|
+
VERSION = 1.5
|
29
29
|
|
30
30
|
ARGV << '--run' if ARGV.empty?
|
31
31
|
|
@@ -54,7 +54,7 @@ parser = OptionParser.new do |opts|
|
|
54
54
|
end
|
55
55
|
|
56
56
|
opts.on('-r', '--run', 'Run the application') do
|
57
|
-
Login.
|
57
|
+
Login.initial_login
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
data/lib/login.rb
CHANGED
@@ -7,22 +7,20 @@ module Login
|
|
7
7
|
@count = 0
|
8
8
|
|
9
9
|
# Login Logic Section
|
10
|
+
# Prompts the user to indicate whether they are a new or returning user
|
10
11
|
def initial_login
|
11
12
|
clear
|
12
13
|
ascii_art
|
13
14
|
puts '》 Welcome to the Spotify Recommendations App! 《'.colorize(:light_green)
|
14
15
|
puts
|
15
|
-
@prompt.select("Are you a new or returning user? \n", %w[New Returning])
|
16
|
-
|
17
|
-
|
18
|
-
def login
|
19
|
-
new_returning = initial_login.downcase
|
20
|
-
new_user if new_returning == 'new'
|
21
|
-
returning_user if new_returning == 'returning'
|
16
|
+
selection = @prompt.select("Are you a new or returning user? \n", %w[New Returning])
|
17
|
+
new_user if selection == 'New'
|
18
|
+
returning_user if selection == 'Returning'
|
22
19
|
end
|
23
20
|
|
24
21
|
# New user
|
25
|
-
|
22
|
+
# Prompts user to enter username for new account. Checks name for any special characters.
|
23
|
+
# Raises error if special character is included, and prompts the user again.
|
26
24
|
def new_user
|
27
25
|
system('clear')
|
28
26
|
File.open(userdata, 'w') { |f| f.write([].to_json) } unless File.exist?(userdata)
|
@@ -36,6 +34,7 @@ module Login
|
|
36
34
|
new_user
|
37
35
|
end
|
38
36
|
|
37
|
+
# Prompts for new password. Validates password so no special characters are included.
|
39
38
|
def new_user_password(username)
|
40
39
|
password = @prompt.mask('Password >')
|
41
40
|
raise RequirementError.new, 'Requirements not met' if password.match?(/[!@#$%^&*(),.?":{}|<>]/)
|
@@ -47,6 +46,7 @@ module Login
|
|
47
46
|
puts 'Password cannot contain special characters. Please try again!'.colorize(:light_red)
|
48
47
|
end
|
49
48
|
|
49
|
+
# Converts user details into a hash, ready to be stored in JSON file
|
50
50
|
def store_user
|
51
51
|
data = load_data
|
52
52
|
user_details = {
|
@@ -60,6 +60,7 @@ module Login
|
|
60
60
|
write_user(data)
|
61
61
|
end
|
62
62
|
|
63
|
+
# Writes the hash of user data to the JSON file
|
63
64
|
def write_user(data)
|
64
65
|
File.open(userdata, 'w') do |f|
|
65
66
|
f.puts JSON.pretty_generate(data)
|
@@ -70,7 +71,7 @@ module Login
|
|
70
71
|
end
|
71
72
|
|
72
73
|
# Returning user
|
73
|
-
|
74
|
+
# Prompts user to enter username and password
|
74
75
|
def returning_user
|
75
76
|
system('clear')
|
76
77
|
File.open(userdata, 'w') { |f| f.write([].to_json) } unless File.exist?(userdata)
|
@@ -80,11 +81,13 @@ module Login
|
|
80
81
|
authenticate(username, user_password)
|
81
82
|
end
|
82
83
|
|
84
|
+
# Loads data from JSON file
|
83
85
|
def authenticate(username, user_password)
|
84
86
|
data_arr = load_data
|
85
87
|
user_data(data_arr, username, user_password)
|
86
88
|
end
|
87
89
|
|
90
|
+
# Checks whether supplied username and password match any in the userfile
|
88
91
|
def user_data(data, username, user_password)
|
89
92
|
data.each do |hash|
|
90
93
|
next unless hash['username'].downcase == username.downcase
|
@@ -98,6 +101,7 @@ module Login
|
|
98
101
|
no_auth
|
99
102
|
end
|
100
103
|
|
104
|
+
# Method exits application if user is unsuccessful 3 times or more. Otherwise returns to login
|
101
105
|
def no_auth
|
102
106
|
puts 'Incorrect username or password!'.colorize(:red)
|
103
107
|
sleep(1)
|
@@ -109,7 +113,6 @@ module Login
|
|
109
113
|
end
|
110
114
|
|
111
115
|
# Helper Module Methods
|
112
|
-
|
113
116
|
def user
|
114
117
|
@user
|
115
118
|
end
|
data/lib/menu.rb
CHANGED
@@ -5,27 +5,48 @@ class Menu
|
|
5
5
|
@user = user
|
6
6
|
@prompt = TTY::Prompt.new
|
7
7
|
@playlist = Playlist.new(@user)
|
8
|
+
@list_length = @user.mylist.length
|
8
9
|
end
|
9
10
|
|
11
|
+
# Prompts the user to select an item on the menu
|
10
12
|
def display_menu
|
11
13
|
system('clear')
|
12
14
|
arr = ['My List', 'Recommendations', 'Playlist', 'Account Details', 'Exit']
|
13
15
|
@prompt.select("》 MAIN MENU 《\n".colorize(:light_green), arr)
|
14
16
|
end
|
15
17
|
|
18
|
+
# Begins to case the user selection from the menu
|
16
19
|
def menu_router
|
17
20
|
selection = display_menu
|
18
21
|
case selection
|
19
22
|
when 'My List'
|
20
23
|
my_list
|
21
24
|
when 'Recommendations'
|
25
|
+
recommendations_menu
|
26
|
+
else
|
27
|
+
case_menu(selection)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Opens the recommendations menu
|
32
|
+
def recommendations_menu
|
33
|
+
if @list_length.positive?
|
22
34
|
recommendation = Rec.new(@user)
|
23
35
|
recommendation.amount_of_suggestions
|
24
36
|
else
|
25
|
-
|
37
|
+
no_items
|
26
38
|
end
|
27
39
|
end
|
28
40
|
|
41
|
+
# Sends user back to menu if they don't have any items in 'MyList' yet
|
42
|
+
def no_items
|
43
|
+
puts "Uh oh! You don't have any items in your list yet, so we can't generate any".colorize(:light_red)
|
44
|
+
puts 'recommendations. Please add some before doing this!'.colorize(:light_red)
|
45
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
46
|
+
display_menu
|
47
|
+
end
|
48
|
+
|
49
|
+
# Continues to case the menu selection and route the user
|
29
50
|
def case_menu(selection)
|
30
51
|
case selection
|
31
52
|
when 'Playlist'
|
@@ -37,6 +58,7 @@ class Menu
|
|
37
58
|
end
|
38
59
|
end
|
39
60
|
|
61
|
+
# Shows the MyList menu
|
40
62
|
def my_list
|
41
63
|
system('clear')
|
42
64
|
selection = @prompt.select("》 MY LIST 《\n".colorize(:light_green), %w[Display Add Remove Back])
|
@@ -44,6 +66,7 @@ class Menu
|
|
44
66
|
case_my_list(selection, mylist)
|
45
67
|
end
|
46
68
|
|
69
|
+
# Cases the selection from the MyList menu and routes to the required method
|
47
70
|
def case_my_list(selection, mylist)
|
48
71
|
case selection
|
49
72
|
when 'Display'
|
@@ -57,12 +80,14 @@ class Menu
|
|
57
80
|
end
|
58
81
|
end
|
59
82
|
|
83
|
+
# Prompts the user to select from the Account details menu
|
60
84
|
def account_details_select
|
61
85
|
system('clear')
|
62
86
|
arr = ['View Details', 'Change Username', 'Change Password', 'Delete Account', 'Back']
|
63
87
|
@prompt.select('》 ACCOUNT DETAILS 《\n'.colorize(:light_green), arr)
|
64
88
|
end
|
65
89
|
|
90
|
+
# Cases the account details menu and routes the user
|
66
91
|
def account_details
|
67
92
|
selection = account_details_select
|
68
93
|
case selection
|
@@ -76,6 +101,7 @@ class Menu
|
|
76
101
|
end
|
77
102
|
end
|
78
103
|
|
104
|
+
# Continues to case the account details menu and route the user
|
79
105
|
def case_account_details(selection)
|
80
106
|
case selection
|
81
107
|
when 'Change Password'
|
data/lib/my_list.rb
CHANGED
@@ -9,7 +9,7 @@ class MyList
|
|
9
9
|
end
|
10
10
|
|
11
11
|
# Display MyList
|
12
|
-
|
12
|
+
# Displays items in MyList. Raises error if no items in list
|
13
13
|
def list
|
14
14
|
raise MyListEmpty.new, 'List must not be empty' if @mylist.empty?
|
15
15
|
|
@@ -20,6 +20,7 @@ class MyList
|
|
20
20
|
empty_list
|
21
21
|
end
|
22
22
|
|
23
|
+
# Generates the list in table view and prints it to the screen
|
23
24
|
def list_table
|
24
25
|
rows = @mylist.map do |hash|
|
25
26
|
if hash['type'] == 'track' || hash['type'] == 'album'
|
@@ -32,6 +33,7 @@ class MyList
|
|
32
33
|
puts table
|
33
34
|
end
|
34
35
|
|
36
|
+
# Tells the user they have no items in their list, and returns to menu
|
35
37
|
def empty_list
|
36
38
|
puts 'Oh no! Your list is currently empty!'.colorize(:light_red)
|
37
39
|
puts 'Add up to 5 items to your list. An item can be a song, artist or genre.'.colorize(:light_red)
|
@@ -41,13 +43,14 @@ class MyList
|
|
41
43
|
end
|
42
44
|
|
43
45
|
# Add to MyList
|
44
|
-
|
46
|
+
# Prompts the user to specify what type of item to add
|
45
47
|
def add_to_list
|
46
48
|
list_too_long if @mylist.length >= 5
|
47
49
|
selection = @prompt.select('Which type would you like to add?'.colorize(:light_green), %w[Song Artist Genre Back])
|
48
50
|
case_add_to_list(selection)
|
49
51
|
end
|
50
52
|
|
53
|
+
# Returns user to menu if the MyList has too many items
|
51
54
|
def list_too_long
|
52
55
|
puts "Oh no! You've reached maximum capacity in your list! You won't be able to add".colorize(:light_red)
|
53
56
|
puts 'another item until you remove an existing one.'.colorize(:light_red)
|
@@ -56,6 +59,7 @@ class MyList
|
|
56
59
|
@menu.my_list
|
57
60
|
end
|
58
61
|
|
62
|
+
# Cases the add to list selection and routes the user
|
59
63
|
def case_add_to_list(selection)
|
60
64
|
case selection
|
61
65
|
when 'Song'
|
@@ -69,6 +73,7 @@ class MyList
|
|
69
73
|
end
|
70
74
|
end
|
71
75
|
|
76
|
+
# Prompts user for song name and searches spotify. Prompts user to select a result
|
72
77
|
def search_song
|
73
78
|
song_query = @prompt.ask('What is the name of the song?'.colorize(:light_green))
|
74
79
|
tracks = RSpotify::Track.search(song_query, limit: 5)
|
@@ -80,7 +85,8 @@ class MyList
|
|
80
85
|
add_to_list if selection[0] == 'Back'
|
81
86
|
store_song(selection)
|
82
87
|
end
|
83
|
-
|
88
|
+
|
89
|
+
# Stores the song in a hash ready to be written to the file
|
84
90
|
def store_song(details)
|
85
91
|
track = RSpotify::Track.search("#{details[0]} #{details[1]}", limit: 1).first
|
86
92
|
song_details = {
|
@@ -93,6 +99,7 @@ class MyList
|
|
93
99
|
update_file
|
94
100
|
end
|
95
101
|
|
102
|
+
# Prompts user for artist name, searches for the artist and prompts user to select a result
|
96
103
|
def search_artist
|
97
104
|
artist_query = @prompt.ask('What is the name of the artist?'.colorize(:light_green))
|
98
105
|
artists = RSpotify::Artist.search(artist_query, limit: 5)
|
@@ -103,6 +110,7 @@ class MyList
|
|
103
110
|
store_artist(selection)
|
104
111
|
end
|
105
112
|
|
113
|
+
# Stores the artist details in a hash, ready to be written to userfile
|
106
114
|
def store_artist(details)
|
107
115
|
artist = RSpotify::Artist.search(details.to_s, limit: 1).first
|
108
116
|
artist_details = {
|
@@ -114,6 +122,7 @@ class MyList
|
|
114
122
|
update_file
|
115
123
|
end
|
116
124
|
|
125
|
+
# Prompts user to select genre from the list. Stores details in hash to be written to file
|
117
126
|
def store_genre
|
118
127
|
genres = RSpotify::Recommendations.available_genre_seeds
|
119
128
|
genre = @prompt.select('Which genre would you like to add to your list?', genres, filter: true)
|
@@ -126,7 +135,7 @@ class MyList
|
|
126
135
|
end
|
127
136
|
|
128
137
|
# Remove From MyList
|
129
|
-
|
138
|
+
# Prompts user to select item to remove from MyList. Removes item from mylist array
|
130
139
|
def remove_from_list
|
131
140
|
empty_list if @mylist.length <= 0
|
132
141
|
item_names = @mylist.map { |item| item['name'] }
|
@@ -140,7 +149,7 @@ class MyList
|
|
140
149
|
end
|
141
150
|
|
142
151
|
# Update userfile
|
143
|
-
|
152
|
+
# Writes the user MyList to the userfile
|
144
153
|
def update_file
|
145
154
|
updated_data = Login.load_data.each { |user| user['mylist'] = @mylist if user['id'] == @user.uid.to_s }
|
146
155
|
File.open(userdata, 'w') do |f|
|
data/lib/playlist.rb
CHANGED
@@ -10,7 +10,7 @@ class Playlist
|
|
10
10
|
end
|
11
11
|
|
12
12
|
# Playlist Menu Section
|
13
|
-
|
13
|
+
# Prompts user to select an item from the menu
|
14
14
|
def menu
|
15
15
|
system('clear')
|
16
16
|
selection = @prompt.select('》 PLAYLIST 《', ['Display', 'Add', 'Remove', 'Export To File', 'Back'])
|
@@ -22,6 +22,7 @@ class Playlist
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
# Cases the user selection and routes the user
|
25
26
|
def case_menu(selection)
|
26
27
|
case selection
|
27
28
|
when 'Add'
|
@@ -33,6 +34,7 @@ class Playlist
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
37
|
+
# Continues to case the selection and route the user
|
36
38
|
def second_case_menu(selection)
|
37
39
|
case selection
|
38
40
|
when 'Export To File'
|
@@ -44,7 +46,7 @@ class Playlist
|
|
44
46
|
end
|
45
47
|
|
46
48
|
# View Playlist
|
47
|
-
|
49
|
+
# Generates table from user playlist and prints it to the screen
|
48
50
|
def list
|
49
51
|
puts '》 PLAYLIST 《'
|
50
52
|
empty if @playlist.empty?
|
@@ -55,6 +57,7 @@ class Playlist
|
|
55
57
|
menu
|
56
58
|
end
|
57
59
|
|
60
|
+
# Tells user if their playlist is empty and sends them back to the menu
|
58
61
|
def empty
|
59
62
|
puts 'Oh no! Your playlist is currently empty!'
|
60
63
|
puts 'You can add songs manually from the previous menu, or generate recommendations and add those!'
|
@@ -64,7 +67,7 @@ class Playlist
|
|
64
67
|
end
|
65
68
|
|
66
69
|
# Add to Playlist
|
67
|
-
|
70
|
+
# Prompts user to enter song name, searches for song and prompts user to select a result
|
68
71
|
def add
|
69
72
|
song_query = @prompt.ask('What is the name of the song?')
|
70
73
|
tracks = RSpotify::Track.search(song_query, limit: 5)
|
@@ -77,6 +80,7 @@ class Playlist
|
|
77
80
|
store(selection)
|
78
81
|
end
|
79
82
|
|
83
|
+
# Turns song details into a hash and adds to playlist array
|
80
84
|
def store(details)
|
81
85
|
track = RSpotify::Track.search("#{details[0]} #{details[1]}", limit: 1).first
|
82
86
|
song_details = {
|
@@ -89,7 +93,7 @@ class Playlist
|
|
89
93
|
end
|
90
94
|
|
91
95
|
# Remove from Playlist
|
92
|
-
|
96
|
+
# Prompts user to select item in playlist to remove and deleted from playlist array
|
93
97
|
def remove
|
94
98
|
empty if @playlist.length <= 0
|
95
99
|
item_names = @playlist.map { |item| "#{item['name']} by #{item['artist']}" }
|
@@ -103,7 +107,7 @@ class Playlist
|
|
103
107
|
end
|
104
108
|
|
105
109
|
# Update Playlist in file
|
106
|
-
|
110
|
+
# Loads userdata and updates playlist in file. Returns the user to the menu
|
107
111
|
def update_playlist
|
108
112
|
updated_data = Login.load_data.each { |user| user['playlist'] = @playlist if user['id'] == @user.uid.to_s }
|
109
113
|
File.open(Login.userdata, 'w') do |f|
|
@@ -115,7 +119,7 @@ class Playlist
|
|
115
119
|
end
|
116
120
|
|
117
121
|
# Export playlist to file
|
118
|
-
|
122
|
+
# Writes user playlist information to a markdown file
|
119
123
|
def export_to_file
|
120
124
|
path = File.join(File.dirname(File.dirname(File.absolute_path(__FILE__))))
|
121
125
|
File.open("#{path}/playlist.md", 'w') do |f|
|
@@ -128,6 +132,7 @@ class Playlist
|
|
128
132
|
copy_to_desktop(path)
|
129
133
|
end
|
130
134
|
|
135
|
+
# Copies markdown file to desktop for easy access
|
131
136
|
def copy_to_desktop(path)
|
132
137
|
system("cp #{path}/playlist.md ~/Desktop/playlist.md")
|
133
138
|
puts 'Exported playlist to your Desktop!'
|
data/lib/rec.rb
CHANGED
@@ -10,9 +10,9 @@ class Rec
|
|
10
10
|
@prompt = TTY::Prompt.new
|
11
11
|
end
|
12
12
|
|
13
|
+
# Prompts user to choose how many suggestions to generate
|
13
14
|
def amount_of_suggestions
|
14
15
|
system('clear')
|
15
|
-
too_many_items if @user_list.length > 5
|
16
16
|
puts '》 RECOMMENDATIONS 《'
|
17
17
|
amount = @prompt.ask('How many recommendations would you like to generate?'.colorize(:light_green)) do |q|
|
18
18
|
q.in '1-10'
|
@@ -21,14 +21,7 @@ class Rec
|
|
21
21
|
recommend(amount.to_i)
|
22
22
|
end
|
23
23
|
|
24
|
-
|
25
|
-
puts "Uh oh! You don't have any items in your list yet, so we can't generate any".colorize(:light_red)
|
26
|
-
puts 'recommendations. Please add some before doing this!'.colorize(:light_red)
|
27
|
-
@prompt.keypress('Press any key to return to the previous menu..')
|
28
|
-
menu = Menu.new(@user)
|
29
|
-
menu.display_menu
|
30
|
-
end
|
31
|
-
|
24
|
+
# Prompts user to select which recommendations to add to their playlist
|
32
25
|
def recommend(num)
|
33
26
|
system('clear')
|
34
27
|
recommendations = recommendations_generate(num)
|
@@ -39,6 +32,7 @@ class Rec
|
|
39
32
|
clean_recommendations(selections)
|
40
33
|
end
|
41
34
|
|
35
|
+
# Sorts list items into arrays to be used in generating recommendations
|
42
36
|
def sort_my_list
|
43
37
|
@tracks.clear
|
44
38
|
@artists.clear
|
@@ -50,11 +44,13 @@ class Rec
|
|
50
44
|
end
|
51
45
|
end
|
52
46
|
|
47
|
+
# Generates recommendations with RSpotify
|
53
48
|
def recommendations_generate(num)
|
54
49
|
sort_my_list
|
55
50
|
RSpotify::Recommendations.generate(limit: num, seed_artists: @artists, seed_genres: @genres, seed_tracks: @tracks)
|
56
51
|
end
|
57
52
|
|
53
|
+
# Searches again for song selections to get the track object rather than just the name and artist
|
58
54
|
def clean_recommendations(selections)
|
59
55
|
selections.each do |track|
|
60
56
|
details = track.split(' by ')
|
@@ -64,6 +60,7 @@ class Rec
|
|
64
60
|
update_file
|
65
61
|
end
|
66
62
|
|
63
|
+
# Pulls song details from track and stores in a hash. Pushes to user playlist array
|
67
64
|
def song_details(song)
|
68
65
|
song_details = {
|
69
66
|
'name' => song.name,
|
@@ -73,6 +70,7 @@ class Rec
|
|
73
70
|
@user.playlist << song_details
|
74
71
|
end
|
75
72
|
|
73
|
+
# Updates file with current user playlist
|
76
74
|
def update_file
|
77
75
|
updated_data = Login.load_data.each { |user| user['playlist'] = @user.playlist if user['id'] == @user.uid.to_s }
|
78
76
|
File.open(userdata, 'w') do |f|
|
@@ -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
|
data/lib/user.rb
CHANGED
@@ -14,29 +14,31 @@ class User
|
|
14
14
|
@prompt = TTY::Prompt.new
|
15
15
|
end
|
16
16
|
|
17
|
+
# Prints user details
|
17
18
|
def details
|
18
19
|
puts "Username: #{@username.colorize(:light_green)}"
|
19
20
|
puts "Password: #{@password.colorize(:light_green)}"
|
20
21
|
puts "User ID: #{@uid.to_s.colorize(:light_green)}"
|
21
22
|
@prompt.keypress('Press any key to continue..')
|
22
|
-
menu = Menu.new(
|
23
|
+
menu = Menu.new(self)
|
23
24
|
menu.account_details
|
24
25
|
end
|
25
26
|
|
26
27
|
# Change Username section
|
27
|
-
|
28
|
+
# Changes user name and routes back to menu
|
28
29
|
def change_username(new_name)
|
29
30
|
update_username(new_name)
|
30
31
|
@username = new_name
|
31
|
-
puts "Success! Your new username is #{
|
32
|
+
puts "Success! Your new username is #{@username}".colorize(:light_green)
|
32
33
|
@prompt.keypress('Press any key to continue..')
|
33
|
-
menu = Menu.new(
|
34
|
+
menu = Menu.new(self)
|
34
35
|
menu.account_details
|
35
36
|
end
|
36
37
|
|
38
|
+
# Updates username in file
|
37
39
|
def update_username(new_name)
|
38
40
|
updated_data = Login.load_data.each do |user|
|
39
|
-
user['username'] = new_name if user['id'] ==
|
41
|
+
user['username'] = new_name if user['id'] == @uid.to_s
|
40
42
|
end
|
41
43
|
File.open(Login.userdata, 'w') do |f|
|
42
44
|
f.puts JSON.pretty_generate(updated_data)
|
@@ -44,16 +46,17 @@ class User
|
|
44
46
|
end
|
45
47
|
|
46
48
|
# Change password section
|
47
|
-
|
49
|
+
# Changes user name and routes back to menu
|
48
50
|
def change_password(new_password)
|
49
51
|
update_password(new_password)
|
50
52
|
@password = new_password
|
51
53
|
puts 'Success! Your password has been changed.'.colorize(:light_green)
|
52
54
|
@prompt.keypress('Press any key to continue..')
|
53
|
-
menu = Menu.new(
|
55
|
+
menu = Menu.new(self)
|
54
56
|
menu.account_details
|
55
57
|
end
|
56
58
|
|
59
|
+
# Updates user password in file
|
57
60
|
def update_password(new_password)
|
58
61
|
updated_data = Login.load_data.each do |user|
|
59
62
|
user['password'] = new_password if user['id'] == Login.user.uid.to_s
|
@@ -64,7 +67,7 @@ class User
|
|
64
67
|
end
|
65
68
|
|
66
69
|
# Delete account section
|
67
|
-
|
70
|
+
#Prompts user to confirm they would like to delete account.
|
68
71
|
def delete_account
|
69
72
|
puts 'Woah there! Deleting your account is serious business, and cannot be undone.'.colorize(:light_red)
|
70
73
|
selection = @prompt.yes?('Are you sure you want to delete your account?'.colorize(:light_red))
|
@@ -76,6 +79,7 @@ class User
|
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
82
|
+
# Deletes user data from the userfile
|
79
83
|
def delete_from_file
|
80
84
|
updated_data = []
|
81
85
|
Login.load_data.each { |user| updated_data << user unless user['id'] == Login.user.uid.to_s }
|
data/public/users.json
CHANGED
@@ -1,47 +0,0 @@
|
|
1
|
-
[
|
2
|
-
{
|
3
|
-
"id": "1",
|
4
|
-
"username": "benahale",
|
5
|
-
"password": "password",
|
6
|
-
"playlist": [
|
7
|
-
{
|
8
|
-
"name": "44 More",
|
9
|
-
"id": "3e7Y6sfFlIdBMJhX7wpqVO",
|
10
|
-
"artist": "Logic"
|
11
|
-
},
|
12
|
-
{
|
13
|
-
"name": "Outnumbered",
|
14
|
-
"id": "6UjZ2Yx2g2a52XxiA8ONxZ",
|
15
|
-
"artist": "Dermot Kennedy"
|
16
|
-
}
|
17
|
-
],
|
18
|
-
"mylist": [
|
19
|
-
{
|
20
|
-
"name": "Dermot Kennedy",
|
21
|
-
"id": "5KNNVgR6LBIABRIomyCwKJ",
|
22
|
-
"type": "artist"
|
23
|
-
},
|
24
|
-
{
|
25
|
-
"name": "MIDDLE CHILD",
|
26
|
-
"artist": "J. Cole",
|
27
|
-
"id": "2JvzF1RMd7lE3KmFlsyZD8",
|
28
|
-
"type": "track"
|
29
|
-
},
|
30
|
-
{
|
31
|
-
"name": "Pop",
|
32
|
-
"type": "genre"
|
33
|
-
},
|
34
|
-
{
|
35
|
-
"name": "Fool's Gold - Acoustic",
|
36
|
-
"artist": "Passenger",
|
37
|
-
"id": "4JPB2Kjr3lkMJFz4sZnt6G",
|
38
|
-
"type": "track"
|
39
|
-
},
|
40
|
-
{
|
41
|
-
"name": "Drake",
|
42
|
-
"id": "3TVXtAsR1Inumwj472S9r4",
|
43
|
-
"type": "artist"
|
44
|
-
}
|
45
|
-
]
|
46
|
-
}
|
47
|
-
]
|
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.
|
4
|
+
version: '1.5'
|
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-
|
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:
|
@@ -24,6 +80,8 @@ files:
|
|
24
80
|
- lib/my_list.rb
|
25
81
|
- lib/playlist.rb
|
26
82
|
- lib/rec.rb
|
83
|
+
- lib/spec/rec_spec.rb
|
84
|
+
- lib/spec/user_spec.rb
|
27
85
|
- lib/tutorial.rb
|
28
86
|
- lib/user.rb
|
29
87
|
- public/users.json
|