shack_kit 0.1.2 → 0.2.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.
@@ -1,7 +1,11 @@
1
1
  require 'fileutils'
2
2
  require 'sqlite3'
3
3
  require 'sequel'
4
- require 'simple-spreadsheet'
4
+ require 'maidenhead'
5
+ require 'csv'
6
+ require 'yaml'
7
+ require 'http'
8
+ require 'oga'
5
9
 
6
10
  module ShackKit
7
11
  module Data
@@ -9,8 +13,11 @@ module ShackKit
9
13
  MIGRATIONS_DIR = ShackKit::GEM_ROOT + "/db/migrations"
10
14
  SOURCES_DIR = ShackKit::GEM_ROOT + "/db/sources"
11
15
  DB_FILE = DATA_DIR + "/shack_kit.db"
16
+ CONFIG_FILE = DATA_DIR + "/config.yml"
17
+ CONFIG = File.exists?(CONFIG_FILE) ? YAML.load(File.read(CONFIG_FILE)) : Hash.new.freeze
12
18
  DB = Sequel.sqlite(DB_FILE)
13
19
  CALLSIGN_REGEX = /\A([A-Z]{1,2}|[0-9][A-Z])([0-9])/
20
+ USER_AGENT = "Ruby-gem-shack_kit-#{ShackKit::VERSION}"
14
21
 
15
22
  class << self
16
23
  def db_setup
@@ -35,6 +42,9 @@ end
35
42
 
36
43
  ShackKit::Data.schema_update
37
44
 
45
+ require 'shack_kit/data/ham_qth'
46
+ require 'shack_kit/data/qrz'
47
+ require 'shack_kit/data/qrz_pl'
38
48
  require 'shack_kit/data/sota_calls'
39
49
  require 'shack_kit/data/sota_summits'
40
50
  require 'shack_kit/data/sp_calls'
@@ -0,0 +1,32 @@
1
+ module ShackKit
2
+ module Data
3
+ class HamQTH
4
+ attr_reader :session_key
5
+ QUERY_URL = 'https://www.hamqth.com/xml.php'
6
+
7
+ def initialize(params = {})
8
+ return false unless params[:login] && params[:password] || CONFIG && CONFIG.has_key?('ham_qth')
9
+ login = params[:login] || CONFIG['ham_qth']['login']
10
+ password = params[:password] || CONFIG['ham_qth']['password']
11
+ response = HTTP.get("#{QUERY_URL}?u=#{login}&p=#{password}")
12
+ parsed_response = Oga.parse_xml(response.to_s)
13
+ @session_key = parsed_response.xpath("HamQTH/session/session_id").text
14
+ puts parsed_response.xpath("HamQTH/session/error").text if @session_key.empty?
15
+ end
16
+
17
+ def lookup(callsign)
18
+ return { error: "Can't query HamQTH.com without submitting valid login credentials first" } if @session_key.nil? || @session_key.empty?
19
+ response = HTTP.get("#{QUERY_URL}?id=#{@session_key}&callsign=#{callsign}&prg=#{USER_AGENT}")
20
+ parsed_response = Oga.parse_xml(response.to_s)
21
+ return { error: parsed_response.xpath("HamQTH/session/error").text } if
22
+ parsed_response.xpath("HamQTH/search").text.empty?
23
+ attributes = parsed_response.xpath("HamQTH/search").first.children.select{ |c| c.class == Oga::XML::Element }.map(&:name)
24
+ {}.tap do |output|
25
+ attributes.each do |attribute|
26
+ output[attribute.to_sym] = parsed_response.xpath("HamQTH/search/#{attribute}").text
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module ShackKit
2
+ module Data
3
+ class QRZ
4
+ attr_reader :session_key
5
+ QUERY_URL = 'https://xmldata.qrz.com/xml/current/'
6
+
7
+ def initialize(params = {})
8
+ return false unless params[:login] && params[:password] || CONFIG && CONFIG.has_key?('qrz_com')
9
+ login = params[:login] || CONFIG['qrz_com']['login']
10
+ password = params[:password] || CONFIG['qrz_com']['password']
11
+ response = HTTP.post(QUERY_URL, form: { username: login, password: password, agent: USER_AGENT })
12
+ parsed_response = Oga.parse_xml(response.to_s)
13
+ @session_key = parsed_response.xpath("QRZDatabase/Session/Key").text
14
+ puts parsed_response.xpath("QRZDatabase/Session/Error").text if @session_key.empty?
15
+ end
16
+
17
+ def lookup(callsign)
18
+ return { error: "Can't query qrz.com, use valid login credentials to get access" } if @session_key.nil? || @session_key.empty?
19
+ response = HTTP.post(QUERY_URL, form: { s: @session_key, callsign: callsign })
20
+ parsed_response = Oga.parse_xml(response.to_s)
21
+ return { error: parsed_response.xpath("QRZDatabase/Session/Error").text } if
22
+ parsed_response.xpath("QRZDatabase/Callsign").text.empty?
23
+ attributes = parsed_response.xpath("QRZDatabase/Callsign").first.children.select{ |c| c.class == Oga::XML::Element }.map(&:name)
24
+ {}.tap do |output|
25
+ attributes.each do |attribute|
26
+ output[attribute.to_sym] = parsed_response.xpath("QRZDatabase/Callsign/#{attribute}").text
27
+ end
28
+ output[:message] = parsed_response.xpath('QRZDatabase/Session/Message').text
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module ShackKit
2
+ module Data
3
+ class QRZ_PL
4
+ QUERY_URL = "http://qrz.pl/callbook.asp"
5
+
6
+ def self.lookup(callsign)
7
+ response = HTTP.post("http://qrz.pl/callbook.asp", form: { "F_DOMENA": callsign })
8
+ document = Oga.parse_html(response.to_s)
9
+ return { error: "Not found: #{callsign}"} unless
10
+ document.xpath('//span[contains(@class, "znak")]').text == callsign
11
+ details = document.xpath('//span[contains(@class, "dane")]').map(&:text)
12
+ { callsign: callsign, details: details, grid: grid_lookup(details) }
13
+ end
14
+
15
+ private
16
+
17
+ def self.grid_lookup(details)
18
+ return nil unless grid_info = details.select{ |d| d =~ /^LOKATOR\: [A-Z]{2}\d{2}/}.first
19
+ grid_info.split.last
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,33 +4,35 @@ module ShackKit
4
4
  def self.update(source_file = SOURCES_DIR + "/summitslist.csv")
5
5
  summits = DB[:sota_summits]
6
6
  summits.delete
7
- csv = SimpleSpreadsheet::Workbook.read(source_file, ".csv")
8
- 3.upto(csv.last_row) do |line|
7
+ CSV.foreach(source_file, headers: true, skip_lines: /SOTA Summits List/) do |row|
9
8
  summits.insert(
10
- summit_code: csv.cell(line, 1),
11
- association_name: csv.cell(line, 2),
12
- region_name: csv.cell(line, 3),
13
- summit_name: csv.cell(line, 4),
14
- alt_m: csv.cell(line, 5).to_i,
15
- alt_ft: csv.cell(line, 6).to_i,
16
- grid_ref1: csv.cell(line, 7),
17
- grid_ref2: csv.cell(line, 8),
18
- longitude: csv.cell(line, 9).to_f,
19
- latitude: csv.cell(line, 10).to_f,
20
- points: csv.cell(line, 11).to_i,
21
- bonus_points: csv.cell(line, 12).to_i,
22
- valid_from: Date.parse(csv.cell(line, 13)),
23
- valid_to: Date.parse(csv.cell(line, 14)),
24
- activation_count: csv.cell(line, 15).to_i,
25
- activation_date: csv.cell(line, 16).nil? ? nil : Date.parse(csv.cell(line, 16)),
26
- activation_call: csv.cell(line, 17)
9
+ summit_code: row["SummitCode"],
10
+ association_name: row["AssociationName"],
11
+ region_name: row["RegionName"],
12
+ summit_name: row["SummitName"],
13
+ alt_m: row["AltM"].to_i,
14
+ alt_ft: row["AltFt"].to_i,
15
+ grid_ref1: row["GridRef1"],
16
+ grid_ref2: row["GridRef2"],
17
+ longitude: row["Longitude"].to_f,
18
+ latitude: row["Latitude"].to_f,
19
+ points: row["Points"].to_i,
20
+ bonus_points: row["BonusPoints"].to_i,
21
+ valid_from: Date.parse(row["ValidFrom"]),
22
+ valid_to: Date.parse(row["ValidTo"]),
23
+ activation_count: row["ActivationCount"].to_i,
24
+ activation_date: row["ActivationDate"].nil? ? nil : Date.parse(row["ActivationDate"]),
25
+ activation_call: row["ActivationCall"]
27
26
  )
28
27
  end
29
28
  summits.count
30
29
  end
31
30
 
32
31
  def self.check(reference)
33
- DB[:sota_summits].where(summit_code: reference).first
32
+ summit = DB[:sota_summits].where(summit_code: reference).first
33
+ return false if summit.nil?
34
+ locator = Maidenhead.to_maidenhead(summit[:latitude], summit[:longitude], 3)
35
+ summit.merge(maidenhead_locator: locator)
34
36
  end
35
37
  end
36
38
  end
@@ -5,8 +5,8 @@ module ShackKit
5
5
  sources = [source_file] + other_source_files
6
6
  calls = DB[:sp_calls]
7
7
  calls.delete
8
- sources.each do |source_file|
9
- CSV.foreach(source_file, col_sep: ";", encoding: "Windows-1250:UTF-8", headers: true) do |row|
8
+ sources.each do |source|
9
+ CSV.foreach(source, col_sep: ";", encoding: "Windows-1250:UTF-8", headers: true) do |row|
10
10
  individual = row["operator_1"].nil?
11
11
  calls.insert(
12
12
  callsign: row["call_sign"],
@@ -1,3 +1,3 @@
1
1
  module ShackKit
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shack_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcin Bajer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-01 00:00:00.000000000 Z
11
+ date: 2016-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -107,25 +107,65 @@ dependencies:
107
107
  - !ruby/object:Gem::Version
108
108
  version: '4.28'
109
109
  - !ruby/object:Gem::Dependency
110
- name: simple-spreadsheet
110
+ name: maidenhead
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '0.4'
115
+ version: '1.0'
116
116
  - - ">="
117
117
  - !ruby/object:Gem::Version
118
- version: 0.4.1
118
+ version: 1.0.1
119
119
  type: :runtime
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - "~>"
124
124
  - !ruby/object:Gem::Version
125
- version: '0.4'
125
+ version: '1.0'
126
126
  - - ">="
127
127
  - !ruby/object:Gem::Version
128
- version: 0.4.1
128
+ version: 1.0.1
129
+ - !ruby/object:Gem::Dependency
130
+ name: oga
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '2.3'
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '2.3'
139
+ type: :runtime
140
+ prerelease: false
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '2.3'
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '2.3'
149
+ - !ruby/object:Gem::Dependency
150
+ name: http
151
+ requirement: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - "~>"
154
+ - !ruby/object:Gem::Version
155
+ version: '2.0'
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: 2.0.3
159
+ type: :runtime
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '2.0'
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: 2.0.3
129
169
  description: Set of HAM radio tools, currently limited to SP and SOTA-related stuff
130
170
  email:
131
171
  - bajer@tigana.pl
@@ -133,32 +173,27 @@ executables: []
133
173
  extensions: []
134
174
  extra_rdoc_files: []
135
175
  files:
136
- - ".gitignore"
137
- - ".ruby-gemset"
138
- - ".ruby-version"
139
- - ".travis.yml"
140
176
  - CHANGELOG.md
141
- - Gemfile
142
177
  - LICENSE.txt
143
178
  - README.md
144
- - Rakefile
145
179
  - bin/console
146
180
  - bin/setup
147
181
  - db/migrations/001_create_sota_calls.rb
148
182
  - db/migrations/002_create_sp_calls.rb
149
183
  - db/migrations/003_create_sota_summits.rb
150
- - db/sources/201511 - RA2WWW_ok.xls
151
- - db/sources/clubs_2016-04-01.csv
152
- - db/sources/individuals_2016-04-01.csv
184
+ - db/sources/clubs_2016-08-25.csv
185
+ - db/sources/individuals_2016-08-25.csv
153
186
  - db/sources/masterSOTA.scp
154
187
  - db/sources/summitslist.csv
155
188
  - lib/shack_kit.rb
156
189
  - lib/shack_kit/data/base.rb
190
+ - lib/shack_kit/data/ham_qth.rb
191
+ - lib/shack_kit/data/qrz.rb
192
+ - lib/shack_kit/data/qrz_pl.rb
157
193
  - lib/shack_kit/data/sota_calls.rb
158
194
  - lib/shack_kit/data/sota_summits.rb
159
195
  - lib/shack_kit/data/sp_calls.rb
160
196
  - lib/shack_kit/version.rb
161
- - shack_kit.gemspec
162
197
  homepage: https://github.com/rrrodrigo/shack_kit
163
198
  licenses:
164
199
  - MIT
@@ -180,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
215
  version: '0'
181
216
  requirements: []
182
217
  rubyforge_project:
183
- rubygems_version: 2.4.6
218
+ rubygems_version: 2.5.1
184
219
  signing_key:
185
220
  specification_version: 4
186
221
  summary: Set of HAM radio tools packaged by SQ9OZM
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- *.gem
data/.ruby-gemset DELETED
@@ -1 +0,0 @@
1
- shack-kit
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.2
data/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2.3
4
- before_install: gem install bundler -v 1.10.6
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in shack_kit.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList['test/**/*_test.rb']
8
- end
9
-
10
- task :default => :test
Binary file