quran-audio 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd6892ac4ea40e4ceedcf5596e92bb06bcd578db055b16acf793cec19dca277f
4
- data.tar.gz: 942914a841bd747cbcd11fd8af1666aef716d48996789438acac8b5cbdd08cb9
3
+ metadata.gz: 709a79351be5539a80a26a13ac39b41336b6a084cc14e56d476e5cd203090ab6
4
+ data.tar.gz: 7a0e5403541389a206d28f98bf53756a33ef672ad2bbc7162378efd59080642e
5
5
  SHA512:
6
- metadata.gz: b732e4378bf21f7d7341f68db747e2fae0dcee83ad7d0b5235b602ab3a7439daa6f1311b0d1a0f7a6a19ca2537fff21280d58ee9d5c881c7ae11f5aabd94628a
7
- data.tar.gz: 77b4d19899be0bc4041a4d087fcad940a5e624f64559fe0ae024009378f1b7cb5d4579eb6446038f31bd4e41cadf7388101ff15deab3f0eb1cee42d74f8406a7
6
+ metadata.gz: 655fda01723b31bd0d125f886a1b4695d6f16f8ae6bc5b3fac69c12019954c059f1a0fad0987e4d417e689d818400696a11dfa4431002cbcf4d9151f3c41640e
7
+ data.tar.gz: ede8a0dee97e2c33ddb78314bf4004ab8e785cf6b761cb7b9aea2c1ce03e30d7bbc88b7c0dfc0eeca96c5ac23b013f767b062f415eb3d2ed6608da600fd76554
data/README.md CHANGED
@@ -19,15 +19,14 @@ An example path:
19
19
  * **~/.local/share/quran-audio/mp3/yassin/** <br>
20
20
  Contains recitations by Sahl Yassin
21
21
 
22
- ## Usage
22
+ ## Install
23
23
 
24
- # Clone
25
- git clone https://github.com/ReflectsLight/quran-audio
26
- cd quran-audio
24
+ quran-audio is available via rubygems.org:
27
25
 
28
- # Install
29
- gem install quran-audio
30
- quran-audio --help
26
+ user@localhost$ gem install quran-audio
27
+ user@localhost$ quran-audio --help
28
+ user@localhost$ quran-audio ls --help
29
+ user@localhost$ quran-audio pull --help
31
30
 
32
31
  ## Thanks
33
32
 
data/bin/quran-audio CHANGED
@@ -1,17 +1,28 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- libexec = File.realpath File.join(__dir__, "..", "libexec", "quran-audio")
5
- case ARGV[0]
6
- when "pull"
7
- Process.spawn File.join(libexec, "pull"), *ARGV[1..]
4
+ def wait
8
5
  Process.wait
9
- when "ls"
10
- Process.spawn File.join(libexec, "ls"), *ARGV[1..]
11
- Process.wait
12
- else
13
- warn "Usage: quran-audio [COMMAND] [OPTIONS]\n\n" \
14
- "Commands:\n" \
15
- " pull Pull MP3 files from everyayah.com\n" \
16
- " ls List reciters\n" \
6
+ rescue Interrupt
7
+ retry
8
+ end
9
+
10
+ def main(argv)
11
+ libexec = File.realpath File.join(__dir__, "..", "libexec", "quran-audio")
12
+ case argv[0]
13
+ when "pull"
14
+ Process.spawn File.join(libexec, "pull"), *ARGV[1..]
15
+ Process.wait
16
+ when "ls"
17
+ Process.spawn File.join(libexec, "ls"), *ARGV[1..]
18
+ Process.wait
19
+ else
20
+ warn "Usage: quran-audio [COMMAND] [OPTIONS]\n\n" \
21
+ "Commands:\n" \
22
+ " pull Pull MP3 files from everyayah.com\n" \
23
+ " ls List reciters\n" \
24
+ end
25
+ rescue Interrupt
26
+ wait
17
27
  end
28
+ main(ARGV)
@@ -3,19 +3,19 @@
3
3
  module Quran::Audio
4
4
  class Command::Ls < Command
5
5
  set_banner usage: "quran-audio ls [OPTIONS]",
6
- description: "List reciters"
6
+ description: "List recitations"
7
7
 
8
8
  def run
9
- authors = Ryo.from_json(path: File.join(dir.datadir, "authors.json"))
10
- template = File.binread(File.join(dir.datadir, "erb", "author.txt.erb"))
11
- render(authors, template)
9
+ recitations = Ryo.from_json(path: File.join(dir.datadir, "recitations.json"))
10
+ template = File.binread(File.join(dir.datadir, "erb", "recitation.erb"))
11
+ render(recitations, template)
12
12
  end
13
13
 
14
14
  private
15
15
 
16
- def render(authors, template)
17
- puts Ryo.each(authors).map { |switch, author|
18
- ERB.new(template).result_with_hash({switch:, author: Ryo(author)})
16
+ def render(recitations, template)
17
+ puts Ryo.each(recitations).map { |switch, recitation|
18
+ ERB.new(template).result_with_hash({switch:, recitation: Ryo(recitation)})
19
19
  }.join("\n")
20
20
  end
21
21
  end
@@ -4,44 +4,47 @@ module Quran::Audio
4
4
  class Command::Pull < Command
5
5
  set_banner usage: "quran-audio pull [OPTIONS]",
6
6
  description: "Pull MP3 files from everyayah.com"
7
- set_option "-a AUTHOR", "--author AUTHOR", "An author's name"
7
+ set_option "-r RECITATION", "--recitation RECITATION", "A recitation's name", default: "alafasy"
8
8
  set_option "-b BITRATE", "--bitrate BITRATE", "MP3 bitrate"
9
- set_option "-s NUMBERS", "--surahs NUMBERS", "Comma-separated list of surah IDs", as: Array
10
- set_option "-d SECONDS", "--delay", "Delay between requests, in seconds", as: Float
11
- set_default author: "alafasy", surahs: (1..114).to_a, delay: 0.5
12
-
13
- attr_reader :http
9
+ set_option "-s NUMBERS", "--surahs NUMBERS", "Comma-separated list of surah IDs", as: Array, default: (1..114)
10
+ set_option "-d SECONDS", "--delay", "Delay between requests, in seconds", as: Float, default: 0.5
14
11
 
15
12
  def initialize(...)
16
13
  super
17
14
  @http = Net::HTTP.new("everyayah.com", 443).tap { _1.use_ssl = true }
18
- @surah_length = Ryo.from_json(path: File.join(dir.datadir, "surah_length.json"))
19
15
  end
20
16
 
21
17
  def run
18
+ summary(recitations[recitation])
19
+ start(surahs)
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :http
25
+
26
+ def start(surahs)
22
27
  surahs.each do |surah|
23
- 1.upto(surah_length(surah)) do |ayah|
24
- mp3 = MP3.new(author:, surah:, ayah:, bitrate:)
25
- pull(mp3, options.delay) unless File.exist?(mp3.local_path)
26
- percent = sprintf("%.2f", (ayah / surah_length(surah).to_f) * 100)
28
+ 1.upto(sizeof[surah]) do |ayah|
29
+ mp3 = MP3.new(recitation:, surah:, ayah:, bitrate:)
30
+ pull(mp3, delay) unless File.exist?(mp3.local_path)
31
+ percent = sprintf("%.2f", (ayah / sizeof[surah].to_f) * 100)
27
32
  line.rewind.print "Surah #{surah} [#{percent}%]"
28
33
  end
29
34
  line.end
30
35
  end
31
36
  end
32
37
 
33
- private
34
-
35
38
  def pull(mp3, delay, interrupt: false)
36
39
  res = http.get(mp3.remote_path)
37
40
  write(mp3, res, interrupt:)
38
41
  sleep(delay)
39
42
  rescue Interrupt
40
- line.end.rewind.print("Wait for a graceful exit").end
43
+ line.end.rewind.print("SIGINT: exiting cleanly, please wait").end
41
44
  pull(mp3, delay, interrupt: true)
42
45
  rescue SocketError, SystemCallError, Net::OpenTimeout => e
43
46
  line.end.rewind.print("#{e.class}: retry")
44
- interrupt ? throw(:interrupt, true) : pull(mp3, delay)
47
+ interrupt ? abort! : pull(mp3, delay)
45
48
  end
46
49
 
47
50
  def write(mp3, res, interrupt:)
@@ -49,14 +52,31 @@ module Quran::Audio
49
52
  when Net::HTTPOK
50
53
  mkdir_p File.dirname(mp3.local_path)
51
54
  File.binwrite(mp3.local_path, res.body)
52
- throw(:interrupt, true) if interrupt
55
+ abort! if interrupt
53
56
  else
54
- puts "error #{res.body}"
57
+ line.end.print("error: unexpected response (#{res.class})")
58
+ abort!
55
59
  end
56
60
  end
57
61
 
58
- def surah_length(surah)
59
- @surah_length[surah.to_s]
62
+ def summary(r)
63
+ line
64
+ .rewind
65
+ .print("Recitation".ljust(12), r.name).end
66
+ .print("Directory".ljust(12), format(r.destdir, sharedir: dir.sharedir))
67
+ .end.end
68
+ end
69
+
70
+ def sizeof
71
+ @sizeof ||= Ryo.from_json(path: File.join(dir.datadir, "sizeof.json"))
72
+ end
73
+
74
+ def recitations
75
+ @recitations ||= Ryo.from_json(path: File.join(dir.datadir, "recitations.json"))
76
+ end
77
+
78
+ def abort!
79
+ throw(:abort, 1)
60
80
  end
61
81
  end
62
82
  end
@@ -1,23 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quran::Audio
4
- class MP3 < Struct.new(:author, :surah, :ayah, :bitrate, keyword_init: true)
5
- def initialize(author:, **kw)
6
- super(author: authors[author], **kw)
4
+ ##
5
+ # {Quran::Audio::MP3 Quran::Audio::MP3} provides
6
+ # an abstract interface around an MP3 file, and
7
+ # within the context of the quran-audio project.
8
+ class MP3 < Struct.new(:recitation, :surah, :ayah, :bitrate, keyword_init: true)
9
+ def initialize(recitation:, **kw)
10
+ super(recitation: recitations[recitation], **kw)
7
11
  end
8
12
 
13
+ ##
14
+ # @return [String]
15
+ # Returns the bitrate of an MP3 file
9
16
  def bitrate
10
- super || author.default_bitrate
17
+ super || recitation.default_bitrate
11
18
  end
12
19
 
20
+ ##
21
+ # @return [String]
22
+ # Returns the path to an MP3 file on a remote HTTP server
13
23
  def remote_path
14
24
  filename = [surah.to_s.rjust(3, "0"), ayah.to_s.rjust(3, "0"), ".mp3"].join
15
- File.join format(author.remote_path, bitrate:), filename
25
+ File.join format(recitation.path, bitrate:), filename
16
26
  end
17
27
 
28
+ ##
29
+ # @return [String]
30
+ # Returns the path to an MP3 file on disk
18
31
  def local_path
19
32
  File.join(
20
- format(author.dest_dir, sharedir:),
33
+ format(recitation.destdir, sharedir:),
21
34
  surah.to_s,
22
35
  "#{ayah}.mp3"
23
36
  )
@@ -25,8 +38,8 @@ module Quran::Audio
25
38
 
26
39
  private
27
40
 
28
- def authors
29
- @authors ||= Ryo.from_json(path: File.join(datadir, "authors.json"))
41
+ def recitations
42
+ @recitations ||= Ryo.from_json(path: File.join(datadir, "recitations.json"))
30
43
  end
31
44
 
32
45
  def sharedir
@@ -7,5 +7,8 @@ def main(argv)
7
7
  .new(argv)
8
8
  .run
9
9
  end
10
- interrupt = catch(:interrupt) { main(ARGV) }
11
- exit(1) if interrupt
10
+ excode = catch(:abort) {
11
+ main(ARGV)
12
+ 0
13
+ }
14
+ exit excode
@@ -1 +1 @@
1
- v0.3.1
1
+ v0.3.3
@@ -0,0 +1,4 @@
1
+ <%= Paint[recitation.name, :bold] %>
2
+ From <%= recitation.origin %>
3
+ Bitrates <%= recitation.available_bitrates.join(", ") %> (default = <%= recitation.default_bitrate %>)
4
+ CLI --recitation <%= switch %>
@@ -0,0 +1,26 @@
1
+ {
2
+ "alafasy": {
3
+ "name": "Mishari bin Rashed Alafasy",
4
+ "origin": "Kuwait",
5
+ "available_bitrates": [128, 64],
6
+ "default_bitrate": 128,
7
+ "path": "/data/Alafasy_%{bitrate}kbps/",
8
+ "destdir": "%{sharedir}/mp3/alafasy/"
9
+ },
10
+ "alajmi": {
11
+ "name": "Ahmad bin Ali Al-Ajmi",
12
+ "origin": "Saudi Arabia",
13
+ "available_bitrates": [128],
14
+ "default_bitrate": 128,
15
+ "path": "/data/ahmed_ibn_ali_al_ajamy_%{bitrate}kbps/",
16
+ "destdir": "%{sharedir}/mp3/alajmi/"
17
+ },
18
+ "yassin": {
19
+ "name": "Sahl Yassin",
20
+ "origin": "Saudi Arabia",
21
+ "available_bitrates": [128],
22
+ "default_bitrate": 128,
23
+ "path": "/data/Sahl_Yassin_%{bitrate}kbps/",
24
+ "destdir": "%{sharedir}/mp3/yassin/"
25
+ }
26
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quran-audio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - '0x1eef'
@@ -113,12 +113,12 @@ files:
113
113
  - libexec/quran-audio/ls
114
114
  - libexec/quran-audio/pull
115
115
  - share/quran-audio/VERSION
116
- - share/quran-audio/data/authors.json
117
- - share/quran-audio/data/erb/author.txt.erb
118
- - share/quran-audio/data/surah_length.json
116
+ - share/quran-audio/data/erb/recitation.erb
117
+ - share/quran-audio/data/recitations.json
118
+ - share/quran-audio/data/sizeof.json
119
119
  homepage: https://github.com/ReflectsLight/quran-audio#readme
120
120
  licenses:
121
- - BSD0L
121
+ - GPL-3.0-or-later
122
122
  metadata: {}
123
123
  post_install_message:
124
124
  rdoc_options: []
@@ -1,26 +0,0 @@
1
- {
2
- "alafasy": {
3
- "name": "Mishari bin Rashed Alafasy",
4
- "nationality": "Kuwait",
5
- "available_bitrates": [128, 64],
6
- "default_bitrate": 128,
7
- "remote_path": "/data/Alafasy_%{bitrate}kbps/",
8
- "dest_dir": "%{sharedir}/mp3/alafasy/"
9
- },
10
- "alajmi": {
11
- "name": "Ahmad bin Ali Al-Ajmi",
12
- "nationality": "Saudi Arabia",
13
- "available_bitrates": [128],
14
- "default_bitrate": 128,
15
- "remote_path": "/data/ahmed_ibn_ali_al_ajamy_%{bitrate}kbps/",
16
- "dest_dir": "%{sharedir}/mp3/alajmi/"
17
- },
18
- "yassin": {
19
- "name": "Sahl Yassin",
20
- "nationality": "Saudi Arabia",
21
- "available_bitrates": [128],
22
- "default_bitrate": 128,
23
- "remote_path": "/data/Sahl_Yassin_%{bitrate}kbps/",
24
- "dest_dir": "%{sharedir}/mp3/yassin/"
25
- }
26
- }
@@ -1,4 +0,0 @@
1
- <%= Paint[author.name, :bold] %>
2
- From <%= author.nationality %>
3
- Bitrates <%= author.available_bitrates.join(", ") %> (default = <%= author.default_bitrate %>)
4
- CLI --author <%= switch %>