spotify_rec 1.1 → 1.6

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.
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
  - - ">="