Add Cmd::Pull

This commit is contained in:
0x1eef 2023-03-27 01:47:23 -03:00
parent 880eb64897
commit e01d64b4a2
8 changed files with 127 additions and 155 deletions

View file

@ -16,12 +16,12 @@ AllCops:
- bin/*
##
# Enabled cops
# Enabled
Style/FrozenStringLiteralComment:
Enabled: true
##
# Disabled cops
# Disabled
Layout/MultilineMethodCallIndentation:
Enabled: false
Layout/ArgumentAlignment:

View file

@ -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

View file

@ -3,6 +3,6 @@
module Quran
module JSON
require_relative "json/cmd"
require_relative "json/pull"
require_relative "json/cmd/pull"
end
end

View file

@ -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

View 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

View file

@ -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

View file

@ -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)])

View file

@ -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)