fcc 0.1.0 → 1.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.
@@ -0,0 +1,29 @@
1
+ require 'httparty'
2
+ require 'byebug'
3
+ require_relative './extended_info/parser'
4
+
5
+ module FCC
6
+ module Station
7
+ class Cache
8
+ attr_reader :store
9
+
10
+ def initialize(service)
11
+ @service = service
12
+ @store = Station::ExtendedInfo.new(@service)
13
+ end
14
+
15
+ def find(fcc_id)
16
+ results.detect { |r| r[:fcc_id].to_s == fcc_id.to_s }
17
+ end
18
+
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}>"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,74 @@
1
+ require 'httparty'
2
+ require 'byebug'
3
+ require_relative './extended_info/parser'
4
+
5
+ module FCC
6
+ module Station
7
+ class ExtendedInfo
8
+ include HTTParty
9
+ attr_accessor :results, :service
10
+ base_uri 'http://transition.fcc.gov/fcc-bin/'
11
+
12
+ def initialize(service)
13
+ @service = service
14
+ @options = {
15
+ follow_redirects: true
16
+ }
17
+ @query = {
18
+ # state: nil,
19
+ # call: nil,
20
+ # city: nil,
21
+ # arn: nil,
22
+ serv: service.to_s.downcase,
23
+ vac: 3, # licensed records only
24
+ # freq: @service.to_sym == :fm ? '87.1' : '530',
25
+ # fre2: @service.to_sym == :fm ? '107.9' : '1700',
26
+ # facid: nil,
27
+ # class: nil,
28
+ # dkt: nil,
29
+ # dist: nil,
30
+ # dlat2: nil,
31
+ # dlon2: nil,
32
+ # mlon2: nil,
33
+ # mlat2: nil,
34
+ # slat2: nil,
35
+ # slon2: nil,
36
+ # NS: "N",
37
+ # e: 9,
38
+ # EW: 'W',
39
+ list: 4, # pipe separated output
40
+ size: 9
41
+ }
42
+ end
43
+
44
+ def all_results
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
50
+ end
51
+ end
52
+
53
+ def find(id_or_call_sign)
54
+ if id_or_call_sign =~ /^\d+$/
55
+ id = id_or_call_sign
56
+ else
57
+ id = FCC::Station.index(@service).call_sign_to_id(id_or_call_sign)
58
+ end
59
+
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
69
+ end
70
+
71
+ parser FCC::Station::ExtendedInfoParser
72
+ end
73
+ end
74
+ 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
@@ -0,0 +1,39 @@
1
+ require 'httparty'
2
+ require 'byebug'
3
+ module FCC
4
+ module Station
5
+ class Index
6
+ include HTTParty
7
+ base_uri 'publicfiles.fcc.gov'
8
+
9
+ attr_accessor :service
10
+
11
+ def initialize(service)
12
+ @service = service
13
+ end
14
+
15
+ def call_sign_to_id(call_sign)
16
+ found = results.detect do |hash|
17
+ hash['callSign'] == call_sign.upcase
18
+ end
19
+
20
+ found ||= results.detect do |hash|
21
+ hash['callSign'] == "#{call_sign.upcase}-#{service.to_s.upcase}"
22
+ end
23
+
24
+ found['id'] if found
25
+ end
26
+
27
+ def inspect
28
+ "<Station::Index @results=[#{results.size}]>"
29
+ end
30
+
31
+ def results
32
+ @results ||= begin
33
+ response = self.class.get("/api/service/#{service.to_s.downcase}/facility/getall.json")
34
+ response.parsed_response['results']['facilityList']
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ require 'httparty'
2
+ require 'byebug'
3
+
4
+ module FCC
5
+ module Station
6
+ class Info
7
+ include HTTParty
8
+ base_uri 'publicfiles.fcc.gov'
9
+
10
+ attr_accessor :results, :service
11
+
12
+ def initialize(service)
13
+ @service = service
14
+ end
15
+
16
+ def find(id_or_call_sign, options = {})
17
+ id = if id_or_call_sign =~ /^\d+$/
18
+ id_or_call_sign
19
+ else
20
+ Station.index(service).call_sign_to_id(id_or_call_sign)
21
+ end
22
+
23
+ response = self.class.get("/api/service/#{service.to_s.downcase}/facility/id/#{id}.json")
24
+ response['results']['facility']
25
+ end
26
+ end
27
+ end
28
+ 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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FCC
4
+ VERSION = '1.1'
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'spec_helper'
3
+
4
+ RSpec.describe FCC, type: :model do
5
+
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'fcc'
2
+
3
+ RSpec.configure do |config|
4
+ config.mock_with :rspec do |mocks|
5
+ mocks.syntax = [:should, :expect]
6
+ end
7
+ end
metadata CHANGED
@@ -1,154 +1,166 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: fcc
3
- version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.1'
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Jeff Keen
14
- autorequire:
8
+ autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2011-01-30 00:00:00 -06:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
23
- none: false
24
- requirements:
11
+ date: 2011-01-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
25
17
  - - ">="
26
- - !ruby/object:Gem::Version
27
- hash: 3
28
- segments:
29
- - 0
30
- version: "0"
31
- requirement: *id001
32
- prerelease: false
33
- name: nokogiri
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
34
20
  type: :runtime
35
- - !ruby/object:Gem::Dependency
36
- version_requirements: &id002 !ruby/object:Gem::Requirement
37
- none: false
38
- requirements:
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
39
24
  - - ">="
40
- - !ruby/object:Gem::Version
41
- hash: 3
42
- segments:
43
- - 0
44
- version: "0"
45
- requirement: *id002
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.18'
34
+ type: :runtime
46
35
  prerelease: false
47
- name: shoulda
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.18'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.1'
48
48
  type: :development
49
- - !ruby/object:Gem::Dependency
50
- version_requirements: &id003 !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ~>
54
- - !ruby/object:Gem::Version
55
- hash: 23
56
- segments:
57
- - 1
58
- - 0
59
- - 0
60
- version: 1.0.0
61
- requirement: *id003
62
49
  prerelease: false
63
- name: bundler
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 12.3.3
64
62
  type: :development
65
- - !ruby/object:Gem::Dependency
66
- version_requirements: &id004 !ruby/object:Gem::Requirement
67
- none: false
68
- requirements:
69
- - - ~>
70
- - !ruby/object:Gem::Version
71
- hash: 7
72
- segments:
73
- - 1
74
- - 5
75
- - 2
76
- version: 1.5.2
77
- requirement: *id004
78
63
  prerelease: false
79
- name: jeweler
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 12.3.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.9.0
80
76
  type: :development
81
- - !ruby/object:Gem::Dependency
82
- version_requirements: &id005 !ruby/object:Gem::Requirement
83
- none: false
84
- requirements:
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.9.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
85
87
  - - ">="
86
- - !ruby/object:Gem::Version
87
- hash: 3
88
- segments:
89
- - 0
90
- version: "0"
91
- requirement: *id005
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
92
91
  prerelease: false
93
- name: rcov
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: awesome_print
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
94
104
  type: :development
95
- description: ""
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: ''
96
112
  email: jeff@keen.me
97
- executables: []
98
-
113
+ executables:
114
+ - console
115
+ - setup
99
116
  extensions: []
100
-
101
- extra_rdoc_files:
102
- - LICENSE.txt
103
- - README.rdoc
104
- files:
105
- - .document
106
- - .rvmrc
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".document"
120
+ - ".gitignore"
107
121
  - Gemfile
108
122
  - Gemfile.lock
109
123
  - LICENSE.txt
110
- - README.rdoc
124
+ - README.md
111
125
  - Rakefile
112
126
  - VERSION
113
- - lib/am.rb
127
+ - bin/console
128
+ - bin/setup
129
+ - fcc.gemspec
114
130
  - lib/fcc.rb
115
- - lib/fm.rb
116
- - test/helper.rb
117
- - test/test_fcc.rb
118
- has_rdoc: true
131
+ - lib/fcc/station.rb
132
+ - lib/fcc/station/cache.rb
133
+ - lib/fcc/station/extended_info.rb
134
+ - lib/fcc/station/extended_info/parser.rb
135
+ - lib/fcc/station/index.rb
136
+ - lib/fcc/station/info.rb
137
+ - lib/fcc/station/result_delegate.rb
138
+ - lib/version.rb
139
+ - spec/fcc_spec.rb
140
+ - spec/spec_helper.rb
119
141
  homepage: http://github.com/jkeen/fcc
120
- licenses:
142
+ licenses:
121
143
  - MIT
122
- post_install_message:
144
+ metadata: {}
145
+ post_install_message:
123
146
  rdoc_options: []
124
-
125
- require_paths:
147
+ require_paths:
126
148
  - lib
127
- required_ruby_version: !ruby/object:Gem::Requirement
128
- none: false
129
- requirements:
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
130
151
  - - ">="
131
- - !ruby/object:Gem::Version
132
- hash: 3
133
- segments:
134
- - 0
135
- version: "0"
136
- required_rubygems_version: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
139
156
  - - ">="
140
- - !ruby/object:Gem::Version
141
- hash: 3
142
- segments:
143
- - 0
144
- version: "0"
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
145
159
  requirements: []
146
-
147
- rubyforge_project:
148
- rubygems_version: 1.4.1
149
- signing_key:
150
- specification_version: 3
151
- summary: Searches the FCC's FM and AM databases
152
- test_files:
153
- - test/helper.rb
154
- - test/test_fcc.rb
160
+ rubygems_version: 3.1.2
161
+ signing_key:
162
+ specification_version: 4
163
+ summary: Searches the FCC's FM, AM, and TV databases
164
+ test_files:
165
+ - spec/fcc_spec.rb
166
+ - spec/spec_helper.rb