fcc 1.0.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +15 -3
- data/Gemfile.lock +18 -16
- data/README.md +24 -70
- data/VERSION +1 -0
- data/fcc.gemspec +3 -3
- data/lib/fcc/station/cache.rb +14 -20
- data/lib/fcc/station/extended_info/parser.rb +66 -0
- data/lib/fcc/station/extended_info.rb +22 -28
- data/lib/fcc/station/index.rb +1 -1
- data/lib/fcc/station/info.rb +2 -9
- data/lib/fcc/station/result_delegate.rb +24 -0
- data/lib/fcc/station.rb +71 -9
- data/lib/fcc.rb +1 -22
- data/lib/version.rb +1 -1
- metadata +30 -52
- data/.github/workflows/release.yml +0 -27
- data/.github/workflows/tests.yml +0 -53
- data/CHANGELOG.md +0 -11
- data/lib/fcc/station/lms_data.rb +0 -139
- data/lib/fcc/station/parsers/extended_info.rb +0 -78
- data/lib/fcc/station/parsers/lms_data.rb +0 -13
- data/lib/fcc/station/record_delegate.rb +0 -121
- data/lib/fcc/station/record_group.rb +0 -49
- data/lib/fcc/station/result.rb +0 -180
- data/package.json +0 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1a2e65473c73d939b88beed853dfe8cb2ab4bb67684c522996a4b1eb0f8d7f8
|
4
|
+
data.tar.gz: d86f808b6da433d743ac6e2546307cf4bdfeb42ec521796cb78a0ecfffb7da63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6a3bea8e717984ddd25fed17731e3ba06709c70dcb49340a274d148fcdd281e1463baf6483879d9a2427961589f2e0d7af908d8ce4ab6508776c8ba1d80c5e3
|
7
|
+
data.tar.gz: 6da0ba2408b94f8488c45900938d3950e580a5cb71493b942a78696b462f0bc4dee61ea26b5bf4cbd1c54a155ad0b0c5670cde37e90c99ede9581b196cd75586
|
data/Gemfile
CHANGED
@@ -2,10 +2,22 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
git_source(:github) { |repo_name| 'https://github.com/jkeen/fcc' }
|
4
4
|
|
5
|
-
# Specify your gem's dependencies in
|
5
|
+
# Specify your gem's dependencies in popularity.gemspec
|
6
6
|
gemspec
|
7
7
|
|
8
|
+
#
|
9
|
+
# source "http://rubygems.org"
|
10
|
+
# # Add dependencies required to use your gem here.
|
11
|
+
# # Example:
|
12
|
+
# # gem "activesupport", ">= 2.3.5"
|
13
|
+
#
|
14
|
+
# # Add dependencies to develop your gem here.
|
15
|
+
# # Include everything needed to run rake, tests, features, etc.
|
16
|
+
#
|
17
|
+
# gem "nokogiri"
|
18
|
+
#
|
8
19
|
# group :development do
|
9
|
-
# gem "
|
10
|
-
# gem "
|
20
|
+
# gem "shoulda", ">= 0"
|
21
|
+
# gem "bundler"
|
22
|
+
# gem "jeweler"
|
11
23
|
# end
|
data/Gemfile.lock
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fcc (1.
|
4
|
+
fcc (1.1)
|
5
5
|
activesupport (>= 6.1)
|
6
6
|
httparty (~> 0.18)
|
7
|
-
lightly (~> 0.3.3)
|
8
|
-
logger
|
9
|
-
rubyzip (~> 2.3.2)
|
10
7
|
|
11
8
|
GEM
|
12
9
|
remote: https://rubygems.org/
|
13
10
|
specs:
|
14
|
-
activesupport (
|
11
|
+
activesupport (6.1.0)
|
15
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
16
13
|
i18n (>= 1.6, < 2)
|
17
14
|
minitest (>= 5.1)
|
18
15
|
tzinfo (~> 2.0)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
zeitwerk (~> 2.3)
|
17
|
+
awesome_print (1.8.0)
|
18
|
+
byebug (11.1.3)
|
19
|
+
concurrent-ruby (1.1.7)
|
20
|
+
diff-lcs (1.4.4)
|
21
|
+
httparty (0.18.1)
|
22
|
+
mime-types (~> 3.0)
|
23
23
|
multi_xml (>= 0.5.2)
|
24
|
-
i18n (1.
|
24
|
+
i18n (1.8.6)
|
25
25
|
concurrent-ruby (~> 1.0)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
minitest (5.
|
26
|
+
mime-types (3.3.1)
|
27
|
+
mime-types-data (~> 3.2015)
|
28
|
+
mime-types-data (3.2020.1104)
|
29
|
+
minitest (5.14.2)
|
30
30
|
multi_xml (0.6.0)
|
31
31
|
rake (12.3.3)
|
32
32
|
rspec (3.9.0)
|
@@ -42,15 +42,17 @@ GEM
|
|
42
42
|
diff-lcs (>= 1.2.0, < 2.0)
|
43
43
|
rspec-support (~> 3.9.0)
|
44
44
|
rspec-support (3.9.4)
|
45
|
-
|
46
|
-
tzinfo (2.0.6)
|
45
|
+
tzinfo (2.0.4)
|
47
46
|
concurrent-ruby (~> 1.0)
|
47
|
+
zeitwerk (2.4.2)
|
48
48
|
|
49
49
|
PLATFORMS
|
50
50
|
ruby
|
51
51
|
|
52
52
|
DEPENDENCIES
|
53
|
+
awesome_print
|
53
54
|
bundler (~> 2.1)
|
55
|
+
byebug
|
54
56
|
fcc!
|
55
57
|
rake (~> 12.3.3)
|
56
58
|
rspec (~> 3.9.0)
|
data/README.md
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
Query the FCC database for fm, am, and tv information.
|
4
4
|
|
5
|
-
|
6
|
-
This gem uses the new FCC apis and the old FCC apis and combines records to be the most complete version possible. The old (transition.fcc.gov) API provides way more data than the new one does.
|
7
|
-
|
8
5
|
## Install
|
9
6
|
|
10
7
|
```
|
@@ -15,78 +12,35 @@ gem install fcc
|
|
15
12
|
|
16
13
|
* Ruby 2.0.0 or higher
|
17
14
|
|
15
|
+
## Examples
|
16
|
+
|
18
17
|
#### Get station information by call sign
|
19
18
|
|
20
19
|
```ruby
|
21
20
|
station = FCC::Station.find(:fm, "KOOP")
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
station.to_json #=>
|
48
|
-
[{:band=>"FM",
|
49
|
-
:signal_strength=>"3.0 kW",
|
50
|
-
:latitude=>"30.266861111111112",
|
51
|
-
:longitude=>"-97.67444444444445",
|
52
|
-
:station_class=>"A",
|
53
|
-
:file_number=>"BLED-19950103KA",
|
54
|
-
:effective_radiated_power=>"3.0 kW",
|
55
|
-
:haat_horizontal=>"26.0",
|
56
|
-
:haat_vertical=>"26.0",
|
57
|
-
:antenna_type=>"ND",
|
58
|
-
:operating_hours=>nil,
|
59
|
-
:licensed_to=>"TEXAS EDUCATIONAL BROADCASTING CO-OPERATIVE, INC.",
|
60
|
-
:city=>"HORNSBY",
|
61
|
-
:state=>"TX",
|
62
|
-
:country=>"US",
|
63
|
-
:id=>"65320",
|
64
|
-
:call_sign=>"KOOP",
|
65
|
-
:status=>"LICENSED",
|
66
|
-
:rf_channel=>"219",
|
67
|
-
:license_expiration_date=>"08/01/2029",
|
68
|
-
:facility_type=>"ED",
|
69
|
-
:frequency=>"91.7",
|
70
|
-
:contact=>
|
71
|
-
{:name=>"Federico Pacheco",
|
72
|
-
:title=>"",
|
73
|
-
:address=>"3823 Airport Blvd. Suite B",
|
74
|
-
:address2=>"",
|
75
|
-
:city=>"Austin",
|
76
|
-
:state=>"TX",
|
77
|
-
:zip_code=>"78722",
|
78
|
-
:phone=>"(512)472-1369",
|
79
|
-
:fax=>"",
|
80
|
-
:email=>"federico.pacheco@koop.org",
|
81
|
-
:website=>"koop.org"},
|
82
|
-
:owner=>{:name=>"TEXAS EDUCATIONAL BROADCASTING CO-OPERATIVE, INC.", :city=>"AUSTIN", :state=>"TX", :phone=>"(512)472-1369"},
|
83
|
-
:community=>{:city=>"HORNSBY", :state=>"TX"}}]
|
84
|
-
```
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
### Caching
|
89
|
-
Extended attributes take several seconds to load from transition.fcc.gov. In order to work around this, we query the entire dataset and then cache the result locally for 3 days (using the lightly gem). To use your own cache, set `FCC.cache=` to your cache class (Rails.cache, maybe?) which should have a #fetch method that should take a key and a block like `cache.fetch(key) { // yield for expensive fetch }}`.
|
22
|
+
#Basic attributes, available quickly because the FCC actually caches these in a CDN:
|
23
|
+
station.id #=> 65320
|
24
|
+
station.status #=> LICENSED
|
25
|
+
station.rf_channel #=> 219
|
26
|
+
station.license_expiration_date #=> "08/01/2021"
|
27
|
+
station.facility_type #=> ED
|
28
|
+
station.frequency #=> 91.7
|
29
|
+
station.contact #=> <struct FCC::Station::Contact>
|
30
|
+
station.owner #=> <struct FCC::Station::Contact>
|
31
|
+
station.community #=> <struct FCC::Station::Community city="HORNSBY", state="TX">
|
32
|
+
|
33
|
+
#Extended attributes, takes several seconds to load because the FCC is running this endpoint on a 1960s era mainframe operated by trained hamsters
|
34
|
+
station.station_class #=> A
|
35
|
+
station.signal_strength #=> 3.0 kW
|
36
|
+
station.antenna_type #=> ND
|
37
|
+
station.effective_radiated_power #=> 3.0 kW
|
38
|
+
station.haat_horizontal #=> 26.0
|
39
|
+
station.haat_vertical #=> 26.0
|
40
|
+
station.latitude #=> "30.266861111111112"
|
41
|
+
station.longitude #=> "-97.67444444444445"
|
42
|
+
station.file_number #=> BLED-19950103KA
|
43
|
+
```
|
90
44
|
|
91
45
|
### Get all station call signs on a particular service (:fm, :am, :tv)
|
92
46
|
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/fcc.gemspec
CHANGED
@@ -6,6 +6,7 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = %q{fcc}
|
7
7
|
spec.version = FCC::VERSION
|
8
8
|
spec.authors = ["Jeff Keen"]
|
9
|
+
spec.date = %q{2011-01-30}
|
9
10
|
spec.description = %q{}
|
10
11
|
spec.email = %q{jeff@keen.me}
|
11
12
|
spec.homepage = "http://github.com/jkeen/fcc"
|
@@ -19,10 +20,9 @@ Gem::Specification.new do |spec|
|
|
19
20
|
spec.summary = %q{Searches the FCC's FM, AM, and TV databases}
|
20
21
|
spec.add_dependency "activesupport", ">= 6.1"
|
21
22
|
spec.add_dependency "httparty", "~> 0.18"
|
22
|
-
spec.add_dependency "lightly", "~> 0.3.3"
|
23
|
-
spec.add_dependency "rubyzip", "~> 2.3.2"
|
24
|
-
spec.add_dependency "logger"
|
25
23
|
spec.add_development_dependency "bundler", "~> 2.1"
|
26
24
|
spec.add_development_dependency "rake", "~> 12.3.3"
|
27
25
|
spec.add_development_dependency 'rspec', '~> 3.9.0'
|
26
|
+
spec.add_development_dependency "byebug", ">= 0"
|
27
|
+
spec.add_development_dependency "awesome_print", ">= 0"
|
28
28
|
end
|
data/lib/fcc/station/cache.rb
CHANGED
@@ -1,34 +1,28 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
|
3
|
-
|
4
|
-
require 'logger'
|
2
|
+
require 'byebug'
|
3
|
+
require_relative './extended_info/parser'
|
5
4
|
|
6
5
|
module FCC
|
7
6
|
module Station
|
8
7
|
class Cache
|
9
8
|
attr_reader :store
|
10
9
|
|
11
|
-
def initialize
|
12
|
-
@
|
13
|
-
|
14
|
-
end
|
10
|
+
def initialize(service)
|
11
|
+
@service = service
|
12
|
+
@store = Station::ExtendedInfo.new(@service)
|
15
13
|
end
|
16
14
|
|
17
|
-
def
|
18
|
-
|
15
|
+
def find(fcc_id)
|
16
|
+
results.detect { |r| r[:fcc_id].to_s == fcc_id.to_s }
|
19
17
|
end
|
20
18
|
|
21
|
-
def
|
22
|
-
|
23
|
-
@
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
nil
|
30
|
-
end
|
31
|
-
end
|
19
|
+
def results
|
20
|
+
#TODO: add redis caching tie-in because this query is molasses
|
21
|
+
@store.all_results.parsed_response
|
22
|
+
end
|
23
|
+
|
24
|
+
def inspect
|
25
|
+
"<Cache @service=#{service}>"
|
32
26
|
end
|
33
27
|
end
|
34
28
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'byebug'
|
3
|
+
|
4
|
+
module FCC
|
5
|
+
module Station
|
6
|
+
class ExtendedInfoParser < HTTParty::Parser
|
7
|
+
def parse
|
8
|
+
results = []
|
9
|
+
body.each_line do |row|
|
10
|
+
attrs = {}
|
11
|
+
attrs[:raw] = row
|
12
|
+
fields = row.split('|').slice(1...-1).collect(&:strip).map { |v| v == '-' ? "" : v }
|
13
|
+
|
14
|
+
attrs[:call_sign] = fields[0]
|
15
|
+
attrs[:frequency] = parse_frequency(fields[1])
|
16
|
+
attrs[:band] = fields[2]
|
17
|
+
attrs[:channel] = fields[3]
|
18
|
+
attrs[:antenna_type] = fields[4] # Directional Antenna (DA) or NonDirectional (ND)
|
19
|
+
attrs[:am_operating_time] = fields[5] if fields[5] && attrs[:band] == "AM" # (Only used for AM)
|
20
|
+
attrs[:station_class] = fields[6]
|
21
|
+
attrs[:region_2_station_class] = fields[7] if fields[7] && attrs[:band] == "AM" # (only used for AM)
|
22
|
+
attrs[:status] = fields[8]
|
23
|
+
attrs[:city] = fields[9]
|
24
|
+
attrs[:state] = fields[10]
|
25
|
+
attrs[:country] = fields[11]
|
26
|
+
attrs[:file_number] = fields[12] #File Number (Application, Construction Permit or License) or
|
27
|
+
attrs[:signal_strength] = parse_signal_strength(fields[13]) # Effective Radiated Power --
|
28
|
+
attrs[:effective_radiated_power] = parse_signal_strength(fields[14]) # Effective Radiated Power -- vertically polarized (maximum)
|
29
|
+
attrs[:haat_horizontal] = fields[15] # Antenna Height Above Average Terrain (HAAT) -- horizontal polarization
|
30
|
+
attrs[:haat_vertical] = fields[16] # Antenna Height Above Average Terrain (HAAT) -- vertical polarization
|
31
|
+
attrs[:fcc_id] = fields[17] # Facility ID Number (unique to each station)
|
32
|
+
attrs[:latitude] = parse_latitude(fields[18], fields[19], fields[20], fields[21])
|
33
|
+
attrs[:longitude] = parse_longitude(fields[22], fields[23], fields[24], fields[25])
|
34
|
+
attrs[:licensed_to] = fields[26] # Licensee or Permittee
|
35
|
+
|
36
|
+
results << attrs
|
37
|
+
end
|
38
|
+
|
39
|
+
results
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_longitude(direction, degrees, minutes, seconds)
|
43
|
+
decimal_degrees = degrees.to_i + (minutes.to_f / 60) + (seconds.to_f / 3600)
|
44
|
+
|
45
|
+
"#{direction =~ /W/ ? '-' : ''}#{decimal_degrees}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_latitude(direction, degrees, minutes, seconds)
|
49
|
+
decimal_degrees = degrees.to_i + (minutes.to_f / 60) + (seconds.to_f / 3600)
|
50
|
+
|
51
|
+
"#{direction =~ /S/ ? '-' : ''}#{decimal_degrees}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_signal_strength(raw_signal)
|
55
|
+
if raw_signal
|
56
|
+
parsed_signal = raw_signal[/[0-9]+\.?[0-9]?/]
|
57
|
+
"#{parsed_signal.to_f} #{raw_signal.scan(/\w+$/).first}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_frequency(freq)
|
62
|
+
freq.to_f
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -1,27 +1,26 @@
|
|
1
1
|
require 'httparty'
|
2
|
-
|
2
|
+
require 'byebug'
|
3
|
+
require_relative './extended_info/parser'
|
3
4
|
|
4
5
|
module FCC
|
5
6
|
module Station
|
6
7
|
class ExtendedInfo
|
7
8
|
include HTTParty
|
8
9
|
attr_accessor :results, :service
|
9
|
-
|
10
|
-
base_uri 'https://fcc-cache.b-cdn.net/fcc-bin/'
|
10
|
+
base_uri 'http://transition.fcc.gov/fcc-bin/'
|
11
11
|
|
12
12
|
def initialize(service)
|
13
13
|
@service = service
|
14
14
|
@options = {
|
15
15
|
follow_redirects: true
|
16
16
|
}
|
17
|
-
|
18
17
|
@query = {
|
19
18
|
# state: nil,
|
20
19
|
# call: nil,
|
21
20
|
# city: nil,
|
22
21
|
# arn: nil,
|
23
|
-
|
24
|
-
|
22
|
+
serv: service.to_s.downcase,
|
23
|
+
vac: 3, # licensed records only
|
25
24
|
# freq: @service.to_sym == :fm ? '87.1' : '530',
|
26
25
|
# fre2: @service.to_sym == :fm ? '107.9' : '1700',
|
27
26
|
# facid: nil,
|
@@ -43,38 +42,33 @@ module FCC
|
|
43
42
|
end
|
44
43
|
|
45
44
|
def all_results
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
FCC.log(response.request.uri.to_s.gsub('&list=4', '&list=0'))
|
52
|
-
response.parsed_response
|
53
|
-
end
|
54
|
-
rescue StandardError => e
|
55
|
-
FCC.error(e.message)
|
56
|
-
FCC.error(e.backtrace)
|
45
|
+
@all_results ||= begin
|
46
|
+
puts "charging cache for #{service} extended info"
|
47
|
+
response = self.class.get("/#{service.to_s.downcase}q", @options.merge(query: @query))
|
48
|
+
puts response.request.uri.to_s.gsub('&list=4', '&list=0')
|
49
|
+
response
|
57
50
|
end
|
58
51
|
end
|
59
52
|
|
60
53
|
def find(id_or_call_sign)
|
61
54
|
if id_or_call_sign =~ /^\d+$/
|
62
55
|
id = id_or_call_sign
|
63
|
-
all_results.filter { |r| r[:fcc_id].to_s == id.to_s } || find_directly({ facid: id_or_call_sign })
|
64
56
|
else
|
65
|
-
|
66
|
-
r[:call_sign].to_s == id_or_call_sign.to_s || r[:call_sign].to_s.upcase =~ Regexp.new("^#{id_or_call_sign.upcase}[-—–][A-Z0-9]+$")
|
67
|
-
} || find_directly({ call: id_or_call_sign })
|
57
|
+
id = FCC::Station.index(@service).call_sign_to_id(id_or_call_sign)
|
68
58
|
end
|
69
|
-
end
|
70
59
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
60
|
+
begin
|
61
|
+
FCC::Station.extended_info_cache(@service).find(id)
|
62
|
+
rescue Exception => e
|
63
|
+
response = self.class.get("/#{service.to_s.downcase}q", @options.merge(query: @query.merge(facid: id)))
|
64
|
+
puts response.request.uri.to_s.gsub('&list=4', '&list=0')
|
65
|
+
result = response.first
|
66
|
+
result['source_url'] = response.request.uri.to_s.gsub('&list=4', '&list=0')
|
67
|
+
result
|
68
|
+
end
|
75
69
|
end
|
76
|
-
|
77
|
-
parser FCC::Station::
|
70
|
+
|
71
|
+
parser FCC::Station::ExtendedInfoParser
|
78
72
|
end
|
79
73
|
end
|
80
74
|
end
|
data/lib/fcc/station/index.rb
CHANGED
data/lib/fcc/station/info.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'httparty'
|
2
|
+
require 'byebug'
|
2
3
|
|
3
4
|
module FCC
|
4
5
|
module Station
|
@@ -20,15 +21,7 @@ module FCC
|
|
20
21
|
end
|
21
22
|
|
22
23
|
response = self.class.get("/api/service/#{service.to_s.downcase}/facility/id/#{id}.json")
|
23
|
-
|
24
|
-
begin
|
25
|
-
body = response['results']['facility']
|
26
|
-
body['band'] = service.to_s.upcase.to_s
|
27
|
-
|
28
|
-
body
|
29
|
-
rescue StandardError => e
|
30
|
-
return nil
|
31
|
-
end
|
24
|
+
response['results']['facility']
|
32
25
|
end
|
33
26
|
end
|
34
27
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'byebug'
|
3
|
+
|
4
|
+
module FCC
|
5
|
+
module Station
|
6
|
+
class ResultDelegate
|
7
|
+
def initialize(result)
|
8
|
+
@result = result
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(m, *args, &block)
|
12
|
+
if @result
|
13
|
+
matched_key = @result.keys.detect { |d| m.to_s == d.to_s } || @result.keys.detect { |d| m.to_s == d.underscore.to_s }
|
14
|
+
|
15
|
+
if matched_key
|
16
|
+
@result[matched_key]
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/fcc/station.rb
CHANGED
@@ -1,17 +1,13 @@
|
|
1
1
|
require 'active_support/core_ext/module/delegation'
|
2
|
+
require_relative 'station/result_delegate'
|
2
3
|
require_relative 'station/extended_info'
|
3
|
-
require_relative 'station/cache'
|
4
4
|
require_relative 'station/index'
|
5
5
|
require_relative 'station/info'
|
6
|
-
require_relative 'station/result'
|
7
|
-
require_relative 'station/lms_data'
|
8
|
-
require_relative 'station/record_group'
|
9
|
-
require_relative 'station/record_delegate'
|
10
6
|
|
11
7
|
module FCC
|
12
8
|
module Station
|
13
|
-
Contact = Struct.new(:name, :title, :address, :address2, :city, :state, :
|
14
|
-
Community = Struct.new(:city, :state,
|
9
|
+
Contact = Struct.new(:name, :title, :address, :address2, :city, :state, :zip_code, :phone, :fax, :email, :website, keyword_init: true)
|
10
|
+
Community = Struct.new(:city, :state, keyword_init: true)
|
15
11
|
|
16
12
|
def self.find_each(service, &block)
|
17
13
|
results = index(service).results
|
@@ -38,8 +34,74 @@ module FCC
|
|
38
34
|
end
|
39
35
|
end
|
40
36
|
|
41
|
-
def self.extended_info_cache
|
42
|
-
@cache ||=
|
37
|
+
def self.extended_info_cache(service)
|
38
|
+
@cache ||= {}
|
39
|
+
@cache[service] ||= Station::Cache.new(service)
|
40
|
+
@cache[service]
|
41
|
+
end
|
42
|
+
|
43
|
+
class Result
|
44
|
+
EXTENDED_ATTRIBUTES = %i[signal_strength latitude longitude coordinates station_class file_number effective_radiated_power haat_horizontal haat_vertical] # these take a long time to query
|
45
|
+
BASIC_ATTRIBUTES = %i[id call_sign status rf_channel license_expiration_date facility_type frequency]
|
46
|
+
|
47
|
+
delegate *EXTENDED_ATTRIBUTES, to: :extended_data
|
48
|
+
delegate *BASIC_ATTRIBUTES, to: :data
|
49
|
+
|
50
|
+
alias_method :channel, :rf_channel
|
51
|
+
|
52
|
+
def initialize(service, call_sign, options = {})
|
53
|
+
@call_sign = call_sign.upcase
|
54
|
+
@service = service
|
55
|
+
@options = options
|
56
|
+
|
57
|
+
data
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_json
|
61
|
+
{}.tap do |hash|
|
62
|
+
[EXTENDED_ATTRIBUTES | BASIC_ATTRIBUTES | %i[contact owner community]].flatten.each do |attr|
|
63
|
+
result = send(attr.to_sym)
|
64
|
+
if result.respond_to?(:to_h)
|
65
|
+
hash[attr] = result.to_h
|
66
|
+
else
|
67
|
+
hash[attr] = result.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def owner
|
74
|
+
@owner ||= Contact.new(name: data.partyName, address: data.partyAddress1, address2: data.partyAddress2, city: data.partyCity, state: data.partyState, zip_code: data.partyZip1, phone: data.partyPhone)
|
75
|
+
end
|
76
|
+
|
77
|
+
def community
|
78
|
+
@community ||= Community.new(city: data.communityCity, state: data.communityState)
|
79
|
+
end
|
80
|
+
|
81
|
+
def contact
|
82
|
+
contact = data.mainStudioContact
|
83
|
+
@contact ||= Contact.new(name: contact['contactName'], title: contact['contactTitle'], address: contact['contactAddress1'], address2: contact['contactAddress2'], city: contact['contactCity'], state: contact['contactState'], zip_code: contact['contactZip'], phone: contact['contactPhone'], fax: contact['contactFax'], email: contact['contactEmail'], website: contact['contactWebsite'])
|
84
|
+
end
|
85
|
+
|
86
|
+
def coordinates
|
87
|
+
[latitude.to_f, longitude.to_f].to_json
|
88
|
+
end
|
89
|
+
|
90
|
+
def coordinates_url
|
91
|
+
"https://www.google.com/maps/search/#{coordinates[0]},#{coordinates[1]}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def extended_data_url
|
95
|
+
"https://transition.fcc.gov/fcc-bin/#{@service.to_s.downcase}q?list=4&facid=#{id}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def extended_data
|
99
|
+
@extended_data ||= ResultDelegate.new(ExtendedInfo.new(@service).find(@call_sign))
|
100
|
+
end
|
101
|
+
|
102
|
+
def data
|
103
|
+
@data ||= ResultDelegate.new(Info.new(@service).find(@call_sign))
|
104
|
+
end
|
43
105
|
end
|
44
106
|
end
|
45
107
|
end
|
data/lib/fcc.rb
CHANGED
@@ -3,29 +3,8 @@ require_relative './fcc/station'
|
|
3
3
|
require_relative './fcc/station/cache'
|
4
4
|
require_relative './fcc/station/info'
|
5
5
|
require_relative './fcc/station/extended_info'
|
6
|
-
require_relative './fcc/station/
|
6
|
+
require_relative './fcc/station/result_delegate'
|
7
7
|
|
8
8
|
module FCC
|
9
|
-
FM_FULL_SERVICE = 'FM'
|
10
|
-
FM_LOW_POWER = 'FL'
|
11
|
-
FM_BOOSTER = 'FB'
|
12
|
-
FM_TRANSLATOR = 'FX'
|
13
9
|
|
14
|
-
def self.cache
|
15
|
-
@cache ||= Station::Cache.new
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.cache=(cache_service)
|
19
|
-
@cache = cache_service
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.log(message)
|
23
|
-
@logger ||= Logger.new($stdout)
|
24
|
-
@logger.info(message)
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.error(message)
|
28
|
-
@error_logger ||= Logger.new($stderr)
|
29
|
-
@error_logger.error(message)
|
30
|
-
end
|
31
10
|
end
|
data/lib/version.rb
CHANGED