relaton-itu 2.1.2 → 2.2.0.pre.alpha.1

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: 6934a71bcfd52917864d6cf3af90fd07333ce87cc9c5d8cd045217d86a423b28
4
- data.tar.gz: 0a1daa40935cb00409c1d40186aa63d7c25bd70866356a635fa52dc4ef512d87
3
+ metadata.gz: 1c4821cc8b6a9ce8a01c25c40b1f45d719d86fd0d0c0573fe4043a12b17ff9cb
4
+ data.tar.gz: 5eecc3cf067f12aacda1765adb5dcaf442617c2d30acd79b18739b98697a37b2
5
5
  SHA512:
6
- metadata.gz: 11d05f246d70e236f0995ec2a80abfef38c8085b602aa6bff5aa4c5033fdc5d4984cec8e9125348f9f31739903cf82e89d9d16819a4233e4855ece1488455366
7
- data.tar.gz: 42cfd40edebcd128a3cc402a3c6e3c6fd4b2d7e1bad5a4a9d2403dd59b020cf729034eeaa864d915e69e1bf192b0bb7d2e90ce31465fa7db942dbaa608d3eb7f
6
+ metadata.gz: b49648210b4649382889aa44a46dfb3b2ee28833bd35f82946e052e0dc7731404a5e03a8f6076735f55676b4dd6a248a6c73014dcae7655bf8e2d14ae62be7c0
7
+ data.tar.gz: 3dfc18dd9e59e79295f532c27a37c540b0f3a4c8515c6373b8b9823edf568fc5fb39707c24361aa399e9f940afd3701aaa59dacf027a607c527d4a4996510550
data/CLAUDE.md CHANGED
@@ -45,28 +45,6 @@ All model classes use `Lutaml::Model::Serializable` for XML/YAML serialization:
45
45
  - **`DataParserR`** — module that parses ITU-R JSON search API results into `ItemData` instances (sets `flavor: "itu"` on all parsed documents)
46
46
  - Sources: recommendations (JSON index), questions, reports, handbooks, resolutions (HTML indices)
47
47
 
48
- ### Runtime lookup (`HitCollection#search`)
49
-
50
- `Bibliography.get`/`search` routes by reference in `HitCollection#search`:
51
-
52
- - **ITU-T Recommendations** (`request_recommendation`) — discovery is a two-stage HTTP flow against
53
- `www.itu.int`. The `RunSearch` Deep Search endpoint was removed/WAF-blocked (issue #88), so
54
- discovery now GETs the public `ITU-T/recommendations/rec.aspx?rec={code}` page, extracts the
55
- record handle (`11.1002/1000/{idrec}`), and calls the `mws/api/recommendations/getRecEditions`
56
- API to build one `Hit` per edition (each `hit[:url]` is a `handle.itu.int/.../{idrec}-en` URL so
57
- `Scraper#idrec` re-parses it). Year/edition filtering stays in `Bibliography#search_filter` /
58
- `#isobib_results_filter`. Full metadata is fetched by `RecommendationParser` (the `mws/api/*`
59
- endpoints), unchanged.
60
- - **ITU-R RR & Operational Bulletins** (`request_publication`) — resolved to their predictable
61
- `/pub/{pubid}` landing page (`R-REG-RR-{year}`, `T-SP-OB.{num}-{year}`) and scraped by
62
- `RadioRegulationsParser`. A redirect to `notfound.aspx` (or a 404) yields no hit.
63
- - **ITU-R (other)** (`request_document`) — reads the pre-built `relaton-data-itu-r` GitHub dataset
64
- via `Relaton::Index`; does not hit `www.itu.int`.
65
-
66
- Note: `DataFetcher` (the offline ITU-R harvester) still POSTs to the removed `RunSearch` endpoint,
67
- so a dataset *refresh* is currently broken — a follow-up should migrate it (and, longer term, ITU-T)
68
- to a relaton-data dataset.
69
-
70
48
  ### Processor
71
49
 
72
50
  `Relaton::Itu::Processor` extends `Relaton::Core::Processor` and is the entry point for the Relaton plugin system. Provides `get`, `fetch_data`, `from_xml`, `hash_to_bib`, `grammar_hash`, and `remove_index_file`.
data/Gemfile CHANGED
@@ -5,6 +5,14 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in relaton_itu.gemspec
6
6
  gemspec
7
7
 
8
+ # Use local monorepo sibling gems where available.
9
+ Dir["../*/"].each do |dir|
10
+ name = File.basename(dir)
11
+ next if name == File.basename(__dir__)
12
+ next unless File.exist?(File.join(dir, "#{name}.gemspec"))
13
+ gem name, path: dir
14
+ end
15
+
8
16
 
9
17
  gem "equivalent-xml", "~> 0.6"
10
18
  gem "pry-byebug"
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi"
4
- require "json"
5
3
  require_relative "hit"
6
4
 
7
5
  module Relaton
@@ -10,16 +8,11 @@ module Relaton
10
8
  class HitCollection < Relaton::Core::HitCollection
11
9
  DOMAIN = "https://www.itu.int"
12
10
  GH_ITU_R = "https://raw.githubusercontent.com/relaton/relaton-data-itu-r/refs/heads/v2/"
13
- REC_URL = "#{DOMAIN}/ITU-T/recommendations/rec.aspx?rec=%<rec>s&lang=en".freeze
14
- RECEDITIONS_URL = "#{DOMAIN}/mws/api/recommendations/getRecEditions?idrec=%<idrec>s&lang=en".freeze
15
- HANDLE_URL = "http://handle.itu.int/11.1002/1000/%<idrec>s-en".freeze
16
11
 
17
12
  def search
18
13
  case ref.to_ref
19
- when %r{^ITU-R\sRR}, %r{\bOB\.|Operational Bulletin}
20
- request_publication
21
- when /^ITU-T/
22
- request_recommendation
14
+ when /^(ITU-T|ITU-R\sRR)/
15
+ request_search
23
16
  when /^ITU-R\s/
24
17
  request_document
25
18
  end
@@ -34,87 +27,12 @@ module Relaton
34
27
 
35
28
  private
36
29
 
37
- # Resolve an ITU-T Recommendation to its editions via the public rec.aspx
38
- # page (which exposes the record's handle/idrec) and the getRecEditions API.
39
- # One hit is built per edition, mirroring the multi-result shape the old
40
- # RunSearch endpoint used to return, so year filtering keeps working.
41
- def request_recommendation
30
+ def request_search
42
31
  Util.info "Fetching from www.itu.int ...", key: ref.to_s
43
- idrec = fetch_idrec
44
- return @array = [] unless idrec
45
-
46
- @array = editions(idrec).map { |ed| recommendation_hit(ed) }
47
- end
48
-
49
- # @return [String, nil] the record's idrec, or nil when the code is unknown
50
- def fetch_idrec
51
- url = format(REC_URL, rec: CGI.escape(rec_query))
52
- agent.get(url).body[%r{11\.1002/1000/(\d+)}, 1]
53
- rescue Mechanize::ResponseCodeError => e
54
- raise unless e.response_code == "404" # unknown code => treat as not found
55
-
56
- nil
57
- end
58
-
59
- # @return [String] the `rec=` value for the rec.aspx lookup
60
- def rec_query
61
- ref.suppl ? "#{ref.code} Suppl. #{ref.suppl}" : ref.code
62
- end
63
-
64
- # @param idrec [String]
65
- # @return [Array<Hash>] editions of the recommendation
66
- def editions(idrec)
67
- JSON.parse agent.get(format(RECEDITIONS_URL, idrec: idrec)).body
68
- rescue JSON::ParserError
69
- []
70
- end
71
-
72
- # @param edition [Hash] a getRecEditions entry
73
- # @return [Relaton::Itu::Hit]
74
- def recommendation_hit(edition)
75
- Hit.new({
76
- code: "ITU-T #{edition['rec_name']}",
77
- title: edition["title"],
78
- url: format(HANDLE_URL, idrec: edition["idrec"]),
79
- type: "recommendation",
80
- }, self)
81
- end
82
-
83
- # Resolve an ITU-R Radio Regulation or Operational Bulletin to its stable
84
- # /pub landing page, whose id is derivable from the reference.
85
- def request_publication
86
- Util.info "Fetching from www.itu.int ...", key: ref.to_s
87
- return @array = [] unless ref.year
88
-
89
- url = "#{DOMAIN}/pub/#{publication_id}"
90
- page = fetch_publication_page url
91
- return @array = [] if page.nil? || page.uri.to_s.match?(/notfound/i)
92
-
93
- hit = Hit.new({ code: publication_code, title: nil, url: url, type: "publication" }, self)
94
- @array = [hit]
95
- end
96
-
97
- # @return [Mechanize::Page, nil] nil when the publication does not exist
98
- def fetch_publication_page(url)
99
- agent.get url
100
- rescue Mechanize::ResponseCodeError => e
101
- raise unless e.response_code == "404" # unknown publication => not found
102
-
103
- nil
104
- end
105
-
106
- # @return [String] the /pub identifier for RR or OB
107
- def publication_id
108
- if ref.code == "RR"
109
- "R-REG-RR-#{ref.year}"
110
- else # Operational Bulletin, e.g. OB.1096
111
- "T-SP-OB.#{ref.code[/\d+/]}-#{ref.year}"
112
- end
113
- end
114
-
115
- # @return [String] the docidentifier-friendly code (year only, no month)
116
- def publication_code
117
- "#{ref.prefix}-#{ref.sector} #{ref.code} (#{ref.year})"
32
+ url = "#{DOMAIN}/net4/ITU-T/search/GlobalSearch/RunSearch"
33
+ data = { json: params.to_json }
34
+ resp = agent.post url, data
35
+ @array = hits JSON.parse(resp.body)
118
36
  end
119
37
 
120
38
  def request_document # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
@@ -132,6 +50,78 @@ module Relaton
132
50
  hit.item = item
133
51
  @array = [hit]
134
52
  end
53
+
54
+ # @return [String]
55
+ def group
56
+ @group ||= case ref.to_ref
57
+ when %r{OB|Operational Bulletin}, %r{^ITU-R\sRR}
58
+ "Publications"
59
+ when %r{^ITU-T} then "Recommendations"
60
+ end
61
+ end
62
+
63
+ # @return [Hash]
64
+ def params # rubocop:disable Metrics/MethodLength
65
+ input = ref.dup
66
+ input.year = nil
67
+ {
68
+ "Input" => input.to_s,
69
+ "Start" => 0,
70
+ "Rows" => 20,
71
+ "SortBy" => "RELEVANCE",
72
+ "ExactPhrase" => false,
73
+ "CollectionName" => "General",
74
+ "CollectionGroup" => group,
75
+ "Sector" => ref.to_ref.match(/(?<=^ITU-)\w/).to_s.downcase,
76
+ "Criterias" => [{
77
+ "Name" => "Search in",
78
+ "Criterias" => [
79
+ {
80
+ "Selected" => false,
81
+ "Value" => "",
82
+ "Label" => "Name",
83
+ "Target" => "/name_s",
84
+ "TypeName" => "CHECKBOX",
85
+ "GetCriteriaType" => 0,
86
+ },
87
+ {
88
+ "Selected" => false,
89
+ "Value" => "",
90
+ "Label" => "Short description",
91
+ "Target" => "/short_description_s",
92
+ "TypeName" => "CHECKBOX",
93
+ "GetCriteriaType" => 0,
94
+ },
95
+ {
96
+ "Selected" => false,
97
+ "Value" => "",
98
+ "Label" => "File content",
99
+ "Target" => "/file",
100
+ "TypeName" => "CHECKBOX",
101
+ "GetCriteriaType" => 0,
102
+ },
103
+ ],
104
+ "ShowCheckbox" => true,
105
+ "Selected" => false,
106
+ }],
107
+ "Topics" => "",
108
+ "ClientData" => {},
109
+ "Language" => "en",
110
+ "SearchType" => "All",
111
+ }
112
+ end
113
+
114
+ # @param data [Hash]
115
+ # @return [Array<Relaton::Itu::Hit>]
116
+ def hits(data)
117
+ data["results"].map do |h|
118
+ code = h["Media"]["Name"]
119
+ title = h["Title"]
120
+ url = "#{DOMAIN}#{h['Redirection']}"
121
+ type = h["Collection"]["Group"].downcase[0...-1]
122
+ Hit.new({ code: code, title: title, url: url, type: type }, self)
123
+ end
124
+ end
135
125
  end
136
126
  end
137
127
  end
@@ -19,8 +19,7 @@ module Relaton
19
19
  end
20
20
 
21
21
  def doc_url
22
- url = CGI.unescape(hit.hit[:url])
23
- url.include?("dest=") ? url.split("dest=").last : url
22
+ CGI.unescape(hit.hit[:url]).split("dest=").last
24
23
  end
25
24
 
26
25
  def fetch_edition = nil
@@ -91,24 +91,10 @@ module Relaton
91
91
  @docid ||= begin
92
92
  docids = hit.hit[:code].to_s.split(" | ").map { |c| createdocid(c) }
93
93
  docids << createdocid(doc["rec_name"]) if docids.empty?
94
- iso = iso_docid
95
- docids << iso if iso
96
94
  docids
97
95
  end
98
96
  end
99
97
 
100
- # The equivalent ISO/IEC identifier used to come from the search result's
101
- # media name; it is now re-sourced from the recommendation header's
102
- # `iso_number` field (e.g. "Equivalent standard: ISO/IEC 17788:2014 (Common)").
103
- # @return [Relaton::Bib::Docidentifier, nil]
104
- def iso_docid
105
- return unless idrec # only recommendations carry an idrec / iso_number
106
-
107
- num = parser.doc && parser.doc["iso_number"]
108
- id = num && num[%r{ISO(?:/IEC)?(?:/IEEE)?\s+\d[\d-]*}]
109
- createdocid(id) if id
110
- end
111
-
112
98
  # @param text [String]
113
99
  # @return [Relaton::Bib::Docidentifier]
114
100
  def createdocid(text) # rubocop:disable Metrics/MethodLength
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Itu
3
- VERSION = "2.1.2".freeze
3
+ VERSION = "2.2.0.pre.alpha.1".freeze
4
4
  end
5
5
  end
data/relaton-itu.gemspec CHANGED
@@ -23,11 +23,11 @@ Gem::Specification.new do |spec|
23
23
  spec.bindir = "exe"
24
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ["lib"]
26
- spec.required_ruby_version = Gem::Requirement.new(">= 3.2.0")
26
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.3.0")
27
27
 
28
28
  spec.add_dependency "mechanize", "~> 2.10"
29
29
  spec.add_dependency "parslet", "~> 2.0.0"
30
- spec.add_dependency "relaton-bib", "~> 2.1.0"
31
- spec.add_dependency "relaton-core", "~> 0.0.13"
32
- spec.add_dependency "relaton-index", "~> 0.2.0"
30
+ spec.add_dependency "relaton-bib", "~> 2.2.0.pre.alpha.1"
31
+ spec.add_dependency "relaton-core", "~> 2.2.0.pre.alpha.1"
32
+ spec.add_dependency "relaton-index", "~> 2.2.0.pre.alpha.1"
33
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-itu
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.2.0.pre.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-29 00:00:00.000000000 Z
11
+ date: 2026-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mechanize
@@ -44,42 +44,42 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 2.1.0
47
+ version: 2.2.0.pre.alpha.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 2.1.0
54
+ version: 2.2.0.pre.alpha.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: relaton-core
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.0.13
61
+ version: 2.2.0.pre.alpha.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.0.13
68
+ version: 2.2.0.pre.alpha.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: relaton-index
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.2.0
75
+ version: 2.2.0.pre.alpha.1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.2.0
82
+ version: 2.2.0.pre.alpha.1
83
83
  description: 'Relaton::Itu: retrieve ITU Standards for bibliographic use using the
84
84
  BibliographicItem model'
85
85
  email:
@@ -92,7 +92,6 @@ files:
92
92
  - ".github/workflows/release.yml"
93
93
  - ".gitignore"
94
94
  - ".rspec"
95
- - ".rubocop.yml"
96
95
  - CLAUDE.md
97
96
  - Gemfile
98
97
  - LICENSE.txt
@@ -141,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
140
  requirements:
142
141
  - - ">="
143
142
  - !ruby/object:Gem::Version
144
- version: 3.2.0
143
+ version: 3.3.0
145
144
  required_rubygems_version: !ruby/object:Gem::Requirement
146
145
  requirements:
147
146
  - - ">="
data/.rubocop.yml DELETED
@@ -1,12 +0,0 @@
1
- # This project follows the Ribose OSS style guide.
2
- # https://github.com/riboseinc/oss-guides
3
- # All project-specific additions and overrides should be specified in this file.
4
-
5
- require: rubocop-rails
6
-
7
- inherit_from:
8
- - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
9
- AllCops:
10
- TargetRubyVersion: 3.2
11
- Rails:
12
- Enabled: false