fcc 0.1.0 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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