Add Cmd::Pull
This commit is contained in:
parent
880eb64897
commit
e01d64b4a2
8 changed files with 127 additions and 155 deletions
|
@ -16,12 +16,12 @@ AllCops:
|
||||||
- bin/*
|
- bin/*
|
||||||
|
|
||||||
##
|
##
|
||||||
# Enabled cops
|
# Enabled
|
||||||
Style/FrozenStringLiteralComment:
|
Style/FrozenStringLiteralComment:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
##
|
##
|
||||||
# Disabled cops
|
# Disabled
|
||||||
Layout/MultilineMethodCallIndentation:
|
Layout/MultilineMethodCallIndentation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
Layout/ArgumentAlignment:
|
Layout/ArgumentAlignment:
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
# frozen_string_literal: true
|
# 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
|
# Utils
|
||||||
|
@ -18,22 +24,11 @@ end
|
||||||
##
|
##
|
||||||
# main
|
# main
|
||||||
def main(argv)
|
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]
|
case argv[0]
|
||||||
when "pull"
|
when "pull"
|
||||||
cli = Quran::JSON::Pull.cli(argv[1..])
|
cmd = Cmd::Pull.new(argv[1..])
|
||||||
sources.each do |locale, source|
|
source = Ryo.find(cmd.sources) { _1 == cmd.options.locale }
|
||||||
case cli.locale
|
wait spawn(cmd.libexec_dir, source[cmd.options.locale]["http"]["hostname"], *argv[1..])
|
||||||
when locale
|
|
||||||
wait spawn(libexec_dir, source["http"]["hostname"], *argv[1..])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
warn "Usage: quran-json pull [OPTIONS]"
|
warn "Usage: quran-json pull [OPTIONS]"
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
module Quran
|
module Quran
|
||||||
module JSON
|
module JSON
|
||||||
require_relative "json/cmd"
|
require_relative "json/cmd"
|
||||||
require_relative "json/pull"
|
require_relative "json/cmd/pull"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,14 @@ module Quran::JSON::Cmd
|
||||||
File.join(quran_dir, options.locale)
|
File.join(quran_dir, options.locale)
|
||||||
end
|
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
|
def line
|
||||||
@line ||= IO::Line.new($stdout)
|
@line ||= IO::Line.new($stdout)
|
||||||
end
|
end
|
||||||
|
|
95
lib/quran-json/quran/json/cmd/pull.rb
Normal file
95
lib/quran-json/quran/json/cmd/pull.rb
Normal file
|
@ -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
|
|
@ -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
|
|
|
@ -6,6 +6,10 @@ require File.join(lib_dir, "quran", "json")
|
||||||
require "optparse"
|
require "optparse"
|
||||||
require "nokogiri"
|
require "nokogiri"
|
||||||
|
|
||||||
|
##
|
||||||
|
# Provide short access to 'Quran::JSON::Cmd::Pull'
|
||||||
|
include Quran::JSON
|
||||||
|
|
||||||
##
|
##
|
||||||
# Grep for ayah content
|
# Grep for ayah content
|
||||||
def grep(res)
|
def grep(res)
|
||||||
|
@ -14,16 +18,10 @@ def grep(res)
|
||||||
el.text.gsub(/[0-9]/, "")
|
el.text.gsub(/[0-9]/, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
|
||||||
# CLI parser
|
|
||||||
def parse_cli(argv)
|
|
||||||
Quran::JSON::Pull.cli(argv)
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# main
|
# main
|
||||||
def main(argv)
|
def main(argv)
|
||||||
cmd = Quran::JSON::Pull.new parse_cli(argv)
|
cmd = Cmd::Pull.new(argv)
|
||||||
cmd.keepalive do
|
cmd.keepalive do
|
||||||
1.upto(114) do |surah_no|
|
1.upto(114) do |surah_no|
|
||||||
if cmd.keep?(surah_no)
|
if cmd.keep?(surah_no)
|
||||||
|
@ -32,7 +30,7 @@ def main(argv)
|
||||||
cmd.update(surah_no)
|
cmd.update(surah_no)
|
||||||
else
|
else
|
||||||
rows = [nil]
|
rows = [nil]
|
||||||
ayah_count = cmd.metadata[surah_no].ayahs
|
ayah_count = cmd.metadata[surah_no - 1].ayahs
|
||||||
1.upto(ayah_count) do |ayah_no|
|
1.upto(ayah_count) do |ayah_no|
|
||||||
res = cmd.pull_ayah(surah_no, ayah_no)
|
res = cmd.pull_ayah(surah_no, ayah_no)
|
||||||
rows.push([ayah_no, grep(res)])
|
rows.push([ayah_no, grep(res)])
|
||||||
|
|
|
@ -6,6 +6,10 @@ require File.join(lib_dir, "quran", "json")
|
||||||
require "optparse"
|
require "optparse"
|
||||||
require "nokogiri"
|
require "nokogiri"
|
||||||
|
|
||||||
|
##
|
||||||
|
# Provide short access to 'Quran::JSON::Cmd::Pull'
|
||||||
|
include Quran::JSON
|
||||||
|
|
||||||
##
|
##
|
||||||
# Grep for ayah content
|
# Grep for ayah content
|
||||||
def grep(res)
|
def grep(res)
|
||||||
|
@ -15,16 +19,10 @@ def grep(res)
|
||||||
html.css(sel).map { _1.text.strip.gsub(/^[0-9]+\.\s*/, "") }
|
html.css(sel).map { _1.text.strip.gsub(/^[0-9]+\.\s*/, "") }
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
|
||||||
# CLI parser
|
|
||||||
def parse_cli(argv)
|
|
||||||
Quran::JSON::Pull.cli(argv)
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# main
|
# main
|
||||||
def main(argv)
|
def main(argv)
|
||||||
cmd = Quran::JSON::Pull.new parse_cli(argv)
|
cmd = Cmd::Pull.new(argv)
|
||||||
cmd.keepalive do
|
cmd.keepalive do
|
||||||
1.upto(114) do |surah_no|
|
1.upto(114) do |surah_no|
|
||||||
if cmd.keep?(surah_no)
|
if cmd.keep?(surah_no)
|
||||||
|
|
Loading…
Reference in a new issue