podcast-book-club 1.0.1 → 1.0.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/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/podcast_book_club/author.rb +3 -15
- data/lib/podcast_book_club/book.rb +16 -20
- data/lib/podcast_book_club/cli.rb +61 -21
- data/lib/podcast_book_club/episode.rb +0 -5
- data/lib/podcast_book_club/genre.rb +2 -22
- data/lib/podcast_book_club/scraper.rb +13 -23
- data/lib/podcast_book_club/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cd880410f24a83c490284a946f7f8e1ef7fb9f7bc48962b41fecfe0561c3a7f
|
4
|
+
data.tar.gz: 47d9f4fd6aef4c2b0a9d6426c81cc42724518ea702d2f2284c6b53e85f253f54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c76a17d8f75cca411508f83205a86a46d5b59c24615acab7d542fe5df5114ea3639a4bd7be009d5c9378a626e28a61f47d4f3b1498341e8ec841fe2340cbd503
|
7
|
+
data.tar.gz: a0fa7d5f5ea3071be1620cd56ce30a19b0e036db2b08f264a707dc19e73ef5018b21bff581a83086b11fe1898b3344c5f3bd9a2d27a3bf15c42eaca16376e8e4
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -11,9 +11,8 @@ class Author
|
|
11
11
|
def initialize(attributes)
|
12
12
|
@books = []
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
end
|
14
|
+
@name = attributes[:name]
|
15
|
+
self.add_book(attributes[:book])
|
17
16
|
|
18
17
|
end
|
19
18
|
|
@@ -21,7 +20,7 @@ class Author
|
|
21
20
|
@@all
|
22
21
|
end
|
23
22
|
|
24
|
-
def
|
23
|
+
def add_book(book)
|
25
24
|
@books << book unless @books.include?(book)
|
26
25
|
end
|
27
26
|
|
@@ -29,15 +28,4 @@ class Author
|
|
29
28
|
@books.map { |book| book.genre }.flatten.uniq
|
30
29
|
end
|
31
30
|
|
32
|
-
def output
|
33
|
-
|
34
|
-
puts "\n\n" + Rainbow("#{self.name}").bg(:black).yellow.bright + Rainbow(" (#{self.books.count})").silver
|
35
|
-
|
36
|
-
sorted_books = self.books.sort_by { |book| book.title}
|
37
|
-
sorted_books.each do |book|
|
38
|
-
puts " #{book.title}"
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
31
|
end
|
@@ -6,14 +6,25 @@ class Book
|
|
6
6
|
extend Sortable::ClassMethods
|
7
7
|
include Memorable::InstanceMethods
|
8
8
|
|
9
|
-
|
10
9
|
@@all = []
|
11
10
|
|
12
11
|
def initialize(attributes)
|
13
12
|
@episode = []
|
14
13
|
|
15
14
|
attributes.each do |k,v|
|
16
|
-
|
15
|
+
unless v == nil
|
16
|
+
|
17
|
+
if "#{k}" == "genre"
|
18
|
+
self.add_genre(v)
|
19
|
+
elsif "#{k}" == "episode"
|
20
|
+
self.add_episode(v)
|
21
|
+
elsif "#{k}" == "author"
|
22
|
+
self.add_author(v)
|
23
|
+
else
|
24
|
+
self.send("#{k}=", v)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
17
28
|
end
|
18
29
|
|
19
30
|
end
|
@@ -22,11 +33,11 @@ class Book
|
|
22
33
|
@@all
|
23
34
|
end
|
24
35
|
|
25
|
-
def
|
36
|
+
def add_episode(episode)
|
26
37
|
episode.add_book(self)
|
27
38
|
end
|
28
39
|
|
29
|
-
def
|
40
|
+
def add_author(authors)
|
30
41
|
@author ||= []
|
31
42
|
|
32
43
|
if authors.kind_of?(Array)
|
@@ -43,7 +54,7 @@ class Book
|
|
43
54
|
|
44
55
|
end
|
45
56
|
|
46
|
-
def
|
57
|
+
def add_genre(genre)
|
47
58
|
@genre ||= []
|
48
59
|
|
49
60
|
new_genre = Genre.find_or_create_by_name(genre)
|
@@ -54,19 +65,4 @@ class Book
|
|
54
65
|
self.all.select { |book| book.title.downcase.include?(keyword) || book.synopsis.downcase.include?(keyword) unless book.synopsis == nil }
|
55
66
|
end
|
56
67
|
|
57
|
-
def output(number)
|
58
|
-
authors = []
|
59
|
-
genres = []
|
60
|
-
|
61
|
-
self.author.each {|a| authors << a.name} unless self.author == [] || self.author == nil
|
62
|
-
self.genre.each {|g| genres << g.name} unless self.genre == [] || self.genre == nil
|
63
|
-
|
64
|
-
puts Rainbow("#{number} - #{self.title}").bg(:black).yellow.bright
|
65
|
-
puts Rainbow("Author(s): ").bg(:black).yellow.bright + authors.join(", ") unless authors == []
|
66
|
-
puts Rainbow("Genre: ").bg(:black).yellow.bright + genres.join(", ") unless genres == []
|
67
|
-
puts Rainbow("Synopsis: ").bg(:black).yellow.bright + "#{self.synopsis}" unless self.synopsis == ""
|
68
|
-
puts Rainbow("URL: ").bg(:black).yellow.bright + "#{self.url}\n\n"
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
68
|
end
|
@@ -3,7 +3,7 @@ class PodcastBookClub::CLI
|
|
3
3
|
def initialize
|
4
4
|
welcome_message
|
5
5
|
@today = Date.today
|
6
|
-
|
6
|
+
|
7
7
|
Whirly.start(spinner: "pencil", color: false, remove_after_stop: true, status: "Loading Episodes") do
|
8
8
|
@scraper = Scraper.new
|
9
9
|
end
|
@@ -37,7 +37,7 @@ class PodcastBookClub::CLI
|
|
37
37
|
when "3", "this month"
|
38
38
|
first_date = @today - @today.mday + 1
|
39
39
|
episodes = Episode.find_by_date(first_date, @today)
|
40
|
-
|
40
|
+
|
41
41
|
select_episodes(episodes)
|
42
42
|
|
43
43
|
when "4", "last month"
|
@@ -61,9 +61,9 @@ class PodcastBookClub::CLI
|
|
61
61
|
select_episodes(episodes)
|
62
62
|
|
63
63
|
when "7", "author"
|
64
|
-
|
65
|
-
if Book.count > 0
|
66
|
-
Author.sort_by_name.each { |author| author
|
64
|
+
|
65
|
+
if Book.count > 0
|
66
|
+
Author.sort_by_name.each { |author| output_author(author) }
|
67
67
|
else
|
68
68
|
no_books
|
69
69
|
end
|
@@ -71,7 +71,7 @@ class PodcastBookClub::CLI
|
|
71
71
|
when "8", "genre"
|
72
72
|
|
73
73
|
if Book.count > 0
|
74
|
-
Genre.sort_by_name.each { |genre| genre
|
74
|
+
Genre.sort_by_name.each { |genre| output_genre(genre) }
|
75
75
|
else
|
76
76
|
no_books
|
77
77
|
end
|
@@ -82,14 +82,14 @@ class PodcastBookClub::CLI
|
|
82
82
|
puts "\n\nEnter a keyword or phrase:"
|
83
83
|
keyword = gets.chomp.downcase
|
84
84
|
books = Book.find_by_keyword(keyword)
|
85
|
-
|
85
|
+
|
86
86
|
books.each_with_index do |book, i|
|
87
87
|
episodes = book.episode.map { |ep| ep.title}
|
88
|
-
|
89
|
-
book
|
88
|
+
|
89
|
+
output_book(book, i+1)
|
90
90
|
puts "From the episode(s): #{episodes.join(", ")}\n\n"
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
else
|
94
94
|
no_books
|
95
95
|
end
|
@@ -102,7 +102,7 @@ class PodcastBookClub::CLI
|
|
102
102
|
|
103
103
|
when "exit"
|
104
104
|
break
|
105
|
-
|
105
|
+
|
106
106
|
else
|
107
107
|
unexpected_input
|
108
108
|
|
@@ -115,14 +115,14 @@ class PodcastBookClub::CLI
|
|
115
115
|
|
116
116
|
def create_library(episodes)
|
117
117
|
episodes.each do |episode|
|
118
|
-
|
118
|
+
|
119
119
|
@scraper.build_books(episode) unless episode.books != []
|
120
120
|
|
121
121
|
puts "\n\nHere are the recommendations from \"#{episode.title}\":\n\n"
|
122
122
|
|
123
123
|
episode.books.each_with_index do |book, i|
|
124
|
-
book
|
125
|
-
end
|
124
|
+
output_book(book, i+1)
|
125
|
+
end
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
@@ -158,14 +158,14 @@ class PodcastBookClub::CLI
|
|
158
158
|
|
159
159
|
private
|
160
160
|
def welcome_message
|
161
|
-
puts Rainbow(" _ _ _ _ _ _
|
162
|
-
_ __ ___ __| | ___ __ _ ___| |_ | |__ ___ ___ | | __ ___| |_ _| |__
|
163
|
-
| '_ \\ / _ \\ / _` |/ __/ _` / __| __| | '_ \\ / _ \\ / _ \\| |/ / / __| | | | | '_ \\
|
161
|
+
puts Rainbow(" _ _ _ _ _ _
|
162
|
+
_ __ ___ __| | ___ __ _ ___| |_ | |__ ___ ___ | | __ ___| |_ _| |__
|
163
|
+
| '_ \\ / _ \\ / _` |/ __/ _` / __| __| | '_ \\ / _ \\ / _ \\| |/ / / __| | | | | '_ \\
|
164
164
|
| |_) | (_) | (_| | (_| (_| \\__ \\ |_ | |_) | (_) | (_) | < | (__| | |_| | |_) |
|
165
|
-
| .__/ \\___/ \\__,_|\\___\\__,_|___/\\__| |_.__/ \\___/ \\___/|_|\\_\\ \\___|_|\\__,_|_.__/
|
166
|
-
|_|
|
165
|
+
| .__/ \\___/ \\__,_|\\___\\__,_|___/\\__| |_.__/ \\___/ \\___/|_|\\_\\ \\___|_|\\__,_|_.__/
|
166
|
+
|_|
|
167
167
|
|
168
|
-
").
|
168
|
+
").yellow.bright
|
169
169
|
|
170
170
|
puts Rainbow(" The Ezra Klein Show ").black.bg(:yellow).bright + " brings you far-reaching conversations about hard problems, big ideas,"
|
171
171
|
puts "illuminating theories, and cutting-edge research.\n\n"
|
@@ -202,7 +202,7 @@ class PodcastBookClub::CLI
|
|
202
202
|
|
203
203
|
def puts_episodes(episodes)
|
204
204
|
puts "\n\nI have found " + Rainbow(episodes.count).bg(:black).yellow.bright + " episode(s).\n\n"
|
205
|
-
episodes.each.with_index { |episode, i| episode
|
205
|
+
episodes.each.with_index { |episode, i| output_episode(episode, i+1) }
|
206
206
|
end
|
207
207
|
|
208
208
|
def select_menu(episodes)
|
@@ -213,6 +213,46 @@ class PodcastBookClub::CLI
|
|
213
213
|
puts "\n\nWhat would you like to do?"
|
214
214
|
end
|
215
215
|
|
216
|
+
def output_book(book, number)
|
217
|
+
|
218
|
+
authors = book.author.map {|a| a.name} unless book.author == [] || book.author == nil
|
219
|
+
genres = book.genre.map {|g| g.name} unless book.genre == [] || book.genre == nil
|
220
|
+
|
221
|
+
puts Rainbow("#{number} - #{book.title}").bg(:black).yellow.bright
|
222
|
+
puts Rainbow("Author(s): ").bg(:black).yellow.bright + authors.join(", ") unless authors == []
|
223
|
+
puts Rainbow("Genre: ").bg(:black).yellow.bright + genres.join(", ") unless genres == []
|
224
|
+
puts Rainbow("Synopsis: ").bg(:black).yellow.bright + "#{book.synopsis}" unless book.synopsis == ""
|
225
|
+
puts Rainbow("URL: ").bg(:black).yellow.bright + "#{book.url}\n\n"
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
def output_episode(episode, number, display_description = false)
|
230
|
+
puts "#{number} - " + Rainbow("#{episode.title}").bg(:black).yellow.bright + " - #{episode.date}"
|
231
|
+
puts "#{episode.description}" if display_description == true
|
232
|
+
end
|
233
|
+
|
234
|
+
def output_author(author)
|
235
|
+
puts "\n\n" + Rainbow("#{author.name}").bg(:black).yellow.bright + Rainbow(" (#{author.books.count})").silver
|
236
|
+
|
237
|
+
sorted_books = author.books.sort_by { |book| book.title}
|
238
|
+
sorted_books.each do |book|
|
239
|
+
puts " #{book.title}"
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
def output_genre(genre)
|
245
|
+
puts "\n\n" + Rainbow("#{genre.name}").bg(:black).yellow.bright + " (#{genre.books.count})"
|
246
|
+
|
247
|
+
sorted_books = genre.books.sort_by { |book| book.title}
|
248
|
+
sorted_books.each do |book|
|
249
|
+
authors = []
|
250
|
+
book.author.each { |author| authors << author.name}
|
251
|
+
|
252
|
+
puts " #{book.title} by #{authors.join(", ")}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
216
256
|
def no_books
|
217
257
|
puts "Your library has no books! Find an episode to begin building your library."
|
218
258
|
menu_options
|
@@ -37,9 +37,4 @@ class Episode
|
|
37
37
|
self.all.select { |ep| ep.date >= first_date && ep.date <= last_date }
|
38
38
|
end
|
39
39
|
|
40
|
-
def output(number, display_description = false)
|
41
|
-
puts "#{number} - " + Rainbow("#{self.title}").bg(:black).yellow.bright + " - #{self.date}"
|
42
|
-
puts "#{self.description}" if display_description == true
|
43
|
-
end
|
44
|
-
|
45
40
|
end
|
@@ -10,23 +10,15 @@ class Genre
|
|
10
10
|
@@all = []
|
11
11
|
|
12
12
|
def initialize(attributes)
|
13
|
-
|
14
13
|
@books = []
|
15
|
-
|
16
|
-
attributes
|
17
|
-
self.send("#{k}=", v)
|
18
|
-
end
|
19
|
-
|
14
|
+
@name = attributes[:name]
|
15
|
+
@books << attributes[:book] if attributes[:book]
|
20
16
|
end
|
21
17
|
|
22
18
|
def self.all
|
23
19
|
@@all
|
24
20
|
end
|
25
21
|
|
26
|
-
def books=(book)
|
27
|
-
self.books << book
|
28
|
-
end
|
29
|
-
|
30
22
|
def add_book(book)
|
31
23
|
self.books << book unless self.books.include?(book)
|
32
24
|
book.genre << self unless book.genre.include?(self)
|
@@ -37,16 +29,4 @@ class Genre
|
|
37
29
|
@books.map { |book| book.author }.flatten.uniq
|
38
30
|
end
|
39
31
|
|
40
|
-
def output
|
41
|
-
puts "\n\n" + Rainbow("#{self.name}").bg(:black).yellow.bright + " (#{self.books.count})"
|
42
|
-
|
43
|
-
sorted_books = self.books.sort_by { |book| book.title}
|
44
|
-
sorted_books.each do |book|
|
45
|
-
authors = []
|
46
|
-
book.author.each { |author| authors << author.name}
|
47
|
-
|
48
|
-
puts " #{book.title} by #{authors.join(", ")}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
32
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative "../podcast_book_club.rb"
|
2
2
|
|
3
3
|
class Scraper
|
4
|
-
|
4
|
+
|
5
5
|
def initialize
|
6
6
|
path = build_path
|
7
7
|
fetch_episodes(path)
|
@@ -18,7 +18,7 @@ class Scraper
|
|
18
18
|
title = episode.css(".info-top a").text.strip
|
19
19
|
link = "https://player.fm#{episode.css(".info-top a").attribute("href").value}"
|
20
20
|
date = Date.strptime(episode.css(".timeago").attribute("datetime").value)
|
21
|
-
|
21
|
+
|
22
22
|
attributes = {
|
23
23
|
title: title,
|
24
24
|
link: link,
|
@@ -42,6 +42,7 @@ class Scraper
|
|
42
42
|
|
43
43
|
attributes = {}
|
44
44
|
|
45
|
+
|
45
46
|
begin
|
46
47
|
|
47
48
|
attributes[:url] = result.info_link unless result.info_link.nil?
|
@@ -50,13 +51,14 @@ class Scraper
|
|
50
51
|
attributes[:genre] = result.categories unless result.categories.nil? || result.categories == ""
|
51
52
|
attributes[:synopsis] = result.description unless result.description.nil?
|
52
53
|
attributes[:episode] = episode
|
54
|
+
|
53
55
|
|
54
56
|
Book.find_or_create_by_title(attributes)
|
55
57
|
|
56
58
|
rescue
|
57
59
|
|
58
|
-
puts "I'm having trouble adding the book " + Rainbow("#{query}").bg(:black).yellow
|
59
|
-
|
60
|
+
puts "I'm having trouble adding the book " + Rainbow("#{query}.").bg(:black).yellow
|
61
|
+
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
@@ -88,46 +90,34 @@ class Scraper
|
|
88
90
|
parse_with_links(episode)
|
89
91
|
when (without_links...with_links)
|
90
92
|
parse_without_links(episode)
|
91
|
-
else
|
93
|
+
else
|
92
94
|
puts "This episode has no recommendations."
|
93
95
|
end
|
94
96
|
|
95
97
|
end
|
96
98
|
|
97
99
|
def parse_with_links(episode)
|
98
|
-
book_titles = []
|
99
|
-
|
100
100
|
book_links = @episode_doc.css(".description.prose > a")
|
101
101
|
|
102
|
-
book_links.
|
103
|
-
if link.attribute("href").value.include?("amazon")
|
104
|
-
book_titles << link.text
|
105
|
-
end
|
106
|
-
end
|
102
|
+
book_titles = book_links.select { |link| link.attribute("href").value.include?("amazon")}.map {|link| link.text}
|
107
103
|
|
108
104
|
description = @description.split(book_titles[0]).pop.to_s
|
109
105
|
|
110
|
-
books = []
|
111
|
-
|
112
106
|
book_titles.map.with_index do |title, i|
|
113
|
-
|
107
|
+
|
108
|
+
if i + 1 < book_titles.length
|
114
109
|
description = description.split(book_titles[i+1 || i])
|
115
110
|
author = description[0].strip
|
116
|
-
|
117
|
-
books << "#{title} #{author}"
|
118
|
-
|
119
111
|
description = description.pop
|
120
112
|
|
113
|
+
"#{title} #{author}"
|
121
114
|
else
|
122
115
|
|
123
|
-
|
116
|
+
"#{title} #{description[0].strip}"
|
124
117
|
|
125
118
|
end
|
126
119
|
|
127
120
|
end
|
128
|
-
|
129
|
-
books
|
130
|
-
|
131
121
|
end
|
132
122
|
|
133
123
|
def parse_without_links(episode)
|
@@ -139,7 +129,7 @@ class Scraper
|
|
139
129
|
|
140
130
|
book_queries = []
|
141
131
|
|
142
|
-
book_array.
|
132
|
+
book_array.each.with_index do |item, i|
|
143
133
|
if i.even?
|
144
134
|
book_queries << "#{item.strip} #{book_array[i+1]}"
|
145
135
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: podcast-book-club
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jessrezac
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|