spotify_rec 1.1 → 1.2
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 +32 -25
- data/lib/login.rb +151 -117
- data/lib/menu.rb +90 -67
- data/lib/my_list.rb +153 -137
- data/lib/playlist.rb +98 -67
- data/lib/rec.rb +56 -44
- data/lib/user.rb +89 -69
- data/public/users.json +1 -13
- metadata +3 -4
- data/lib/run.rb +0 -47
data/lib/my_list.rb
CHANGED
@@ -1,137 +1,153 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
@
|
6
|
-
@
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def list
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
puts
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
@
|
135
|
-
|
136
|
-
|
137
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class MyList
|
4
|
+
def initialize(user)
|
5
|
+
@user = user
|
6
|
+
@mylist = user.mylist
|
7
|
+
@menu = Menu.new(@user)
|
8
|
+
@prompt = TTY::Prompt.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# Display MyList
|
12
|
+
|
13
|
+
def list
|
14
|
+
raise MyListEmpty.new, 'List must not be empty' if @mylist.empty?
|
15
|
+
|
16
|
+
list_table
|
17
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
18
|
+
@menu.my_list
|
19
|
+
rescue MyListEmpty
|
20
|
+
empty_list
|
21
|
+
end
|
22
|
+
|
23
|
+
def list_table
|
24
|
+
rows = @mylist.map do |hash|
|
25
|
+
if hash['type'] == 'track' || hash['type'] == 'album'
|
26
|
+
["#{hash['name']} by #{hash['artist']}", hash['type'].capitalize]
|
27
|
+
else
|
28
|
+
[hash['name'], hash['type'].capitalize]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
table = Terminal::Table.new headings: %w[Item Type], rows: rows
|
32
|
+
puts table
|
33
|
+
end
|
34
|
+
|
35
|
+
def empty_list
|
36
|
+
puts 'Oh no! Your list is currently empty!'.colorize(:light_red)
|
37
|
+
puts 'Add up to 5 items to your list. An item can be a song, artist or genre.'.colorize(:light_red)
|
38
|
+
puts
|
39
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
40
|
+
@menu.my_list
|
41
|
+
end
|
42
|
+
|
43
|
+
# Add to MyList
|
44
|
+
|
45
|
+
def add_to_list
|
46
|
+
list_too_long if @mylist.length >= 5
|
47
|
+
selection = @prompt.select('Which type would you like to add?'.colorize(:light_green), %w[Song Artist Genre Back])
|
48
|
+
case_add_to_list(selection)
|
49
|
+
end
|
50
|
+
|
51
|
+
def list_too_long
|
52
|
+
puts "Oh no! You've reached maximum capacity in your list! You won't be able to add".colorize(:light_red)
|
53
|
+
puts 'another item until you remove an existing one.'.colorize(:light_red)
|
54
|
+
puts "You can do this by heading back to the previous menu, and selecting 'Remove'".colorize(:light_red)
|
55
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
56
|
+
@menu.my_list
|
57
|
+
end
|
58
|
+
|
59
|
+
def case_add_to_list(selection)
|
60
|
+
case selection
|
61
|
+
when 'Song'
|
62
|
+
search_song
|
63
|
+
when 'Artist'
|
64
|
+
search_artist
|
65
|
+
when 'Genre'
|
66
|
+
store_genre
|
67
|
+
when 'Back'
|
68
|
+
@menu.my_list
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def search_song
|
73
|
+
song_query = @prompt.ask('What is the name of the song?'.colorize(:light_green))
|
74
|
+
tracks = RSpotify::Track.search(song_query, limit: 5)
|
75
|
+
cleaned_results = []
|
76
|
+
tracks.each { |t| cleaned_results << "#{t.name} by #{t.artists[0].name}" }
|
77
|
+
system('clear')
|
78
|
+
cleaned_results << 'Back'
|
79
|
+
selection = @prompt.select('Please select one of the search results:', cleaned_results).split(' by ')
|
80
|
+
add_to_list if selection[0] == 'Back'
|
81
|
+
store_song(selection)
|
82
|
+
end
|
83
|
+
|
84
|
+
def store_song(details)
|
85
|
+
track = RSpotify::Track.search("#{details[0]} #{details[1]}", limit: 1).first
|
86
|
+
song_details = {
|
87
|
+
'name' => track.name,
|
88
|
+
'artist' => track.artists[0].name,
|
89
|
+
'id' => track.id,
|
90
|
+
'type' => 'track'
|
91
|
+
}
|
92
|
+
@mylist << song_details
|
93
|
+
update_file
|
94
|
+
end
|
95
|
+
|
96
|
+
def search_artist
|
97
|
+
artist_query = @prompt.ask('What is the name of the artist?'.colorize(:light_green))
|
98
|
+
artists = RSpotify::Artist.search(artist_query, limit: 5)
|
99
|
+
cleaned_results = []
|
100
|
+
artists.each { |a| cleaned_results << a.name.to_s }
|
101
|
+
system('clear')
|
102
|
+
selection = @prompt.select('Please select one of the search results:', cleaned_results)
|
103
|
+
store_artist(selection)
|
104
|
+
end
|
105
|
+
|
106
|
+
def store_artist(details)
|
107
|
+
artist = RSpotify::Artist.search(details.to_s, limit: 1).first
|
108
|
+
artist_details = {
|
109
|
+
'name' => artist.name,
|
110
|
+
'id' => artist.id,
|
111
|
+
'type' => 'artist'
|
112
|
+
}
|
113
|
+
@mylist << artist_details
|
114
|
+
update_file
|
115
|
+
end
|
116
|
+
|
117
|
+
def store_genre
|
118
|
+
genres = RSpotify::Recommendations.available_genre_seeds
|
119
|
+
genre = @prompt.select('Which genre would you like to add to your list?', genres, filter: true)
|
120
|
+
genre_details = {
|
121
|
+
'name' => genre.capitalize,
|
122
|
+
'type' => 'genre'
|
123
|
+
}
|
124
|
+
@mylist << genre_details
|
125
|
+
update_file
|
126
|
+
end
|
127
|
+
|
128
|
+
# Remove From MyList
|
129
|
+
|
130
|
+
def remove_from_list
|
131
|
+
empty_list if @mylist.length <= 0
|
132
|
+
item_names = @mylist.map { |item| item['name'] }
|
133
|
+
item_names << 'Back'
|
134
|
+
selection = @prompt.select('Which item would you like to remove?'.colorize(:light_green), item_names)
|
135
|
+
@menu.my_list if selection == 'Back'
|
136
|
+
@mylist.each_with_index do |item, index|
|
137
|
+
@mylist.delete_at(index) if item['name'] == selection
|
138
|
+
end
|
139
|
+
update_file
|
140
|
+
end
|
141
|
+
|
142
|
+
# Update userfile
|
143
|
+
|
144
|
+
def update_file
|
145
|
+
updated_data = Login.load_data.each { |user| user['mylist'] = @mylist if user['id'] == @user.uid.to_s }
|
146
|
+
File.open(userdata, 'w') do |f|
|
147
|
+
f.puts JSON.pretty_generate(updated_data)
|
148
|
+
end
|
149
|
+
puts 'Sweet! Your list has been updated!'.colorize(:light_green)
|
150
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
151
|
+
@menu.my_list
|
152
|
+
end
|
153
|
+
end
|
data/lib/playlist.rb
CHANGED
@@ -1,112 +1,143 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
class Playlist
|
3
4
|
attr_reader :tracks
|
4
5
|
|
5
6
|
def initialize(user)
|
6
|
-
@playlist = user.playlist
|
7
7
|
@user = user
|
8
|
+
@playlist = user.playlist
|
9
|
+
@prompt = TTY::Prompt.new
|
8
10
|
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
# Playlist Menu Section
|
13
|
+
|
14
|
+
def menu
|
15
|
+
system('clear')
|
16
|
+
selection = @prompt.select('》 PLAYLIST 《', ['Display', 'Add', 'Remove', 'Export To File', 'Back'])
|
17
|
+
case selection
|
18
|
+
when 'Display'
|
19
|
+
list
|
20
|
+
else
|
21
|
+
case_menu(selection)
|
22
|
+
end
|
14
23
|
end
|
15
24
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
def case_menu(selection)
|
26
|
+
case selection
|
27
|
+
when 'Add'
|
28
|
+
add
|
29
|
+
when 'Remove'
|
30
|
+
remove
|
31
|
+
else
|
32
|
+
second_case_menu(selection)
|
24
33
|
end
|
25
|
-
|
34
|
+
end
|
35
|
+
|
36
|
+
def second_case_menu(selection)
|
37
|
+
case selection
|
38
|
+
when 'Export To File'
|
39
|
+
export_to_file
|
40
|
+
when 'Back'
|
41
|
+
menu = Menu.new(@user)
|
42
|
+
menu.menu_router
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# View Playlist
|
47
|
+
|
48
|
+
def list
|
49
|
+
puts '》 PLAYLIST 《'
|
50
|
+
empty if @playlist.empty?
|
51
|
+
rows = @playlist.map { |track| [track['name'], track['artist']] }
|
52
|
+
table = Terminal::Table.new headings: %w[Track Artist], rows: rows
|
53
|
+
puts table
|
54
|
+
keypress_playlist
|
55
|
+
menu
|
26
56
|
end
|
27
57
|
|
28
58
|
def empty
|
29
|
-
puts
|
30
|
-
puts
|
31
|
-
|
32
|
-
|
33
|
-
|
59
|
+
puts 'Oh no! Your playlist is currently empty!'
|
60
|
+
puts 'You can add songs manually from the previous menu, or generate recommendations and add those!'
|
61
|
+
puts
|
62
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
63
|
+
menu
|
34
64
|
end
|
35
65
|
|
66
|
+
# Add to Playlist
|
67
|
+
|
36
68
|
def add
|
37
|
-
song_query =
|
69
|
+
song_query = @prompt.ask('What is the name of the song?')
|
38
70
|
tracks = RSpotify::Track.search(song_query, limit: 5)
|
39
71
|
cleaned_results = []
|
40
72
|
tracks.each { |t| cleaned_results << "#{t.name} by #{t.artists[0].name}" }
|
41
|
-
system(
|
42
|
-
cleaned_results <<
|
43
|
-
selection =
|
44
|
-
menu if selection[0] ==
|
73
|
+
system('clear')
|
74
|
+
cleaned_results << 'Back'
|
75
|
+
selection = @prompt.select('Please select one of the search results:', cleaned_results).split(' by ')
|
76
|
+
menu if selection[0] == 'Back'
|
45
77
|
store(selection)
|
46
78
|
end
|
47
79
|
|
48
80
|
def store(details)
|
49
81
|
track = RSpotify::Track.search("#{details[0]} #{details[1]}", limit: 1).first
|
50
82
|
song_details = {
|
51
|
-
|
52
|
-
|
53
|
-
|
83
|
+
'name' => track.name,
|
84
|
+
'id' => track.id,
|
85
|
+
'artist' => track.artists[0].name
|
54
86
|
}
|
55
87
|
@playlist << song_details
|
56
88
|
update_playlist
|
57
89
|
end
|
58
90
|
|
91
|
+
# Remove from Playlist
|
92
|
+
|
93
|
+
def remove
|
94
|
+
empty if @playlist.length <= 0
|
95
|
+
item_names = @playlist.map { |item| "#{item['name']} by #{item['artist']}" }
|
96
|
+
item_names << 'Back'
|
97
|
+
selection = @prompt.select('Which track would you like to remove?', item_names).split(' by ')
|
98
|
+
menu if selection == 'Back'
|
99
|
+
@playlist.each_with_index do |item, index|
|
100
|
+
@user.playlist.delete_at(index) if item['name'] == selection[0]
|
101
|
+
end
|
102
|
+
update_playlist
|
103
|
+
end
|
104
|
+
|
105
|
+
# Update Playlist in file
|
106
|
+
|
59
107
|
def update_playlist
|
60
|
-
updated_data = Login.load_data.each { |user| user[
|
61
|
-
File.open(
|
108
|
+
updated_data = Login.load_data.each { |user| user['playlist'] = @playlist if user['id'] == @user.uid.to_s }
|
109
|
+
File.open(Login.userdata, 'w') do |f|
|
62
110
|
f.puts JSON.pretty_generate(updated_data)
|
63
111
|
end
|
64
|
-
puts
|
65
|
-
|
112
|
+
puts 'Sweet! Your playlist has been updated!'
|
113
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
66
114
|
menu
|
67
115
|
end
|
68
116
|
|
117
|
+
# Export playlist to file
|
118
|
+
|
69
119
|
def export_to_file
|
70
120
|
path = File.join(File.dirname(File.dirname(File.absolute_path(__FILE__))))
|
71
|
-
|
72
|
-
File.open(playlist_file,"w") do |f|
|
121
|
+
File.open("#{path}/playlist.md", 'w') do |f|
|
73
122
|
f.puts("# #{@user.username}'s Playlist")
|
74
|
-
@playlist.each
|
123
|
+
@playlist.each do |track|
|
124
|
+
link = "[Listen on Spotify](https://open.spotify.com/track/#{track['id']})"
|
125
|
+
f.puts("1. #{track['name']} by #{track['artist']} #{link}")
|
126
|
+
end
|
75
127
|
end
|
76
|
-
|
77
|
-
puts "Exported playlist to your Desktop!"
|
78
|
-
sleep(2)
|
79
|
-
system("clear")
|
128
|
+
copy_to_desktop(path)
|
80
129
|
end
|
81
130
|
|
82
|
-
def
|
83
|
-
|
131
|
+
def copy_to_desktop(path)
|
132
|
+
system("cp #{path}/playlist.md ~/Desktop/playlist.md")
|
133
|
+
puts 'Exported playlist to your Desktop!'
|
134
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
135
|
+
menu
|
84
136
|
end
|
85
137
|
|
86
|
-
|
87
|
-
system("clear")
|
88
|
-
selection = $prompt.select("》 PLAYLIST 《", (["Display", "Add", "Remove", "Export To File", "Back"]))
|
89
|
-
case selection
|
90
|
-
when "Display"
|
91
|
-
puts "》 PLAYLIST 《"
|
92
|
-
list
|
93
|
-
keypress_playlist
|
94
|
-
menu
|
95
|
-
when "Add"
|
96
|
-
add
|
97
|
-
keypress_playlist
|
98
|
-
menu
|
99
|
-
when "Remove"
|
100
|
-
remove
|
101
|
-
menu
|
102
|
-
when "Export To File"
|
103
|
-
export_to_file
|
104
|
-
keypress_playlist
|
105
|
-
menu
|
106
|
-
when "Back"
|
107
|
-
@menu = Menu.new(@user)
|
108
|
-
@menu.menu_router
|
109
|
-
end
|
110
|
-
end
|
138
|
+
# Helper method
|
111
139
|
|
112
|
-
|
140
|
+
def keypress_playlist
|
141
|
+
@prompt.keypress('Press any key to return to the previous menu..')
|
142
|
+
end
|
143
|
+
end
|