votd 3.0.2 → 4.0.0

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/LICENSE +1 -1
  4. data/README.md +24 -22
  5. data/exe/votd +7 -0
  6. data/lib/votd/base.rb +37 -22
  7. data/lib/votd/bible_gateway.rb +80 -72
  8. data/lib/votd/cli.rb +117 -0
  9. data/lib/votd/esvbible.rb +13 -49
  10. data/lib/votd/fetch_error.rb +8 -0
  11. data/lib/votd/helper/command_line.rb +9 -9
  12. data/lib/votd/helper/text.rb +9 -7
  13. data/lib/votd/netbible.rb +33 -29
  14. data/lib/votd/ourmanna.rb +45 -0
  15. data/lib/votd/version.rb +3 -1
  16. data/lib/votd/votd_error.rb +4 -0
  17. data/lib/votd.rb +42 -0
  18. metadata +37 -197
  19. data/.github/workflows/ruby.yml +0 -20
  20. data/.gitignore +0 -19
  21. data/.rspec +0 -2
  22. data/.ruby-version +0 -1
  23. data/.travis.yml +0 -11
  24. data/.yardopts +0 -7
  25. data/CONTRIBUTING.md +0 -46
  26. data/Gemfile +0 -4
  27. data/Guardfile +0 -10
  28. data/Rakefile +0 -13
  29. data/TODO.md +0 -5
  30. data/bin/votd +0 -25
  31. data/lib/votd/helper/helper.rb +0 -6
  32. data/spec/fixtures/base/base.html +0 -5
  33. data/spec/fixtures/base/base.txt +0 -1
  34. data/spec/fixtures/base/base_custom.html +0 -1
  35. data/spec/fixtures/base/base_custom.txt +0 -1
  36. data/spec/fixtures/bible_gateway/bible_gateway.html +0 -5
  37. data/spec/fixtures/bible_gateway/bible_gateway.rss +0 -33
  38. data/spec/fixtures/bible_gateway/bible_gateway.txt +0 -1
  39. data/spec/fixtures/bible_gateway/bible_gateway_custom.html +0 -1
  40. data/spec/fixtures/bible_gateway/bible_gateway_custom.txt +0 -1
  41. data/spec/fixtures/bible_gateway/bible_gateway_nlt.rss +0 -34
  42. data/spec/fixtures/bible_gateway/bible_gateway_with_partial.rss +0 -32
  43. data/spec/fixtures/esvbible/esvbible.html +0 -5
  44. data/spec/fixtures/esvbible/esvbible.rss +0 -19
  45. data/spec/fixtures/esvbible/esvbible.txt +0 -1
  46. data/spec/fixtures/esvbible/esvbible_custom.html +0 -1
  47. data/spec/fixtures/esvbible/esvbible_custom.txt +0 -1
  48. data/spec/fixtures/esvbible/esvbible_with_partial.rss +0 -19
  49. data/spec/fixtures/netbible/netbible.html +0 -5
  50. data/spec/fixtures/netbible/netbible.json +0 -14
  51. data/spec/fixtures/netbible/netbible.txt +0 -1
  52. data/spec/fixtures/netbible/netbible_custom.html +0 -1
  53. data/spec/fixtures/netbible/netbible_custom.txt +0 -1
  54. data/spec/fixtures/netbible/netbible_with_html.json +0 -1
  55. data/spec/fixtures/netbible/netbible_with_partial.json +0 -8
  56. data/spec/lib/votd/base_spec.rb +0 -96
  57. data/spec/lib/votd/bible_gateway_spec.rb +0 -161
  58. data/spec/lib/votd/esvbible_spec.rb +0 -127
  59. data/spec/lib/votd/helper/command_line_spec.rb +0 -21
  60. data/spec/lib/votd/helper/helper_spec.rb +0 -3
  61. data/spec/lib/votd/helper/text_spec.rb +0 -32
  62. data/spec/lib/votd/netbible_spec.rb +0 -135
  63. data/spec/lib/votd/version_spec.rb +0 -7
  64. data/spec/lib/votd/votd_error_spec.rb +0 -5
  65. data/spec/lib/votd_spec.rb +0 -4
  66. data/spec/spec_helper.rb +0 -26
  67. data/votd.gemspec +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d29237ca3f2e6078e0bfea778aabe4881b69fe4c71626faa4bf6faa845d68077
4
- data.tar.gz: 62bb616cc7ac61f2a7dff356b564fe5922c8b0c595631bc9df0365bb583860e5
3
+ metadata.gz: 33707db5963490790f5e1eaf429834d53f7658ee179844f2ca46f47bfa62e4e1
4
+ data.tar.gz: 0be40cbe72ae2e360d50667ea336ce85ecf051725ac16251cbe9ac111ec32f73
5
5
  SHA512:
6
- metadata.gz: 18ba480318c6d9e04ae7aa4f83641a6f8c28cf2e4621779f4bf049c5e1fb6027a155240dad3073e454870c604d6acbdd98b5b065a98e21fc4e28b84ecc2c493c
7
- data.tar.gz: 2fecf83462199f131a1d521a865e51b93717084c05ddee5a3d2b3b764df3262d7cb22f66a87e452c1a2948d63bb6a1ce787cf39a4da7aa769a281cd1efb8cdda
6
+ metadata.gz: 5072c11ffa7c8cfa42d798d132912f84412f534557e28681c5a22573543b2a4e2533b09121f5d48c92c245ab128b208aa91e46bc5662f96f8173bf9c7ebc9ac8
7
+ data.tar.gz: 9b0320cd4b8baea0f6670922ccec324b028d587cb90a355d62def18d4e52262ebb39f84f1a5f17810ba2b731e588bffca502db8631d5f0175f0d6667cbc0079c
data/CHANGELOG.md CHANGED
@@ -1,6 +1,27 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 4.0.0
5
+ -----
6
+ *March 4, 2026*
7
+
8
+ * Upgrade Ruby from 2.6.5 (EOL) to 3.4.8; require >= 3.3
9
+ * Fix BibleGateway and NetBible API endpoints (http → https)
10
+ * Add `Votd::OurManna` provider — free, no-auth JSON API from ourmanna.com (NIV)
11
+ * **Breaking:** Replace stub CLI with Thor-based CLI. The `votd` command now
12
+ requires a subcommand: `votd verse` (with `--provider`, `--translation`,
13
+ `--format` options), `votd version`, `votd help`.
14
+ * Deprecate `Votd::ESVBible` — the gnpcb.org endpoint has been shut down.
15
+ `ESVBible.new` now raises `Votd::VotdError` with a message directing users
16
+ to `Votd::BibleGateway.new(:esv)` as a replacement.
17
+ * **Breaking:** Providers now raise `Votd::FetchError` on any failure instead
18
+ of silently falling back to defaults. Original exception preserved as `#cause`.
19
+ * Add `Votd.logger` and `Votd.on_error` callback for error observability
20
+ * Add YARD documentation to all public classes and methods
21
+ * Modernize gemspec: explicit file list, bounded dependencies, RubyGems metadata
22
+ * Move gem executable from `bin/` to `exe/` (Bundler convention)
23
+ * Add GitHub Actions CI and release workflows with OIDC trusted publishing
24
+
4
25
  3.0.1
5
26
  -----
6
27
  *November 27, 2019*
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2014 Christopher Clarke, Stephen Clarke
1
+ Copyright (c) 2012-2026 Stephen Clarke
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # VotD - (Bible) Verse of the Day
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/doctorbh/votd.png?branch=master)](http://travis-ci.org/Sevenview/votd)
4
- [![Code Climate](https://codeclimate.com/github/sevenview/votd.png)](https://codeclimate.com/github/sevenview/votd)
3
+ [![Ruby](https://github.com/sevenview/votd/actions/workflows/ruby.yml/badge.svg)](https://github.com/sevenview/votd/actions/workflows/ruby.yml)
5
4
 
6
5
  VotD (Verse of the Day) is a Ruby Gem that wraps various web services that generate
7
6
  daily Bible Verses.
@@ -9,9 +8,9 @@ daily Bible Verses.
9
8
 
10
9
  Currently the gem supports three VotD web services:
11
10
 
12
- * [Bible Gateway](http://www.biblegateway.com) - Multiple Translations
13
- * [Bible.org](http://labs.bible.org) - NETBible Translation
14
- * [ESV Bible Web Service](http://www.esvapi.org/) - ESV Translation
11
+ * [Bible Gateway](https://www.biblegateway.com) - Multiple Translations
12
+ * [Bible.org](https://labs.bible.org) - NETBible Translation
13
+ * [Our Manna](https://ourmanna.com) - NIV Translation
15
14
 
16
15
  If you are able to contribute modules for any of these, please see our [CONTRIBUTING](https://github.com/Sevenview/votd/blob/master/CONTRIBUTING.md) file. Let us know before you begin work in case someone else has a module in-progress.
17
16
 
@@ -99,16 +98,19 @@ the day:
99
98
  votd = Votd::NetBible.new
100
99
  ```
101
100
 
102
- ## Votd::ESVBible
101
+ ## Votd::OurManna
103
102
 
104
- To use the ESV Bible Web Service, which generates a English Standard Version
105
- verse of the day:
103
+ To use the Our Manna service, which generates an NIV verse of the day:
106
104
 
107
105
  ```ruby
108
106
  require 'votd'
109
- votd = Votd::BibleGateway.new
107
+ votd = Votd::OurManna.new
110
108
  ```
111
109
 
110
+ ## Votd::ESVBible
111
+
112
+ `Votd::ESVBible` is no longer supported — the upstream endpoint has been shut down. Use `Votd::BibleGateway.new(:esv)` instead.
113
+
112
114
  ### Outputting HTML
113
115
 
114
116
  You can use the built-in formatted HTML:
@@ -163,7 +165,17 @@ This returns the custom formatted text, or you can call the `.to_text` method
163
165
  when ready, and your custom text will be output.
164
166
 
165
167
  ## Command Line
166
- For command-line usage see [here](https://github.com/Sevenview/votd/wiki/Shell-Tool)
168
+
169
+ ```bash
170
+ votd verse # BibleGateway NIV (default)
171
+ votd verse -p netbible # NetBible provider
172
+ votd verse -p ourmanna # OurManna provider
173
+ votd verse --translation kjv # BibleGateway with KJV
174
+ votd verse -f html # HTML output
175
+ votd verse -f json # JSON output
176
+ votd verse --help # Show options
177
+ votd version # Show gem version
178
+ ```
167
179
 
168
180
  ## Documentation
169
181
 
@@ -196,16 +208,6 @@ See our [CHANGELOG](https://github.com/Sevenview/votd/blob/master/CHANGELOG.md)
196
208
 
197
209
  See our [TODO](https://github.com/Sevenview/votd/blob/master/TODO.md) file.
198
210
 
199
- ## Authors
200
-
201
- Christopher Clarke <chris@seven7.ca>
202
-
203
- Stephen Clarke <steve@sevenview.ca>
204
-
205
- [Sebastian Hirsch](https://github.com/SebastianHirsch) (ESV)
206
-
207
- ## Copyright
208
-
209
- (The MIT License)
211
+ ## License
210
212
 
211
- &copy; 2012-2019 Christopher Clarke, Stephen Clarke. See [LICENSE](https://github.com/Sevenview/votd/blob/master/LICENSE) for details.
213
+ MIT see [LICENSE](https://github.com/Sevenview/votd/blob/master/LICENSE) for details.
data/exe/votd ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "votd"
5
+ require "votd/cli"
6
+
7
+ Votd::CLI.start(ARGV)
data/lib/votd/base.rb CHANGED
@@ -1,10 +1,10 @@
1
- require 'votd/helper/text'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Votd
4
4
  # This is the base class that all Votd lookup modules inherit from.
5
- # It provides default values for the Votd in the event of lookup failure.
6
5
  # Child classes should override the {#get_votd} method to implement their
7
- # specific lookup function.
6
+ # specific lookup function. Errors during fetch are raised as {FetchError}
7
+ # and reported via {Votd.logger} and {Votd.on_error}.
8
8
  class Base
9
9
  # @example
10
10
  # votd.text # "For by grace you are saved through faith..."
@@ -62,18 +62,15 @@ module Votd
62
62
  # is provided
63
63
  DEFAULT_BIBLE_VERSION_NAME = "King James Version"
64
64
 
65
+ # The default link to use if none is provided by the VotD service
65
66
  DEFAULT_LINK = "https://www.biblegateway.com/passage/?search=John+3%3A16&version=KJV"
66
67
 
67
68
  # Initializes the class and retrieves the verse of the day.
68
69
  # @return [Base]
69
70
  def initialize
70
- @text = ""
71
- @reference = ""
72
- @copyright = nil
73
- @date = Date.today
71
+ @date = Date.today
74
72
  @custom_html = nil
75
73
  @custom_text = nil
76
- @link = nil
77
74
  get_votd
78
75
  end
79
76
 
@@ -90,11 +87,14 @@ module Votd
90
87
  #
91
88
  # @return [String] the VotD formatted as HTML
92
89
  def to_html
93
- default_html = "<p class=\"votd-text\">#{@text}</p>\n"
94
- default_html << "<p>\n"
95
- default_html << "<span class=\"votd-reference\"><strong>#{@reference}</strong></span>\n"
96
- default_html << "<span class=\"votd-version\"><em>(#{@version})</em></span>\n"
97
- default_html << "</p>\n"
90
+ default_html = [
91
+ %(<p class="votd-text">#{@text}</p>),
92
+ "<p>",
93
+ %(<span class="votd-reference"><strong>#{@reference}</strong></span>),
94
+ %(<span class="votd-version"><em>(#{@version})</em></span>),
95
+ "</p>",
96
+ ""
97
+ ].join("\n")
98
98
  @custom_html ||= default_html
99
99
  end
100
100
 
@@ -114,7 +114,7 @@ module Votd
114
114
  # @yield [votd] the VotD itself
115
115
  # @yieldparam [Base] votd the VotD itself
116
116
  # @yieldreturn [String] the VotD formatted as custom HTML
117
- # @raise {VotdError} when called without block format
117
+ # @raise [VotdError] when called without block format
118
118
  def custom_html
119
119
  if block_given?
120
120
  @custom_html = yield(self)
@@ -149,7 +149,7 @@ module Votd
149
149
  # @yield [votd] the VotD itself
150
150
  # @yieldparam [Base] votd the VotD itself
151
151
  # @yieldreturn [String] the VotD formatted as custom text
152
- # @raise {VotdError} when called without block format
152
+ # @raise [VotdError] when called without block format
153
153
  def custom_text
154
154
  if block_given?
155
155
  @custom_text = yield(self)
@@ -158,22 +158,37 @@ module Votd
158
158
  end
159
159
  end
160
160
 
161
- protected
161
+ private
162
+
162
163
  # Gets the VotD. For {Votd::Base} this will return default values and can be
163
164
  # used in the event of an exception thrown when getting data from live web
164
- # services in subclasses of {Votd::Base}
165
+ # services in subclasses of {Votd::Base}.
166
+ # Subclasses override this to fetch from their respective APIs.
167
+ # @return [void]
165
168
  def get_votd
166
169
  set_defaults
167
170
  end
168
171
 
172
+ # Sets all attributes to their default values.
173
+ # @return [void]
169
174
  def set_defaults
170
- @text = DEFAULT_BIBLE_TEXT
171
- @reference = DEFAULT_BIBLE_REFERENCE
172
- @version = DEFAULT_BIBLE_VERSION
175
+ @text = DEFAULT_BIBLE_TEXT
176
+ @reference = DEFAULT_BIBLE_REFERENCE
177
+ @version = DEFAULT_BIBLE_VERSION
173
178
  @version_name = DEFAULT_BIBLE_VERSION_NAME
174
- @link = DEFAULT_LINK
175
- @copyright = nil
179
+ @link = DEFAULT_LINK
180
+ @copyright = nil
176
181
  end
177
182
 
183
+ # Logs the error, invokes the on_error callback, and raises a FetchError.
184
+ # @param error [Exception] the original exception
185
+ # @param message [String] a human-readable description of the failure
186
+ # @raise [FetchError]
187
+ def report_and_raise(error, message)
188
+ wrapped = FetchError.new("#{message}: #{error.message}")
189
+ Votd.logger&.error("#{self.class.name} - #{error.class}: #{error.message}")
190
+ Votd.on_error_callback&.call(self.class, wrapped)
191
+ raise wrapped
192
+ end
178
193
  end
179
194
  end
@@ -1,52 +1,62 @@
1
- require 'feedjira'
2
- require 'votd/helper/text'
1
+ # frozen_string_literal: true
2
+
3
+ require "feedjira"
3
4
 
4
5
  module Votd
5
6
  # Retrieves a Verse of the Day from biblegateway.com using a variety
6
7
  # of translations.
7
8
  #
8
- # Default translation is NIV (New International Version)
9
+ # Default translation is NIV (New International Version).
9
10
  #
10
- # docs: http://www.biblegateway.com/usage/votd/docs/
11
+ # @example Fetch the default (NIV) verse of the day
12
+ # votd = Votd::BibleGateway.new
13
+ # votd.text # => "For God so loved the world..."
14
+ # votd.reference # => "John 3:16"
11
15
  #
12
- # version list: http://www.biblegateway.com/usage/linking/versionslist.php
13
-
16
+ # @example Fetch the KJV verse of the day
17
+ # votd = Votd::BibleGateway.new(:kjv)
18
+ #
19
+ # @see https://www.biblegateway.com/usage/votd/docs/ BibleGateway VotD docs
20
+ # @see https://www.biblegateway.com/usage/linking/versionslist.php Version list
14
21
  class BibleGateway < Votd::Base
15
- # These are the English translations that are copyright-approved for Bible
16
- # Gateway VotD as of November 2019.
17
- BIBLE_VERSIONS = {
18
- amp: { name: 'Amplified Bible', id: 45 },
19
- asv: { name: 'American Standard Version', id: 8 },
20
- ceb: { name: 'Common English Bible', id: 105 },
21
- darby: { name: 'Darby Translation', id: 16 },
22
- esv: { name: 'English Standard Version', id: 47 },
23
- esvu: { name: 'English Standard Version Anglicised', id: 166 },
24
- gw: { name: "God's Word Translation", id: 158 },
25
- hcsb: { name: 'Holman Christian Standard Bible', id: 77 },
26
- kjv: { name: 'King James Version', id: 9 },
27
- leb: { name: 'Lexham English Bible', id: 165 },
28
- nasb: { name: 'New American Standard Bible', id: 49 },
29
- nirv: { name: "New International Reader's Version", id: 76 },
30
- niv: { name: 'New International Version', id: 31 },
31
- nivuk: { name: 'New International Version - UK', id: 64 },
32
- nlt: { name: 'New Living Translation', id: 51 },
33
- nlv: { name: 'New Life Version', id: 74 },
34
- phillips: { name: 'J.B. Phillips New Testament', id: 164 },
35
- we: { name: 'Worldwide English (New Testament)', id: 73 },
36
- wyc: { name: 'Wycliffe Bible', id: 53 },
37
- ylt: { name: "Young's Literal Translation", id: 15 }
22
+ # These are the English translations that are copyright-approved for Bible
23
+ # Gateway VotD as of November 2019.
24
+ BIBLE_VERSIONS = {
25
+ amp: {name: "Amplified Bible", id: 45},
26
+ asv: {name: "American Standard Version", id: 8},
27
+ ceb: {name: "Common English Bible", id: 105},
28
+ darby: {name: "Darby Translation", id: 16},
29
+ esv: {name: "English Standard Version", id: 47},
30
+ esvu: {name: "English Standard Version Anglicised", id: 166},
31
+ gw: {name: "God's Word Translation", id: 158},
32
+ hcsb: {name: "Holman Christian Standard Bible", id: 77},
33
+ kjv: {name: "King James Version", id: 9},
34
+ leb: {name: "Lexham English Bible", id: 165},
35
+ nasb: {name: "New American Standard Bible", id: 49},
36
+ nirv: {name: "New International Reader's Version", id: 76},
37
+ niv: {name: "New International Version", id: 31},
38
+ nivuk: {name: "New International Version - UK", id: 64},
39
+ nlt: {name: "New Living Translation", id: 51},
40
+ nlv: {name: "New Life Version", id: 74},
41
+ phillips: {name: "J.B. Phillips New Testament", id: 164},
42
+ we: {name: "Worldwide English (New Testament)", id: 73},
43
+ wyc: {name: "Wycliffe Bible", id: 53},
44
+ ylt: {name: "Young's Literal Translation", id: 15}
38
45
  }
39
46
 
40
- # The URI of the API gateway
41
- URI = "http://www.biblegateway.com/usage/votd/rss/votd.rdf?"
47
+ # The URL of the API gateway
48
+ ENDPOINT_URL = "https://www.biblegateway.com/usage/votd/rss/votd.rdf?"
42
49
 
43
50
  # Regular expression for pulling the copyright out of the Bible text
44
- COPYRIGHT_TEXT_REGEX = /(Brought to you by BibleGateway.*$)/
51
+ COPYRIGHT_TEXT_REGEX = /(Brought to you by BibleGateway.*$)/
45
52
 
46
- # Initializes the BibleGateway class
53
+ # Initializes the BibleGateway class and fetches the verse of the day.
54
+ # @param [Symbol] version the Bible translation key (e.g. +:niv+, +:kjv+, +:esv+).
55
+ # Must be a key in {BIBLE_VERSIONS}.
56
+ # @raise [InvalidBibleVersion] if the version symbol is not in {BIBLE_VERSIONS}
47
57
  # @return [BibleGateway]
48
58
  def initialize(version = :niv)
49
- raise InvalidBibleVersion unless BIBLE_VERSIONS.has_key?(version)
59
+ raise InvalidBibleVersion unless BIBLE_VERSIONS.key?(version)
50
60
 
51
61
  @version = version.to_s.upcase
52
62
  @version_number = BIBLE_VERSIONS[version][:id]
@@ -56,58 +66,56 @@ module Votd
56
66
 
57
67
  private
58
68
 
59
- # Gets the votd from the Bible Gateway RSS feed
60
- # @return [String]
69
+ # Fetches the verse of the day from the Bible Gateway RSS feed.
70
+ # Parses the feed, extracts the verse text, reference, link, and copyright.
71
+ # @raise [FetchError] if the HTTP request or feed parsing fails
72
+ # @return [void]
61
73
  def get_votd
62
- uri = "#{URI}#{@version_number}"
63
- feed = Feedjira.parse(HTTParty.get(uri).body)
64
- entry = feed.entries.first
65
- cleaned_text = clean_text(entry.content)
74
+ url = "#{ENDPOINT_URL}#{@version_number}"
75
+ feed = Feedjira.parse(HTTParty.get(url).body)
76
+ entry = feed.entries.first
77
+
78
+ stripped = strip_html_quote_entities(entry.content)
79
+ stripped = Helper::Text.strip_html_tags(stripped)
66
80
 
67
- @reference = entry.title
68
- @link = entry.entry_id
69
- @text = cleaned_text
70
- @copyright = get_copyright(entry.content)
81
+ @reference = entry.title
82
+ @link = entry.entry_id
83
+ @text = build_verse_text(stripped)
84
+ @copyright = extract_copyright(stripped)
71
85
  rescue => e
72
- # use default info for VotD
73
- set_defaults
74
- #raise e
75
- # @todo Add logging
86
+ report_and_raise(e, "Failed to fetch verse from BibleGateway")
76
87
  end
77
88
 
78
- # Cleans up the text. Removes:
79
- # - HTML quote entities
80
- # - HTML tags
81
- # - Copyright text
82
- # - Extra spaces, line breaks, etc.
83
- # @return [String]
84
- def clean_text(text)
85
- text = strip_html_quote_entities(text)
86
- text = Helper::Text.strip_html_tags(text)
87
- text = strip_copyright_text(text)
88
- text.strip!
89
+ # Builds clean verse text from HTML-stripped content.
90
+ # Removes copyright text and cleans up verse start/end punctuation.
91
+ # @param [String] stripped the HTML-stripped feed content
92
+ # @return [String] the cleaned verse text
93
+ def build_verse_text(stripped)
94
+ text = strip_copyright_text(stripped).strip
89
95
  text = Helper::Text.clean_verse_start(text)
90
- text = Helper::Text.clean_verse_end(text)
96
+ Helper::Text.clean_verse_end(text)
91
97
  end
92
98
 
93
- # Extracts copyright tag from the Bible text
94
- # @return [String]
95
- def get_copyright(text)
96
- text = strip_html_quote_entities(text)
97
- text = Helper::Text.strip_html_tags(text)
98
- text.match(COPYRIGHT_TEXT_REGEX)[1]
99
+ # Extracts the copyright notice from HTML-stripped content.
100
+ # @param [String] stripped the HTML-stripped feed content
101
+ # @return [String, nil] the copyright text, or nil if not found
102
+ def extract_copyright(stripped)
103
+ match = stripped.match(COPYRIGHT_TEXT_REGEX)
104
+ match ? match[1] : nil
99
105
  end
100
106
 
101
- # Removes HTML quote entities added by BibleGateway
102
- # @return [String]
107
+ # Removes HTML quote entities (+&ldquo;+ and +&rdquo;+) added by BibleGateway.
108
+ # @param [String] text the raw feed content
109
+ # @return [String] text with quote entities removed
103
110
  def strip_html_quote_entities(text)
104
- text.gsub(/&.dquo;/, '')
111
+ text.gsub(/&[lr]dquo;/, "")
105
112
  end
106
113
 
107
- # Removes copyright text from the Bible text
108
- # @return [String]
114
+ # Removes copyright text from the Bible text.
115
+ # @param [String] text the verse text potentially containing a copyright notice
116
+ # @return [String] text with copyright removed
109
117
  def strip_copyright_text(text)
110
- text.gsub(COPYRIGHT_TEXT_REGEX, '')
118
+ text.gsub(COPYRIGHT_TEXT_REGEX, "")
111
119
  end
112
120
  end
113
121
  end
data/lib/votd/cli.rb ADDED
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require "votd/helper/command_line"
5
+
6
+ module Votd
7
+ # Thor-based command-line interface for the votd gem.
8
+ # Provides commands to display the Bible verse of the day
9
+ # from various providers and translations.
10
+ #
11
+ # @example
12
+ # # From the shell:
13
+ # votd verse
14
+ # votd verse --provider netbible
15
+ # votd verse --provider biblegateway --translation kjv --format json
16
+ # votd version
17
+ class CLI < Thor
18
+ # @return [Boolean] true so Thor exits with status 1 on errors
19
+ def self.exit_on_failure?
20
+ true
21
+ end
22
+
23
+ desc "verse", "Display today's Bible verse of the day"
24
+ option :provider, type: :string, default: "biblegateway", aliases: "-p",
25
+ desc: "VotD provider (biblegateway, netbible, ourmanna)"
26
+ option :translation, type: :string, default: "niv",
27
+ desc: "Bible translation for BibleGateway (e.g. kjv, esv, nlt)"
28
+ option :format, type: :string, default: "text", aliases: "-f",
29
+ desc: "Output format (text, html, json)"
30
+ option :help, type: :boolean, aliases: "-h", hide: true
31
+ # Fetches and displays the verse of the day.
32
+ # @return [void]
33
+ def verse
34
+ return invoke(:help, ["verse"]) if options[:help]
35
+ votd = build_votd(options[:provider], options[:translation])
36
+ output(votd, options[:format])
37
+ rescue InvalidBibleVersion
38
+ warn "Error: Unknown translation '#{options[:translation]}'"
39
+ warn "Valid translations: #{BibleGateway::BIBLE_VERSIONS.keys.join(", ")}"
40
+ exit 1
41
+ rescue FetchError => e
42
+ warn "Error: #{e.message}"
43
+ exit 1
44
+ end
45
+
46
+ desc "version", "Show votd gem version"
47
+ # Prints the votd gem version.
48
+ # @return [void]
49
+ def version
50
+ puts "votd #{Votd::VERSION}"
51
+ end
52
+
53
+ private
54
+
55
+ # Instantiates the appropriate VotD provider.
56
+ # @param [String] provider the provider name ("biblegateway", "netbible", or "ourmanna")
57
+ # @param [String] translation the Bible translation key (only used for BibleGateway)
58
+ # @return [Base] a VotD provider instance
59
+ def build_votd(provider, translation)
60
+ case provider
61
+ when "biblegateway" then BibleGateway.new(translation.to_sym)
62
+ when "netbible" then NetBible.new
63
+ when "ourmanna" then OurManna.new
64
+ else
65
+ warn "Error: Unknown provider '#{provider}'"
66
+ warn "Valid providers: biblegateway, netbible, ourmanna"
67
+ exit 1
68
+ end
69
+ end
70
+
71
+ # Renders the VotD in the requested format.
72
+ # @param [Base] votd the verse of the day instance
73
+ # @param [String] format output format ("text", "html", or "json")
74
+ # @return [void]
75
+ def output(votd, format)
76
+ case format
77
+ when "text" then output_text(votd)
78
+ when "html" then puts votd.to_html
79
+ when "json" then output_json(votd)
80
+ else
81
+ warn "Error: Unknown format '#{format}'"
82
+ warn "Valid formats: text, html, json"
83
+ exit 1
84
+ end
85
+ end
86
+
87
+ # Renders the VotD as formatted plain text with a banner.
88
+ # @param [Base] votd the verse of the day instance
89
+ # @return [void]
90
+ def output_text(votd)
91
+ line_width = 40
92
+ Helper::CommandLine.banner("VERSE OF THE DAY for #{votd.date}", line_width)
93
+ puts "\n"
94
+ puts Helper::CommandLine.word_wrap(votd.to_text, line_width)
95
+
96
+ if votd.copyright
97
+ puts "\n"
98
+ Helper::CommandLine.banner(Helper::CommandLine.word_wrap(votd.copyright, line_width), line_width)
99
+ end
100
+ end
101
+
102
+ # Renders the VotD as pretty-printed JSON.
103
+ # @param [Base] votd the verse of the day instance
104
+ # @return [void]
105
+ def output_json(votd)
106
+ puts JSON.pretty_generate({
107
+ reference: votd.reference,
108
+ text: votd.text,
109
+ version: votd.version,
110
+ version_name: votd.version_name,
111
+ date: votd.date.to_s,
112
+ link: votd.link,
113
+ copyright: votd.copyright
114
+ })
115
+ end
116
+ end
117
+ end
data/lib/votd/esvbible.rb CHANGED
@@ -1,55 +1,19 @@
1
- require 'votd/helper/text'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Votd
4
- # Retrieves a Verse of the Day from http://www.gnpcb.org,
5
- # Good News Publishers, Crossway Bibles,
6
- # using the English Standard Version translation (ESV).
7
- class ESVBible < Votd::Base
8
- # The name of the Bible Translation that this module generates
9
- BIBLE_VERSION = "ESV"
10
- BIBLE_VERSION_NAME = "English Standard Version"
11
-
12
- # The URI of the API gateway
13
- URI = "http://www.gnpcb.org/esv/share/rss2.0/daily/"
14
-
15
- # Initializes the ESVBible class
16
- # @return [Votd::ESVBible]
4
+ # @deprecated Use {BibleGateway} with the +:esv+ version instead.
5
+ # The gnpcb.org RSS endpoint used by this class was shut down.
6
+ # The ESV API (https://api.esv.org/) requires an API key
7
+ # and does not provide a verse-of-the-day endpoint.
8
+ #
9
+ # @example Replacement usage
10
+ # votd = Votd::BibleGateway.new(:esv)
11
+ class ESVBible
12
+ # @raise [VotdError] always; this class is no longer supported
17
13
  def initialize
18
- super()
19
- end
20
-
21
- private
22
-
23
- # Gets the votd from the Good News Publishers, Crossway Bibles,
24
- # RSS feed
25
- # @return [String]
26
- def get_votd
27
- parsed_feed = Nokogiri::XML(HTTParty.get(URI).body)
28
- cleaned_copyright = clean_copyright(parsed_feed.xpath("//copyright").text)
29
-
30
- @reference = parsed_feed.xpath("//title")[1].text
31
- @text = parsed_feed.xpath("//description")[1].text
32
- @copyright = cleaned_copyright
33
- @link = parsed_feed.xpath("//guid").text
34
- @version = BIBLE_VERSION
35
- @version_name = BIBLE_VERSION_NAME
36
-
37
- @text = Helper::Text.clean_verse_start(@text)
38
- @text = Helper::Text.clean_verse_end(@text)
39
- rescue => e
40
- # use default info for VotD
41
- set_defaults
42
- end
43
-
44
- # Cleans up the copyright.
45
- # Removes:
46
- # - Tabs, line breaks
47
- # Inserts:
48
- # - Missing space after commas
49
- # @return [String]
50
- def clean_copyright(text)
51
- text = text.gsub(/[\t\n]/, '')
52
- text = text.gsub(/,(?!\s)/, ', ')
14
+ raise Votd::VotdError, "Votd::ESVBible is no longer supported. " \
15
+ "The gnpcb.org endpoint has been shut down. " \
16
+ "Use Votd::BibleGateway.new(:esv) for an ESV verse of the day."
53
17
  end
54
18
  end
55
19
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Votd
4
+ # Raised when a provider fails to fetch or parse a verse of the day.
5
+ # The original exception is preserved as #cause.
6
+ class FetchError < VotdError
7
+ end
8
+ end