From e01d64b4a2b22a171a8b24a2d4477fc648f719c7 Mon Sep 17 00:00:00 2001 From: 0x1eef <0x1eef@protonmail.com> Date: Mon, 27 Mar 2023 01:47:23 -0300 Subject: [PATCH] Add Cmd::Pull --- .rubocop.yml | 4 +- bin/quran-json | 25 ++--- lib/quran-json/quran/json.rb | 2 +- lib/quran-json/quran/json/cmd.rb | 8 ++ lib/quran-json/quran/json/cmd/pull.rb | 95 +++++++++++++++++++ lib/quran-json/quran/json/pull.rb | 122 ------------------------- libexec/quran-json/quran.com | 14 ++- libexec/quran-json/www.searchtruth.com | 12 +-- 8 files changed, 127 insertions(+), 155 deletions(-) create mode 100644 lib/quran-json/quran/json/cmd/pull.rb delete mode 100644 lib/quran-json/quran/json/pull.rb diff --git a/.rubocop.yml b/.rubocop.yml index 2756af9..96d8573 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -16,12 +16,12 @@ AllCops: - bin/* ## -# Enabled cops +# Enabled Style/FrozenStringLiteralComment: Enabled: true ## -# Disabled cops +# Disabled Layout/MultilineMethodCallIndentation: Enabled: false Layout/ArgumentAlignment: diff --git a/bin/quran-json b/bin/quran-json index b4a4dc8..f23505e 100755 --- a/bin/quran-json +++ b/bin/quran-json @@ -1,7 +1,13 @@ #!/usr/bin/env ruby # frozen_string_literal: true -require "json" +root_dir = File.realpath(File.join(__dir__, "..")) +lib_dir = File.join(root_dir, "lib", "quran-json") +require File.join(lib_dir, "quran", "json") + +## +# Provide short access to 'Quran::JSON::Cmd::Pull' +include Quran::JSON ## # Utils @@ -18,22 +24,11 @@ end ## # main def main(argv) - root_dir = File.realpath(File.join(__dir__, "..")) - lib_dir = File.join(root_dir, "lib", "quran-json") - libexec_dir = File.join(root_dir, "libexec", "quran-json") - share_dir = File.join(root_dir, "share", "quran-json", "data") - sources = JSON.parse(File.binread(File.join(share_dir, "sources.json"))) - require File.join(lib_dir, "quran", "json") - case argv[0] when "pull" - cli = Quran::JSON::Pull.cli(argv[1..]) - sources.each do |locale, source| - case cli.locale - when locale - wait spawn(libexec_dir, source["http"]["hostname"], *argv[1..]) - end - end + cmd = Cmd::Pull.new(argv[1..]) + source = Ryo.find(cmd.sources) { _1 == cmd.options.locale } + wait spawn(cmd.libexec_dir, source[cmd.options.locale]["http"]["hostname"], *argv[1..]) else warn "Usage: quran-json pull [OPTIONS]" end diff --git a/lib/quran-json/quran/json.rb b/lib/quran-json/quran/json.rb index 904af9e..06ae269 100644 --- a/lib/quran-json/quran/json.rb +++ b/lib/quran-json/quran/json.rb @@ -3,6 +3,6 @@ module Quran module JSON require_relative "json/cmd" - require_relative "json/pull" + require_relative "json/cmd/pull" end end diff --git a/lib/quran-json/quran/json/cmd.rb b/lib/quran-json/quran/json/cmd.rb index 8e97934..586c4a5 100644 --- a/lib/quran-json/quran/json/cmd.rb +++ b/lib/quran-json/quran/json/cmd.rb @@ -25,6 +25,14 @@ module Quran::JSON::Cmd File.join(quran_dir, options.locale) end + def libexec_dir + File.join(root_dir, "libexec", "quran-json") + end + + def sources + @sources ||= Ryo.from JSON.parse(File.binread(File.join(data_dir, "sources.json"))) + end + def line @line ||= IO::Line.new($stdout) end diff --git a/lib/quran-json/quran/json/cmd/pull.rb b/lib/quran-json/quran/json/cmd/pull.rb new file mode 100644 index 0000000..6722c1a --- /dev/null +++ b/lib/quran-json/quran/json/cmd/pull.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +module Quran::JSON::Cmd + class Pull + require "ryo" + require "json" + require "net/http" + require "fileutils" + require "optparse" + include Quran::JSON::Cmd + include FileUtils + + attr_reader :options, + :source, + :http + + def self.parse_cli(argv) + op = nil + result = Ryo({locale: "en", replace: false, update: false}) + OptionParser.new(nil, 22, " " * 2) do |o| + op = o + op.banner = "Usage: quran-json pull [OPTIONS]" + cli_options.each { op.on(*_1) } + end.parse(argv, into: result) + result + rescue + puts op.help + exit + end + + def self.cli_options + [ + ["-l", "--locale LOCALE", "A locale (eg 'en')"], + ["-r", "--replace", "Replace existing JSON files"], + ["-u", "--update", "Replace surah metadata"] + ] + end + + def initialize(argv) + @options = self.class.parse_cli(argv) + @source = sources[options.locale] + @http = Net::HTTP.new(source.http.hostname, 443).tap { _1.use_ssl = true } + end + + def pull_surah(surah_no) + pull format(source.http.path, {surah_no:}) + end + + def pull_ayah(surah_no, ayah_no) + pull format(source.http.path, {surah_no:, ayah_no:}) + end + + def write(surah_no, rows) + mkdir_p(locale_dir) + rows[0] = Ryo.table_of(metadata[surah_no - 1]) + write_json File.join(locale_dir, "#{surah_no}.json"), rows + end + + def update(surah_no) + rows = read_json File.join(locale_dir, "#{surah_no}.json") + write(surah_no, rows) + end + + def keepalive + http.start + yield + ensure + http.finish + end + + ## + # @return [Boolean] + # Returns true when a surah shouldn't be replaced, or updated + def keep?(surah_no) + exist?(surah_no) and [options.replace, options.update].all? { _1.equal?(false) } + end + + private + + def exist?(surah_no) + File.exist? File.join(locale_dir, "#{surah_no}.json") + end + + def pull(req_path) + res = http.get(req_path) + case res + when Net::HTTPOK + res + else + ## + # TODO: Handle error + end + end + end +end diff --git a/lib/quran-json/quran/json/pull.rb b/lib/quran-json/quran/json/pull.rb deleted file mode 100644 index 0d30be1..0000000 --- a/lib/quran-json/quran/json/pull.rb +++ /dev/null @@ -1,122 +0,0 @@ -# frozen_string_literal: true - -class Quran::JSON::Pull - require "ryo" - require "json" - require "net/http" - require "fileutils" - require "optparse" - include Quran::JSON::Cmd - include FileUtils - - attr_reader :options, - :source, - :http - - def self.cli(argv) - op = nil - result = Ryo({locale: "en", replace: false, update: false}) - OptionParser.new(nil, 22, " " * 2) do |o| - op = o - op.banner = "Usage: quran-json pull [OPTIONS]" - cli_options.each { op.on(*_1) } - end.parse(argv, into: result) - result - rescue - puts op.help - exit - end - - def self.cli_options - [ - [ - "-l", "--locale LOCALE", - "ar, en, pt, fa, nl, fr, or it (default: en)" - ], - [ - "-r", "--replace", - "Replace existing JSON files (default: no)" - ], - [ - "-u", "--update", - "Replace surah metadata with an updated copy (implies -r, default: no)" - ] - ] - end - - def initialize(options) - @options = options - @source = sources[options.locale] - @http = Net::HTTP.new(source.http.hostname, 443).tap { _1.use_ssl = true } - end - - def pull_surah(surah_no) - pull path(vars(binding)) - end - - def pull_ayah(surah_no, ayah_no) - pull path(vars(binding)) - end - - def write(surah_no, rows) - mkdir_p(locale_dir) - rows[0] = Ryo.table_of(metadata[surah_no - 1]) - write_json File.join(locale_dir, "#{surah_no}.json"), rows - end - - def update(surah_no) - rows = read_json File.join(locale_dir, "#{surah_no}.json") - write(surah_no, rows) - end - - def keepalive - http.start - yield - ensure - http.finish - end - - ## - # @return [Boolean] - # Returns true when a surah shouldn't be replaced, or updated - def keep?(surah_no) - exist?(surah_no) and [options.replace, options.update].all? { _1.equal?(false) } - end - - private - - def path(vars) - format source.http.path, source.http.vars.map { [_1.to_sym, vars[_1.to_sym]] }.to_h - end - - def exist?(surah_no) - File.exist? File.join(locale_dir, "#{surah_no}.json") - end - - def headers - @headers ||= { - "user-agent" => "quran-json (https://github.com/ReflectsLight/quran-json#readme)" - } - end - - def pull(req_path) - res = http.get(req_path, headers) - case res - when Net::HTTPOK - res - else - ## - # TODO: Handle error - end - end - - def vars(binding) - binding.local_variables.map do - [_1.to_sym, binding.local_variable_get(_1)] - end.to_h - end - - def sources - @sources ||= Ryo.from read_json(File.join(data_dir, "sources.json")) - end -end diff --git a/libexec/quran-json/quran.com b/libexec/quran-json/quran.com index fed4fef..0e60cff 100755 --- a/libexec/quran-json/quran.com +++ b/libexec/quran-json/quran.com @@ -6,6 +6,10 @@ require File.join(lib_dir, "quran", "json") require "optparse" require "nokogiri" +## +# Provide short access to 'Quran::JSON::Cmd::Pull' +include Quran::JSON + ## # Grep for ayah content def grep(res) @@ -14,16 +18,10 @@ def grep(res) el.text.gsub(/[0-9]/, "") end -## -# CLI parser -def parse_cli(argv) - Quran::JSON::Pull.cli(argv) -end - ## # main def main(argv) - cmd = Quran::JSON::Pull.new parse_cli(argv) + cmd = Cmd::Pull.new(argv) cmd.keepalive do 1.upto(114) do |surah_no| if cmd.keep?(surah_no) @@ -32,7 +30,7 @@ def main(argv) cmd.update(surah_no) else rows = [nil] - ayah_count = cmd.metadata[surah_no].ayahs + ayah_count = cmd.metadata[surah_no - 1].ayahs 1.upto(ayah_count) do |ayah_no| res = cmd.pull_ayah(surah_no, ayah_no) rows.push([ayah_no, grep(res)]) diff --git a/libexec/quran-json/www.searchtruth.com b/libexec/quran-json/www.searchtruth.com index 5687f6d..d87c3fa 100755 --- a/libexec/quran-json/www.searchtruth.com +++ b/libexec/quran-json/www.searchtruth.com @@ -6,6 +6,10 @@ require File.join(lib_dir, "quran", "json") require "optparse" require "nokogiri" +## +# Provide short access to 'Quran::JSON::Cmd::Pull' +include Quran::JSON + ## # Grep for ayah content def grep(res) @@ -15,16 +19,10 @@ def grep(res) html.css(sel).map { _1.text.strip.gsub(/^[0-9]+\.\s*/, "") } end -## -# CLI parser -def parse_cli(argv) - Quran::JSON::Pull.cli(argv) -end - ## # main def main(argv) - cmd = Quran::JSON::Pull.new parse_cli(argv) + cmd = Cmd::Pull.new(argv) cmd.keepalive do 1.upto(114) do |surah_no| if cmd.keep?(surah_no)