diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..f49590f --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,50 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2017-09-17 09:34:31 +0530 using RuboCop version 0.50.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +Metrics/AbcSize: + Max: 16 + +# Offense count: 8 +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# URISchemes: http, https +Metrics/LineLength: + Max: 80 + AllowHeredoc: true + AllowURI: true + URISchemes: + - https + - http + IgnoredPatterns: + - \` + +# Offense count: 1 +# Configuration parameters: CountComments. +Metrics/MethodLength: + Max: 22 + +# Offense count: 1 +Metrics/PerceivedComplexity: + Max: 10 + +# Offense count: 2 +# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS +Naming/FileName: + Exclude: + - 'wok-reread.rb' + - 'wor-reread.rb' + +# Offense count: 5 +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: for, each +Style/For: + Exclude: + - 'oathbringer.rb' + - 'wok-reread.rb' + - 'wor-reread.rb' diff --git a/README.md b/README.md index a0762c8..075e619 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Scripts to generate books from the [Cosmere]() using various public sources. Cur 1. Oathbringer (Serialized till Chapter 32) 2. Way of Kings Reread +3. Words of Radiance Reread For obvious reasons, the converted ebooks are not part of this repo. You must download and run the script on your own machine to generate the copies. diff --git a/methods.rb b/methods.rb index 1e9c3fe..1ececcc 100644 --- a/methods.rb +++ b/methods.rb @@ -1,50 +1,78 @@ +module Nokogiri + module XML + # Patch to add class? + class Node + def class?(*classes) + present = false + if self.attribute('class') + present = true + classes.each do |klass| + present &&= self['class'].include? klass + end + end + present + end + end + end +end + # https://stackoverflow.com/a/42533209/368328 def command?(name) [name, - *ENV['PATH'].split(File::PATH_SEPARATOR).map {|p| File.join(p, name)} - ].find {|f| File.executable?(f)} + *ENV['PATH'].split(File::PATH_SEPARATOR) + .map { |p| File.join(p, name) }] + .find { |f| File.executable?(f) } end def commands?(commands) - commands.map {|c| command? c} + commands.map { |c| command? c } end def format_match(format) [:all, format].include? format end - -def generate(name, format=:all) - if command? 'pandoc' and format_match(:epub) +def gen_epub(name, _format) + if command?('pandoc') && format_match(:epub) # Convert it to epub `pandoc -S -o books/#{name}.epub --epub-metadata=metadata/#{name}.xml --epub-cover-image=covers/#{name}.jpg books/#{name}.html` - puts "[epub] Generated EPUB file" + puts '[epub] Generated EPUB file' else puts "[error] Can't generate EPUB without pandoc" end +end - if command? 'ebook-convert' and format_match(:mobi) +def gen_mobi(name, _format) + if command?('ebook-convert') && format_match(:mobi) # Convert epub to a mobi `ebook-convert books/#{name}.epub books/#{name}.mobi` - puts "[mobi] Generated MOBI file" + puts '[mobi] Generated MOBI file' else puts "[error] Can't generate MOBI without ebook-convert" end +end - if commands? ['pandoc', 'convert', 'wkhtmltopdf', 'pdftk'] and format_match(:pdf) +def gen_pdf(name, _format) + if commands?(%w[pandoc convert wkhtmltopdf pdftk]) && format_match(:pdf) # Generate PDF as well # First, lets make a better css version of the html - `pandoc books/#{name}.html -s -c style.css -o books/#{name}_pdf.html` - puts "[pdf] Generated html for pdf" + `pandoc books/#{name}.html -s -c ../style.css -o books/#{name}_pdf.html` + puts '[pdf] Generated html for pdf' # Print the pdf_html file to pdf - `wkhtmltopdf #{name}_pdf.html books/#{name}-nocover.pdf` - puts "[pdf] Generated PDF without cover" + `wkhtmltopdf books/#{name}_pdf.html books/#{name}-nocover.pdf` + puts '[pdf] Generated PDF without cover' # Join the cover and pdf together `pdftk covers/#{name}.pdf books/#{name}-nocover.pdf cat output books/#{name}.pdf` - puts "[pdf] Generated PDF file" + puts '[pdf] Generated PDF file' else - puts "[error] Please check README for PDF dependencies" + puts '[error] Please check README for PDF dependencies' end end + +def generate(name, _format = :all) + gen_epub(name, _format) + gen_mobi(name, _format) + gen_pdf(name, _format) +end diff --git a/oathbringer.rb b/oathbringer.rb index d99dd41..bd982a4 100644 --- a/oathbringer.rb +++ b/oathbringer.rb @@ -2,15 +2,15 @@ require 'fileutils' require 'nokogiri' require_relative './methods' -FileUtils.mkdir_p("oathbringer") +FileUtils.mkdir_p('oathbringer') -BASE = 'https://www.tor.com/2017/' +BASE = 'https://www.tor.com/2017/'.freeze links = [ - '08/22/oathbringer-brandon-sanderson-prologue/', - '08/29/oathbringer-brandon-sanderson-chapter-1-3/', - '09/05/oathbringer-by-brandon-sanderson-chapters-4-6/', - '09/12/oathbringer-by-brandon-sanderson-chapters-7-9/' + '08/22/oathbringer-brandon-sanderson-prologue/', + '08/29/oathbringer-brandon-sanderson-chapter-1-3/', + '09/05/oathbringer-by-brandon-sanderson-chapters-4-6/', + '09/12/oathbringer-by-brandon-sanderson-chapters-7-9/' ] links.last.split('/') @@ -22,43 +22,39 @@ episode = 1 -for link in links - url = BASE + link - puts "Download #{url}" - if !File.exists? "oathbringer/#{episode}.html" - `wget --no-clobber "#{url}" --output-document "oathbringer/#{episode}.html" -o /dev/null` - end - episode +=1 +links.each do |link| + url = BASE + link + puts "Download #{url}" + unless File.exist? "oathbringer/#{episode}.html" + `wget --no-clobber "#{url}" --output-document "oathbringer/#{episode}.html" -o /dev/null` + end + episode += 1 end # Now we have all the files -html = "" +html = '' for i in 1..(links.length) page = Nokogiri::HTML(open("oathbringer/#{i}.html")).css('.entry-content') start = ending = false page.children.each do |e| - if e.name == 'h3' - e.name = 'h1' - start = true - end + if e.name == 'h3' + e.name = 'h1' + start = true + end - if e.attribute('class') and e['class'].include? 'frontmatter' and start - ending = true - end + ending = true if e.class?('frontmatter') && start - if !start or ending - e.remove - end + e.remove if !start || ending end html += page.inner_html - url = links[i-1] + url = links[i - 1] html += "
Visit tor.com for discussion.
" end -html += "~fin\~
Next 3 chapters out on #{next_date.to_s}
~fin\~
Next 3 chapters out on #{next_date}
Visit tor.com for discussion.
" end -File.open("books/wok-reread.html", 'w') { |file| file.write(html) } -puts "[html] Generated HTML file" +File.open('books/wok-reread.html', 'w') { |file| file.write(html) } +puts '[html] Generated HTML file' -generate("wok-reread", :all) +generate('wok-reread', :all) diff --git a/wor-reread.rb b/wor-reread.rb index 47bc721..f872644 100644 --- a/wor-reread.rb +++ b/wor-reread.rb @@ -3,155 +3,149 @@ require 'nokogiri' require_relative './methods' -FileUtils.mkdir_p("wor") +FileUtils.mkdir_p('wor') -BASE = 'https://www.tor.com' +BASE = 'https://www.tor.com'.freeze links = [ - "/2014/06/12/introducing-the-words-of-radiance-reread/", - "/2014/06/12/words-of-radiance-reread-prologue/", - "/2014/06/19/words-of-radiance-reread-chapter-1/", - "/2014/06/26/words-of-radiance-reread-chapter-2/", - "/2014/07/03/words-of-radiance-reread-chapter-three/", - "/2014/07/10/words-of-radiance-reread-chapter-4/", - "/2014/07/17/words-of-radiance-reread-chapter-5/", - "/2014/07/24/words-of-radiance-reread-chapter-6/", - "/2014/07/31/words-of-radiance-reread-chapter-7/", - "/2014/08/07/words-of-radiance-reread-chapter-8/", - "/2014/08/14/words-of-radiance-reread-chapter-9/", - "/2014/08/21/words-of-radiance-reread-chapter-10/", - "/2014/08/28/words-of-radiance-reread-chapter-11/", - "/2014/09/04/words-of-radiance-reread-chapter-12/", - "/2014/09/11/words-of-radiance-reread-interlude-1/", - "/2014/09/18/words-of-radiance-reread-interlude-2/", - "/2014/09/25/words-of-radiance-reread-interlude-3/", - "/2014/10/02/words-of-radiance-reread-interlude-4/", - "/2014/10/09/words-of-radiance-reread-chapter-13/", - "/2014/10/16/words-of-radiance-reread-chapter-14/", - "/2014/10/23/words-of-radiance-reread-chapter-15/", - "/2014/10/30/words-of-radiance-reread-chapter-16/", - "/2014/11/06/words-of-radiance-reread-chapter-17/", - "/2014/11/13/words-of-radiance-reread-chapter-18/", - "/2014/11/20/words-of-radiance-reread-chapter-19/", - "/2014/12/04/words-of-radiance-reread-chapter-20/", - "/2014/12/11/words-of-radiance-reread-chapter-21/", - "/2014/12/18/words-of-radiance-reread-chapter-22/", - "/2015/01/08/words-of-radiance-reread-chapter-23/", - "/2015/01/15/words-of-radiance-reread-chapter-24/", - "/2015/01/22/words-of-radiance-reread-chapter-25/", - "/2015/01/29/words-of-radiance-reread-chapter-26/", - "/2015/02/05/words-of-radiance-reread-chapter-27/", - "/2015/02/12/words-of-radiance-reread-chapter-28/", - "/2015/02/19/words-of-radiance-reread-chapter-29/", - "/2015/02/26/words-of-radiance-reread-chapter-30/", - "/2015/03/05/words-of-radiance-reread-chapter-31/", - "/2015/03/12/words-of-radiance-reread-chapter-32/", - "/2015/03/19/words-of-radiance-reread-chapter-33/", - "/2015/03/26/words-of-radiance-reread-chapter-34/", - "/2015/04/02/words-of-radiance-reread-part-2-epigraphs/", - "/2015/04/09/words-of-radiance-reread-interludes-5-and-6/", - "/2015/04/16/words-of-radiance-reread-interludes-7-and-8/", - "/2015/04/23/words-of-radiance-reread-chapter-35/", - "/2015/04/30/words-of-radiance-reread-chapter-36/", - "/2015/05/07/words-of-radiance-reread-chapter-37/", - "/2015/05/14/words-of-radiance-reread-chapter-38/", - "/2015/05/21/words-of-radiance-reread-chapter-39/", - "/2015/05/28/words-of-radiance-reread-chapter-40/", - "/2015/06/04/words-of-radiance-reread-chapter-41/", - "/2015/06/11/words-of-radiance-reread-chapter-42/", - "/2015/06/18/words-of-radiance-reread-chapter-43/", - "/2015/06/25/words-of-radiance-reread-chapter-44/", - "/2015/07/02/words-of-radiance-reread-chapter-45/", - "/2015/07/09/words-of-radiance-reread-chapter-46/", - "/2015/07/23/words-of-radiance-reread-chapter-47/", - "/2015/07/30/words-of-radiance-reread-chapter-48/", - "/2015/08/06/words-of-radiance-reread-chapter-49/", - "/2015/08/13/words-of-radiance-reread-chapter-50/", - "/2015/08/20/words-of-radiance-reread-chapter-51/", - "/2015/08/27/words-of-radiance-reread-chapter-52/", - "/2015/09/03/words-of-radiance-reread-chapter-53/", - "/2015/09/10/words-of-radiance-reread-chapter-54/", - "/2015/09/17/words-of-radiance-reread-chapter-55/", - "/2015/09/24/words-of-radiance-reread-chapter-56/", - "/2015/10/01/words-of-radiance-reread-chapter-57/", - "/2015/10/08/words-of-radiance-reread-chapter-58/", - "/2015/10/15/words-of-radiance-reread-interlude-9/", - "/2015/10/22/words-of-radiance-reread-interlude-10/", - "/2015/10/29/words-of-radiance-reread-interlude-11/", - "/2015/11/05/words-of-radiance-reread-chapter-59/", - "/2015/11/12/words-of-radiance-reread-chapter-60/", - "/2015/11/19/words-of-radiance-reread-chapter-61/", - "/2015/12/03/words-of-radiance-reread-chapter-62/", - "/2015/12/10/words-of-radiance-reread-chapter-63/", - "/2015/12/17/words-of-radiance-reread-chapter-64/", - "/2016/01/07/words-of-radiance-reread-chapter-65/", - "/2016/01/14/words-of-radiance-reread-chapter-66/", - "/2016/01/21/words-of-radiance-reread-chapter-67/", - "/2016/01/28/words-of-radiance-reread-chapter-68/", - "/2016/02/04/words-of-radiance-reread-chapter-69/", - "/2016/02/11/words-of-radiance-reread-chapter-70/", - "/2016/02/18/words-of-radiance-reread-chapter-71/", - "/2016/02/25/words-of-radiance-reread-chapter-72/", - "/2016/03/03/words-of-radiance-reread-chapter-73/", - "/2016/03/10/words-of-radiance-reread-chapter-74/", - "/2016/03/17/words-of-radiance-reread-chapter-75/", - "/2016/03/24/words-of-radiance-reread-part-4-epigraphs/", - "/2016/03/31/words-of-radiance-reread-interludes-12-and-13/", - "/2016/04/07/words-of-radiance-reread-interlude-14/", - "/2016/04/14/words-of-radiance-reread-chapter-76/", - "/2016/04/21/words-of-radiance-reread-chapter-77/", - "/2016/04/28/words-of-radiance-reread-chapter-78/", - "/2016/05/05/words-of-radiance-reread-chapter-79/", - "/2016/05/12/words-of-radiance-reread-chapter-80/", - "/2016/05/19/words-of-radiance-reread-chapter-81/", - "/2016/05/26/words-of-radiance-reread-chapter-82/", - "/2016/06/02/words-of-radiance-reread-chapter-83/", - "/2016/06/09/words-of-radiance-reread-chapter-84/", - "/2016/06/16/words-of-radiance-reread-chapter-85/", - "/2016/06/23/words-of-radiance-reread-chapter-86/", - "/2016/06/30/words-of-radiance-reread-chapter-87/", - "/2016/07/14/words-of-radiance-reread-chapter-88/", - "/2016/07/28/words-of-radiance-reread-chapter-89/", - "/2016/08/04/words-of-radiance-reread-epilogue-and-what-comes-next/" + '/2014/06/12/introducing-the-words-of-radiance-reread/', + '/2014/06/12/words-of-radiance-reread-prologue/', + '/2014/06/19/words-of-radiance-reread-chapter-1/', + '/2014/06/26/words-of-radiance-reread-chapter-2/', + '/2014/07/03/words-of-radiance-reread-chapter-three/', + '/2014/07/10/words-of-radiance-reread-chapter-4/', + '/2014/07/17/words-of-radiance-reread-chapter-5/', + '/2014/07/24/words-of-radiance-reread-chapter-6/', + '/2014/07/31/words-of-radiance-reread-chapter-7/', + '/2014/08/07/words-of-radiance-reread-chapter-8/', + '/2014/08/14/words-of-radiance-reread-chapter-9/', + '/2014/08/21/words-of-radiance-reread-chapter-10/', + '/2014/08/28/words-of-radiance-reread-chapter-11/', + '/2014/09/04/words-of-radiance-reread-chapter-12/', + '/2014/09/11/words-of-radiance-reread-interlude-1/', + '/2014/09/18/words-of-radiance-reread-interlude-2/', + '/2014/09/25/words-of-radiance-reread-interlude-3/', + '/2014/10/02/words-of-radiance-reread-interlude-4/', + '/2014/10/09/words-of-radiance-reread-chapter-13/', + '/2014/10/16/words-of-radiance-reread-chapter-14/', + '/2014/10/23/words-of-radiance-reread-chapter-15/', + '/2014/10/30/words-of-radiance-reread-chapter-16/', + '/2014/11/06/words-of-radiance-reread-chapter-17/', + '/2014/11/13/words-of-radiance-reread-chapter-18/', + '/2014/11/20/words-of-radiance-reread-chapter-19/', + '/2014/12/04/words-of-radiance-reread-chapter-20/', + '/2014/12/11/words-of-radiance-reread-chapter-21/', + '/2014/12/18/words-of-radiance-reread-chapter-22/', + '/2015/01/08/words-of-radiance-reread-chapter-23/', + '/2015/01/15/words-of-radiance-reread-chapter-24/', + '/2015/01/22/words-of-radiance-reread-chapter-25/', + '/2015/01/29/words-of-radiance-reread-chapter-26/', + '/2015/02/05/words-of-radiance-reread-chapter-27/', + '/2015/02/12/words-of-radiance-reread-chapter-28/', + '/2015/02/19/words-of-radiance-reread-chapter-29/', + '/2015/02/26/words-of-radiance-reread-chapter-30/', + '/2015/03/05/words-of-radiance-reread-chapter-31/', + '/2015/03/12/words-of-radiance-reread-chapter-32/', + '/2015/03/19/words-of-radiance-reread-chapter-33/', + '/2015/03/26/words-of-radiance-reread-chapter-34/', + '/2015/04/02/words-of-radiance-reread-part-2-epigraphs/', + '/2015/04/09/words-of-radiance-reread-interludes-5-and-6/', + '/2015/04/16/words-of-radiance-reread-interludes-7-and-8/', + '/2015/04/23/words-of-radiance-reread-chapter-35/', + '/2015/04/30/words-of-radiance-reread-chapter-36/', + '/2015/05/07/words-of-radiance-reread-chapter-37/', + '/2015/05/14/words-of-radiance-reread-chapter-38/', + '/2015/05/21/words-of-radiance-reread-chapter-39/', + '/2015/05/28/words-of-radiance-reread-chapter-40/', + '/2015/06/04/words-of-radiance-reread-chapter-41/', + '/2015/06/11/words-of-radiance-reread-chapter-42/', + '/2015/06/18/words-of-radiance-reread-chapter-43/', + '/2015/06/25/words-of-radiance-reread-chapter-44/', + '/2015/07/02/words-of-radiance-reread-chapter-45/', + '/2015/07/09/words-of-radiance-reread-chapter-46/', + '/2015/07/23/words-of-radiance-reread-chapter-47/', + '/2015/07/30/words-of-radiance-reread-chapter-48/', + '/2015/08/06/words-of-radiance-reread-chapter-49/', + '/2015/08/13/words-of-radiance-reread-chapter-50/', + '/2015/08/20/words-of-radiance-reread-chapter-51/', + '/2015/08/27/words-of-radiance-reread-chapter-52/', + '/2015/09/03/words-of-radiance-reread-chapter-53/', + '/2015/09/10/words-of-radiance-reread-chapter-54/', + '/2015/09/17/words-of-radiance-reread-chapter-55/', + '/2015/09/24/words-of-radiance-reread-chapter-56/', + '/2015/10/01/words-of-radiance-reread-chapter-57/', + '/2015/10/08/words-of-radiance-reread-chapter-58/', + '/2015/10/15/words-of-radiance-reread-interlude-9/', + '/2015/10/22/words-of-radiance-reread-interlude-10/', + '/2015/10/29/words-of-radiance-reread-interlude-11/', + '/2015/11/05/words-of-radiance-reread-chapter-59/', + '/2015/11/12/words-of-radiance-reread-chapter-60/', + '/2015/11/19/words-of-radiance-reread-chapter-61/', + '/2015/12/03/words-of-radiance-reread-chapter-62/', + '/2015/12/10/words-of-radiance-reread-chapter-63/', + '/2015/12/17/words-of-radiance-reread-chapter-64/', + '/2016/01/07/words-of-radiance-reread-chapter-65/', + '/2016/01/14/words-of-radiance-reread-chapter-66/', + '/2016/01/21/words-of-radiance-reread-chapter-67/', + '/2016/01/28/words-of-radiance-reread-chapter-68/', + '/2016/02/04/words-of-radiance-reread-chapter-69/', + '/2016/02/11/words-of-radiance-reread-chapter-70/', + '/2016/02/18/words-of-radiance-reread-chapter-71/', + '/2016/02/25/words-of-radiance-reread-chapter-72/', + '/2016/03/03/words-of-radiance-reread-chapter-73/', + '/2016/03/10/words-of-radiance-reread-chapter-74/', + '/2016/03/17/words-of-radiance-reread-chapter-75/', + '/2016/03/24/words-of-radiance-reread-part-4-epigraphs/', + '/2016/03/31/words-of-radiance-reread-interludes-12-and-13/', + '/2016/04/07/words-of-radiance-reread-interlude-14/', + '/2016/04/14/words-of-radiance-reread-chapter-76/', + '/2016/04/21/words-of-radiance-reread-chapter-77/', + '/2016/04/28/words-of-radiance-reread-chapter-78/', + '/2016/05/05/words-of-radiance-reread-chapter-79/', + '/2016/05/12/words-of-radiance-reread-chapter-80/', + '/2016/05/19/words-of-radiance-reread-chapter-81/', + '/2016/05/26/words-of-radiance-reread-chapter-82/', + '/2016/06/02/words-of-radiance-reread-chapter-83/', + '/2016/06/09/words-of-radiance-reread-chapter-84/', + '/2016/06/16/words-of-radiance-reread-chapter-85/', + '/2016/06/23/words-of-radiance-reread-chapter-86/', + '/2016/06/30/words-of-radiance-reread-chapter-87/', + '/2016/07/14/words-of-radiance-reread-chapter-88/', + '/2016/07/28/words-of-radiance-reread-chapter-89/', + '/2016/08/04/words-of-radiance-reread-epilogue-and-what-comes-next/' ] episode = 1 -for link in links - url = BASE + link - puts "Download #{url}" - if !File.exists? "wor/#{episode}.html" - `wget --no-clobber "#{url}" --output-document "wor/#{episode}.html" -o /dev/null` - end - episode +=1 +links.each do |link| + url = BASE + link + puts "Download #{url}" + unless File.exist? "wor/#{episode}.html" + `wget --no-clobber "#{url}" --output-document "wor/#{episode}.html" -o /dev/null` + end + episode += 1 end # Now we have all the files -html = "" +html = '' for i in 1..(links.length) complete_html = Nokogiri::HTML(open("wor/#{i}.html")) page = complete_html.css('.entry-content') title = complete_html.css('.entry-title>a').inner_html ending = false page.children.each do |e| - - if e.attribute('class') and (e['class'].include? 'squib' or e['class'].include? 'post-end-spacer') - ending = true - end - - if ending - e.remove - end + ending = true if e.class?('squib') || e.class?('post-end-spacer') + e.remove if ending end html += "Visit tor.com for discussion.
" end -File.open("books/wor-reread.html", 'w') { |file| file.write(html) } -puts "[html] Generated HTML file" +File.open('books/wor-reread.html', 'w') { |file| file.write(html) } +puts '[html] Generated HTML file' -generate("wor-reread", :all) +generate('wor-reread', :all)