abcdistill 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3818f08e18b6a811e2a32f1edaf7ff307f2c3222
4
+ data.tar.gz: fd2a307a9b7a0ad3d9b4f97653889baed7ac8d7f
5
+ SHA512:
6
+ metadata.gz: 1bc53f04033670eaecff6eac67035a4b59080b5bc5da86b20cf6bc27eb09103ac3d024ba59b2c61620a48b5fff0f6e30649718b3d556fb968a2b518815d3e7f6
7
+ data.tar.gz: 8a59091c2b13b8505f6ab92cf9efd7e8b04b9ee8fd471df872b6204979ae6da50a6a8e353a3fca109aafd25d4b4e17a8d4b7e7c69760def1e87d2e518305b86f
Binary file
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at TODO: Write your email address. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in abcdistill.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020: Khoi Nguyen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # Abcdistill
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/abcdistill`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'abcdistill'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install abcdistill
22
+
23
+ ## Usage
24
+
25
+ This gem gives you the most read books this week in each genre from GoodReads. You can then select a book to read further details of that book. To quit anytime, type "quit".
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Things I'd love to improve is to make the flow of the user experience better. Like functionalities to go "back" to the previous "page" and go to the first page as opposed to having to start the application over.
36
+
37
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/abcdistill. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/abcdistill/blob/master/CODE_OF_CONDUCT.md).
38
+
39
+
40
+ ## License
41
+
42
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
43
+
44
+ ## Code of Conduct
45
+
46
+ Everyone interacting in the Abcdistill project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/abcdistill/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,32 @@
1
+ require_relative 'lib/abcdistill/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "abcdistill"
5
+ spec.version = Abcdistill::VERSION
6
+ spec.authors = ["Khoi Nguyen"]
7
+ spec.email = ["khoinguyenkc@gmail.com"]
8
+
9
+ spec.summary = %q{Show most read books of each genre on GoodReads.}
10
+ spec.description = %q{This gem gives you the most read books this week in each genre from GoodReads. You can then select a book to read further details of that book.}
11
+ spec.homepage = "https://github.com/khoinguyenkc/abcdistill"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/khoinguyenkc/abcdistill"
19
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency "nokogiri"
31
+
32
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ #thats requiring the environment
3
+
4
+ require './lib/abcdistill'
5
+ #this is an ABSOLUTE path! we still dont know hat it work. for now
6
+ #it's loading the main file in the lib folder. lib/distill.rb
7
+ #that file itself, distill.rb require other stuff surrounding in, inside distill.rb itself
8
+ #so you're not loading these files here(version.rb, cli.rb etc..)
9
+
10
+ Abcdistill::CLI.new.call()
11
+ #Distill::Scraper.new.books_in_genre()
12
+ #Distill::Scraper.new.book_detail(Distill::Book.all[2])
13
+ #puts "hello"
14
+ #puts Distill::Book.all[2].title
15
+ #puts Distill::Book.all[2].authorname
16
+ #puts Distill::Book.all[2].description
17
+
18
+ #Distill::Scraper.new.testing('https://www.goodreads.com/genres/biography')
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "abcdistill"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
Binary file
@@ -0,0 +1,6 @@
1
+ require "abcdistill/version"
2
+
3
+ module Abcdistill
4
+ class Error < StandardError; end
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,16 @@
1
+ class Abcdistill::Book
2
+ attr_accessor :authorname, :pages, :publishdate, :description, :amazonlink
3
+ attr_reader :title, :link, :genre
4
+ @@all = []
5
+ def initialize(title, link = "", genre = "")
6
+ @title = title
7
+ @link = link
8
+ @genre = genre
9
+ @@all << self
10
+ end
11
+
12
+ def self.all
13
+ @@all
14
+ end
15
+
16
+ end
@@ -0,0 +1,131 @@
1
+ #note that back when we put this class CLI inside the Distill module
2
+ #we just define it as class cli
3
+ #but here it's in a seprate file. so things change.
4
+ #i'm not exactly sure the way things work. i'm just parroting and pryaing it works
5
+ #apparently putting in like this creates the same effect as if you phsyically put it inside the module
6
+ #even though it's not, its in a seprate file
7
+ #hiiiii
8
+ class Abcdistill::CLI
9
+
10
+ def initialize
11
+ Abcdistill::Genre.addthegenres()
12
+ #if u add too much at initalize, it slows down the app. but i think here it take same amount either way
13
+ end
14
+
15
+ def call
16
+ #this is the "HomePage"
17
+ puts "Hello!"
18
+ puts "Type quit anytime to quit the app"
19
+ list_genres
20
+ process_genrechoice
21
+ say_goodbye
22
+ end
23
+
24
+ def list_genres
25
+ Abcdistill::Genre.list_genre_names()
26
+ end
27
+
28
+
29
+
30
+ def say_goodbye
31
+ puts "Bye. Thanks for using our app."
32
+ end
33
+
34
+ def display_books_in_genre(genre)
35
+ #aka display books in genre
36
+ #takes the argument of the genre instance and then display books in that genres
37
+ #u only need to fetch it once. make sure this happen properly
38
+ puts genre.name
39
+ puts genre.genrelink
40
+ #scrape the books with scraper tool
41
+ Abcdistill::Scraper.new.books_in_genre(genre)
42
+ #display the books:
43
+ Abcdistill::Genre.display_books_of_genre(genre)
44
+
45
+ end
46
+
47
+ def display_book_detail(book)
48
+ puts "Title: #{book.title}"
49
+ puts "Genre: #{book.genre}"
50
+ puts "Author: #{book.authorname}"
51
+ puts "Pages: #{book.pages}"
52
+ puts "Publish Date: #{book.publishdate}"
53
+ puts "Amazon Link: #{book.amazonlink}"
54
+ puts "Description: #{book.description}"
55
+ end
56
+
57
+ def process_bookchoice(genre)
58
+ #context: user choose a number from a list of 15 books in that genres (from display_genre method)
59
+ #and the task here is to display the details
60
+ #besides the number, we need to figure out the context of the list of choices that was displayed
61
+ #that is needed so that we can figure out what book the user wants
62
+ #to figure out the context, we'll just ask the genre, we won't ask the for the list, we'll get the source of the list ourselves
63
+ #cuz we don't want to have code read the list and understand what it means and search it up it's a mess
64
+ input = nil
65
+ puts "Type the number of the book you want"
66
+ while input != "quit"
67
+ input = gets.strip
68
+
69
+ if input.to_i > 0 && input.to_i < 16 #we're strict so we don't run into nil error
70
+ #figure out what book the user chose:
71
+ book = Abcdistill::Genre.books_of_genre(genre)[input.to_i - 1]
72
+ puts "the book we think the user chose is: #{book.title}"
73
+ # Distill::Genre.display_books_of_genre called in display_books_in_genre actually uses this method above to get its list before it display, so the order should be the same
74
+ #that is, unless there was a change in the moment jsut before. which shouldn't happen. becasue this app doesn't update anything automatically on itself
75
+ #fetch more details on that book:
76
+ Abcdistill::Scraper.new.book_detail(book)
77
+ #this should update the book with more details
78
+ #display the book pseudo code:
79
+ display_book_detail(book)
80
+
81
+ process_bookchoice(genre)
82
+
83
+ return
84
+ elsif input == "quit"
85
+ return
86
+ else
87
+ puts "Invalid input. Please re-enter"
88
+ end #end if
89
+
90
+ end #end loop
91
+ end #end method
92
+
93
+
94
+
95
+ def process_genrechoice
96
+ input = nil
97
+ puts "Type the number of the GENRE you want"
98
+ while input != "quit"
99
+ input = gets.strip
100
+
101
+ if input.to_i > 0 && input.to_i < Abcdistill::Genre.all.size
102
+ #fetch the books in that genre
103
+ genre = Abcdistill::Genre.all[input.to_i - 1] #returns genre instance
104
+ display_books_in_genre(genre)
105
+ process_bookchoice(genre) #this will ask for input and process it
106
+
107
+
108
+ return
109
+
110
+
111
+
112
+
113
+ # if input == "1"
114
+ # puts "1. abc"
115
+ # process_choice()
116
+ # return #gotta put return otherwise u'll be doing nothing
117
+ # #cuz u have many recursive loop, but the outerloop still doesn't have the input = exit, only input of the inner loops are exit
118
+ # elsif input == "2"
119
+ # puts "2. def"
120
+ # process_choice()
121
+ # return #gotta put return otherwise u'll be doing nothing
122
+ elsif input == "quit"
123
+ return
124
+ else
125
+ puts "Invalid input. Please re-enter"
126
+ end #end if
127
+
128
+ end #end loop
129
+ end #end method
130
+
131
+ end
@@ -0,0 +1,75 @@
1
+ class ABCDistill::Genre
2
+ attr_reader :name
3
+ attr_accessor :genrelink
4
+ @@all = []
5
+ @@genrelist = [
6
+ "Art", "Biography","Business","Children's","Christian","Classics","Comics","Cookbooks","Ebooks","Fantasy","Fiction","Graphic Novels","Historical Fiction","History","Horror","Memoir","Music","Mystery","Nonfiction","Poetry","Psychology","Romance","Science","Science Fiction","Self Help","Sports","Thriller","Travel","Young Adult"
7
+ ]
8
+ @@genrelinks = [
9
+ "art", "biography","business","children-s","christian","classics","comics","cookbooks","ebooks","fantasy","fiction","graphic-novels","historical-fiction","history","horror","memoir","music","mystery","non-fiction","poetry","psychology","romance","science","science-fiction","self-help","sports","thriller","travel","young-adult"
10
+ ]
11
+
12
+
13
+ def initialize(name)
14
+ @name = name
15
+ #there should be some kind of name so that it created by accessed/looked up
16
+ #perhaps each book should have a genre property
17
+ #be careful of "grabbing" things, because a book might be severla genre
18
+ #we have to think about at what point we assign genre
19
+ #ther emight be a book that show up in severla genre lists
20
+ #these should be made to be different instnaces? or we have books have the capacity to have diff genres?
21
+ #right now i will be making multiple book instances
22
+ @@all << self
23
+ end
24
+
25
+ def self.books_of_genre(genre)
26
+ ABCDistill::Book.all.select do | book |
27
+ book.genre == genre
28
+ end
29
+ #return all books of this genre
30
+ end
31
+
32
+ def self.display_books_of_genre(genre)
33
+ books = self.books_of_genre(genre)
34
+ books.each_with_index do | book, index |
35
+ puts "#{index+1}. #{book.title}"
36
+ end
37
+ end
38
+
39
+
40
+ def self.find_genre_by_name(genrename) #class method
41
+ #return the FIRST match, not all matches
42
+ self.all.find { | instance | instance.name == genrename }
43
+ end
44
+
45
+ def self.addthegenres #class method
46
+ #THIS METHOD IS MEANT TO BE CALLED ONCE
47
+
48
+ # genrelist = [
49
+ # "Art", "Biography","Business","Children's","Christian","Classics","Comics","Cookbooks","Ebooks","Fantasy","Fiction","Graphic Novels","Historical Fiction","History","Horror","Memoir","Music","Mystery","Nonfiction","Poetry","Psychology","Romance","Science","Science Fiction","Self Help","Sports","Thriller","Travel","Young Adult"
50
+ # ]
51
+ # genrelinks = [
52
+ # "art", "biography","business","children-s","christian","classics","comics","cookbooks","ebooks","fantasy","fiction","graphic-novels","historical-fiction","history","horror","memoir","music","mystery","non-fiction","poetry","psychology","romance","science","science-fiction","self-help","sports","thriller","travel","young-adult"
53
+ # ]
54
+ if @@genrelist != [] #this makes it a one-time method.
55
+ @@genrelist.each_with_index do | genrename, index |
56
+ newinstance = self.new(genrename)
57
+ newinstance.genrelink = "https://www.goodreads.com/genres/#{@@genrelinks[index]}"
58
+ end #end iteration
59
+ end #end if
60
+ end #end method
61
+
62
+ def self.list_genre_names
63
+ self.all.each_with_index do | genre, index |
64
+ puts "#{index+1}. #{genre.name} "
65
+ end
66
+
67
+ end #end method
68
+
69
+ def self.all
70
+ @@all
71
+ end
72
+
73
+
74
+
75
+ end
@@ -0,0 +1,149 @@
1
+ class Abcdistill::Scraper
2
+ #scraper is a tool. not an object. so it doesn't store anything in some kind of @@all array
3
+ #i'm gonna make the methods instance methods becuase it feels that way. like u feed it very diff things..
4
+ #idk..
5
+ def book_detail(bookinstance)
6
+ #eventually we'll have this take premade book instance (made with title and link)
7
+ #and we'll use the link to scrape other info and fill in.
8
+
9
+ html = open('https://www.goodreads.com/book/show/45046808-big-lies-in-a-small-town')
10
+ doc = Nokogiri::HTML(html) #retunrs xml nodeset
11
+
12
+ authorname = doc.css("a.authorName").text
13
+ #omg i'm so excited that this works! u can search by attribute
14
+ pages = doc.css("div#details span[itemprop=\"numberOfPages\"]").text
15
+ publishdate = (doc.css("div#details .row")[1].text).split("\n")[2].strip #this should say the date
16
+ #that piece has really weird strucutre. spaces is asn item too. and u have to strip the space to make it look normal
17
+ #lets hope this is stable across
18
+ description = doc.css("div#description span")[1].text
19
+
20
+ amazonlinktail = doc.css("ul.buyButtonBar a#buyButton").attribute("href").value
21
+ amazonlink = addgoodreadsdotcom(amazonlinktail)
22
+ #yes the link to amazon has a transfer link on goodred
23
+
24
+ #i like to separate the task so that if i had to change css stuff, i can easily experiment neatly
25
+
26
+ bookinstance.authorname = authorname
27
+ bookinstance.pages = pages
28
+ bookinstance.publishdate = publishdate
29
+ bookinstance.description = description
30
+ bookinstance.amazonlink = amazonlink
31
+
32
+
33
+ end
34
+
35
+ def addgoodreadsdotcom(linktail)
36
+ link = "https://www.goodreads.com#{linktail}"
37
+ end
38
+
39
+ # def testing(genrelink)
40
+ # #we'll be given a page , like https://www.goodreads.com/genres/art
41
+ # #we'll scrape all the book titles and its link. 15 of them.
42
+ # #we want this to create 15 book instsances and make sure they are SAVED
43
+ #
44
+ # html = open(genrelink)
45
+ # doc = Nokogiri::HTML(html) #retunrs xml nodeset
46
+ # allbigboxes = doc.css(".coverBigBox")
47
+ # puts allbigboxes.size
48
+ # allbigboxes.each do | box |
49
+ # puts box.css(".h2Container h2 a").text
50
+ # end
51
+ # end
52
+
53
+ def books_in_genre(genre)
54
+ #we'll be given a page , like https://www.goodreads.com/genres/art
55
+ #we'll scrape all the book titles and its link. 15 of them.
56
+ #we want this to create 15 book instsances and make sure they are SAVED
57
+
58
+ #gatekeeper: to prevent duplicates, check if books in this genre is already fetched.
59
+ if Abcdistill::Genre.books_of_genre(genre) != [] #cant do truthy falsey because empty array is truthy in ruby
60
+ return
61
+ end
62
+
63
+
64
+ html = open(genre.genrelink)
65
+ doc = Nokogiri::HTML(html) #retunrs xml nodeset
66
+ genrename = doc.css(".genreHeader h1").text.strip
67
+ puts "the genrename that was scraped is -#{genrename}-"
68
+ if genrename == "Childrens"
69
+ genrename = "Children's"
70
+ end
71
+ puts "new genrename is #{genrename}"
72
+ #i'm fixing it manually because the url can be unreliable. say ...biography vs ...biography/
73
+ #using a split tool can be complicated to deal with edge cases like that
74
+
75
+ genre = Abcdistill::Genre.find_genre_by_name(genrename)
76
+ puts "did they find the genre in the list? the name found is #{genre.name}"
77
+ #the genres were already added at the moment CLI class's list_options is called.
78
+ #mostread = doc.css(".bigBoxBody")[1]
79
+ allbigboxes = doc.css(".coverBigBox")
80
+ mostread = allbigboxes.find do | box |
81
+ box.css(".h2Container h2 a").text.include?("Most Read This Week")
82
+ end
83
+ #i used include because == doesn't work for many cases. it's not uniform. sometiems it's most read this week tagged Christian
84
+
85
+
86
+ #the [0] index is not what we want. we just want the [1]
87
+ #mostread only contains one "item" which is the bigboxbody we want
88
+ books = mostread.css(".bookBox a")
89
+ puts "how many books found in books = mostread.css.... #{books.size}"
90
+ #this puts is really helpful for debugging. don't remove it
91
+
92
+ #Distill::Genre.books_of_genre
93
+ #we mut setup some how to only fetch books if they're not already fetched
94
+ #to prevent duplicates
95
+ #task NOT completed
96
+
97
+ books.each do | book |
98
+ title = book.css("img").attribute("alt").value
99
+ booklink = addgoodreadsdotcom(book.attribute("href").value)
100
+ #create a new book instance:
101
+ Abcdistill::Book.new(title, booklink, genre)
102
+ end
103
+
104
+ puts "how many books of this genre is added and recognized: #{Abcdistill::Genre.books_of_genre(genre).size}"
105
+
106
+ #puts Distill::Genre.books_of_genre(genre)[0]
107
+ # Distill::Genre.books_of_genre(genre).each do | book |
108
+ # puts book
109
+ # puts book.title
110
+ # end
111
+
112
+
113
+
114
+ #we want to seprate tasks. so this should only fetch the books in that genre. but not display it
115
+ #display should be a method for Genre or Book
116
+
117
+
118
+
119
+ #notice how to make this kind of structure, the thing we're looping (titles), need each title to be something that is a ROOT
120
+ #for ex: the alt value of the img element. the img element is a child of the .bookBox a element. .booxBox a leement is a "root"
121
+ #the href is also belongs to the .bookbox a element. otherwise we can't make use of the loop structure
122
+ #metadata
123
+ #when we scrape each element seprately, we don't have to think about that at all, but as a loop its very different!
124
+ #so don't think if i got each element down, putting it in a loop is simple. no! gotta see what they have in common and "refactor"
125
+
126
+ #puts title = mostread.css(".bookBox a img")[0].attribute("alt").value
127
+ # attribute("alt").value
128
+ #linktail = mostread.css(".bookBox a")[0].attribute("href").value
129
+ #ex: /book/show/53991683-the-woman-in-the-moonlight
130
+ #puts booklink = addgoodreadsdotcom(linktail)
131
+
132
+ #how she we organize this?
133
+ #we never want to have to scrape anything twice. so we save everything
134
+ #tehre should be some kinda all that host different genres
135
+ #each genres has 15 hashes of book title and links
136
+ #as we use book_detail, we'll add to the 15 hashes other properties, like author, pages, etc
137
+ #but i dont know how should we organize all this
138
+ #in classes named genres and books?
139
+ #apprently they want objects, which is instances of class, so we'll probably do that..
140
+ #make it life-like i guess
141
+
142
+ #we need to loop through each book. this might take more cleaning effort to loop through the right things
143
+
144
+
145
+ end
146
+
147
+
148
+
149
+ end
@@ -0,0 +1,3 @@
1
+ module Abcdistill
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: abcdistill
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Khoi Nguyen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-09-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
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
+ description: This gem gives you the most read books this week in each genre from GoodReads.
28
+ You can then select a book to read further details of that book.
29
+ email:
30
+ - khoinguyenkc@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".DS_Store"
36
+ - ".gitignore"
37
+ - CODE_OF_CONDUCT.md
38
+ - Gemfile
39
+ - LICENSE.txt
40
+ - README.md
41
+ - Rakefile
42
+ - abcdistill.gemspec
43
+ - bin/abcdistill
44
+ - bin/console
45
+ - bin/setup
46
+ - lib/.DS_Store
47
+ - lib/abcdistill.rb
48
+ - lib/abcdistill/book.rb
49
+ - lib/abcdistill/cli.rb
50
+ - lib/abcdistill/genre.rb
51
+ - lib/abcdistill/scraper.rb
52
+ - lib/abcdistill/version.rb
53
+ homepage: https://github.com/khoinguyenkc/abcdistill
54
+ licenses:
55
+ - MIT
56
+ metadata:
57
+ allowed_push_host: https://rubygems.org
58
+ homepage_uri: https://github.com/khoinguyenkc/abcdistill
59
+ source_code_uri: https://github.com/khoinguyenkc/abcdistill
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 2.3.0
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.5.2.3
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Show most read books of each genre on GoodReads.
80
+ test_files: []