wagon 0.9.5 → 0.10.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.
- data/VERSION +1 -1
- data/bin/wagon +1 -1
- data/lib/wagon/address.rb +6 -1
- data/lib/wagon/connection.rb +58 -26
- data/lib/wagon/directory.rb +5 -17
- data/lib/wagon/household.rb +32 -20
- data/lib/wagon/phone_number.rb +1 -1
- data/lib/wagon/ward.rb +1 -1
- data/spec/spec_helper.rb +6 -0
- data/spec/wagon/directory_spec.rb +8 -4
- metadata +2 -5
- data/lib/wagon/photo_directory.rb +0 -28
- data/spec/wagon/photo_directory_spec.rb +0 -13
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.10.0
|
data/bin/wagon
CHANGED
data/lib/wagon/address.rb
CHANGED
@@ -2,7 +2,7 @@ module Wagon
|
|
2
2
|
class Address
|
3
3
|
CITY_STATE_ZIP = %r/^(\D+), (\D+)?\s*(\d+(-\d+)?)?$/
|
4
4
|
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :city, :state, :zip, :country
|
6
6
|
|
7
7
|
def self.extract_from_string(string)
|
8
8
|
parts = string.split("\n").collect(&:strip).delete_if(&:empty?)
|
@@ -20,6 +20,11 @@ module Wagon
|
|
20
20
|
@street, @city, @state, @zip, @country = street, city, state, zip, country
|
21
21
|
end
|
22
22
|
|
23
|
+
def street
|
24
|
+
#601 N. Monterey Drive Apartment K
|
25
|
+
@street.to_s.gsub(/apartment/i, 'Apt.').gsub(/drive/i, 'Dr.')
|
26
|
+
end
|
27
|
+
|
23
28
|
def to_s
|
24
29
|
[street, [[city, state].compact.join(", "), zip, country.to_s.empty? ? nil : "(#{country})"].compact.join(" ")].compact.join("\n")
|
25
30
|
end
|
data/lib/wagon/connection.rb
CHANGED
@@ -1,20 +1,48 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'net/https'
|
3
|
+
require 'curb'
|
3
4
|
require 'uri'
|
4
5
|
require 'digest/sha1'
|
5
6
|
require 'wagon/ward'
|
6
7
|
|
7
8
|
module Wagon
|
8
|
-
|
9
9
|
class AuthenticationFailure < StandardError; end
|
10
10
|
|
11
11
|
class Connection
|
12
12
|
HOST = 'secure.lds.org'
|
13
13
|
LOGIN_PATH = '/units/a/login/1,21568,779-1,00.html?URL='
|
14
|
-
|
14
|
+
|
15
|
+
# For asynchronous procedures
|
16
|
+
@@trigger = ConditionVariable.new
|
17
|
+
@@lock = Mutex.new
|
18
|
+
@@queue = []
|
19
|
+
|
20
|
+
(1..30).collect do
|
21
|
+
Thread.new do
|
22
|
+
http = Net::HTTP.new(HOST, 443)
|
23
|
+
http.use_ssl = true
|
24
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
25
|
+
http
|
26
|
+
|
27
|
+
while true
|
28
|
+
connection, path, callback = nil, nil, nil
|
29
|
+
@@lock.synchronize do
|
30
|
+
connection, path, callback = *@@queue.shift
|
31
|
+
end
|
32
|
+
|
33
|
+
if connection
|
34
|
+
callback.call(http.request(Net::HTTP::Get.new(path, {'Cookie' => connection.cookies || ''})))
|
35
|
+
else
|
36
|
+
sleep(0.5)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :cookies
|
15
43
|
|
16
44
|
def initialize(username, password)
|
17
|
-
response =
|
45
|
+
response = _post(LOGIN_PATH, 'username' => username, 'password' => password)
|
18
46
|
@cookies = response['set-cookie']
|
19
47
|
@home_path = URI.parse(response['location']).path
|
20
48
|
|
@@ -30,33 +58,17 @@ module Wagon
|
|
30
58
|
end
|
31
59
|
|
32
60
|
def get(path)
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def get_without_caching(path)
|
37
|
-
_http.request(Net::HTTP::Get.new(path, {'Cookie' => @cookies || ''})).body
|
61
|
+
_get(path).body
|
38
62
|
end
|
39
63
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
open(cache_path, "w").write(data = get_without_caching(path))
|
45
|
-
data
|
64
|
+
def get_async(path, &block)
|
65
|
+
@@lock.synchronize do
|
66
|
+
@@queue.push([self, path, block])
|
67
|
+
end
|
46
68
|
end
|
47
69
|
|
48
|
-
def
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.perform_caching(true_or_false)
|
53
|
-
@@perform_caching = true_or_false
|
54
|
-
end
|
55
|
-
|
56
|
-
def post(path, data)
|
57
|
-
request = Net::HTTP::Post.new(path, {'Cookie' => @cookies || ''})
|
58
|
-
request.set_form_data(data)
|
59
|
-
_http.request(request)
|
70
|
+
def expired?
|
71
|
+
_head(ward.directory_path).class != Net::HTTPOK
|
60
72
|
end
|
61
73
|
|
62
74
|
def _dump(depth)
|
@@ -79,5 +91,25 @@ module Wagon
|
|
79
91
|
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
80
92
|
@http
|
81
93
|
end
|
94
|
+
|
95
|
+
def _curl
|
96
|
+
@curl ||= Curl::Easy.new do |curl|
|
97
|
+
curl.headers = {'Cookie' => @cookies || ''}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def _get(path)
|
102
|
+
_http.request(Net::HTTP::Get.new(path, {'Cookie' => @cookies || ''}))
|
103
|
+
end
|
104
|
+
|
105
|
+
def _head(path)
|
106
|
+
_http.request(Net::HTTP::Head.new(path, {'Cookie' => @cookies || ''}))
|
107
|
+
end
|
108
|
+
|
109
|
+
def _post(path, data)
|
110
|
+
request = Net::HTTP::Post.new(path, {'Cookie' => @cookies || ''})
|
111
|
+
request.set_form_data(data)
|
112
|
+
_http.request(request)
|
113
|
+
end
|
82
114
|
end
|
83
115
|
end
|
data/lib/wagon/directory.rb
CHANGED
@@ -8,23 +8,10 @@ module Wagon
|
|
8
8
|
@parent
|
9
9
|
end
|
10
10
|
|
11
|
-
def photo_directory_path
|
12
|
-
return @photo_directory_path unless @photo_directory_path.nil?
|
13
|
-
|
14
|
-
self.at('a.linknoline[href^="javascript:confirm_photo"]')['href'].match(/^javascript:confirm_photo\('(.*)'\);$/)
|
15
|
-
@photo_directory_path = $1
|
16
|
-
end
|
17
|
-
|
18
|
-
def photo_directory
|
19
|
-
@photo_directory ||= PhotoDirectory.new(connection, photo_directory_path)
|
20
|
-
end
|
21
|
-
|
22
11
|
def households
|
23
|
-
@households ||=
|
24
|
-
|
25
|
-
|
26
|
-
def members
|
27
|
-
households.collect(&:members).flatten()
|
12
|
+
@households ||= self.search('body > table > tr > td.eventsource[@width="25%"]').collect do |household_td|
|
13
|
+
household = Household.create_from_td(connection, household_td)
|
14
|
+
end.sort
|
28
15
|
end
|
29
16
|
|
30
17
|
def to_pdf(options = {})
|
@@ -62,8 +49,9 @@ module Wagon
|
|
62
49
|
y = pdf.bounds.top - row*grid_height - header_height
|
63
50
|
(0...columns).each do |column|
|
64
51
|
break if (index = page*rows*columns+row*columns+column) >= households.size
|
65
|
-
household = households[index]
|
66
52
|
x = pdf.bounds.left + column*grid_width
|
53
|
+
household = households[index]
|
54
|
+
|
67
55
|
pdf.bounding_box([x, y], :width => grid_width, :height => grid_height) do
|
68
56
|
pdf.bounding_box([pdf.bounds.left + padding, pdf.bounds.top - padding], :width => box_width, :height => box_height) do
|
69
57
|
info = []
|
data/lib/wagon/household.rb
CHANGED
@@ -6,13 +6,16 @@ require 'base64'
|
|
6
6
|
|
7
7
|
module Wagon
|
8
8
|
class Household
|
9
|
-
attr_reader :connection
|
10
|
-
attr_writer :name
|
11
|
-
attr_accessor :address, :phone_number, :image_path, :members
|
9
|
+
attr_reader :connection, :address, :phone_number, :image_path, :members
|
12
10
|
|
13
|
-
def initialize(connection)
|
14
|
-
@members =
|
15
|
-
|
11
|
+
def initialize(connection, name, address, phone_number, image_path, members)
|
12
|
+
@connection, @name, @address, @phone_number, @image_path, @members = connection, name, address, phone_number, image_path, members
|
13
|
+
|
14
|
+
if has_image?
|
15
|
+
@connection.get_async(image_path) do |response|
|
16
|
+
@image_data = response.body
|
17
|
+
end
|
18
|
+
end
|
16
19
|
end
|
17
20
|
|
18
21
|
def name
|
@@ -32,7 +35,11 @@ module Wagon
|
|
32
35
|
end
|
33
36
|
|
34
37
|
def image_data
|
35
|
-
|
38
|
+
return nil unless has_image?
|
39
|
+
|
40
|
+
sleep(0.5) while @image_data.nil?
|
41
|
+
|
42
|
+
@image_data
|
36
43
|
end
|
37
44
|
|
38
45
|
def <=>(other)
|
@@ -43,21 +50,26 @@ module Wagon
|
|
43
50
|
end
|
44
51
|
end
|
45
52
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@
|
50
|
-
|
51
|
-
|
52
|
-
@phone_number = PhoneNumber.extract_from_string(phone_element.inner_text)
|
53
|
-
|
54
|
-
member_elements.each_slice(2) do |name_and_email|
|
55
|
-
name, email = *name_and_email.collect { |element| element.inner_text.gsub(/\302\240/, '').strip() }
|
56
|
-
@members << Member.new(self, name, email)
|
57
|
-
end
|
53
|
+
private
|
54
|
+
def spawn_download_thread
|
55
|
+
@thread ||= Thread.new(image_path) do |path|
|
56
|
+
@image_data = connection.get_async(path)
|
57
|
+
end
|
58
|
+
end
|
58
59
|
|
59
|
-
|
60
|
+
def self.create_from_td(connection, td)
|
61
|
+
name_element, phone_element, *member_elements = *td.search('table > tr > td.eventsource[width="45%"] > table > tr > td.eventsource')
|
62
|
+
address = Address.extract_from_string(td.search('table > tr > td.eventsource[width="25%"]').inner_text)
|
63
|
+
image_path = td.at('table > tr > td.eventsource[width="30%"] > img')['src'] rescue nil
|
64
|
+
phone_number = PhoneNumber.extract_from_string(phone_element.inner_text)
|
65
|
+
members = []
|
66
|
+
|
67
|
+
member_elements.each_slice(2) do |name_and_email|
|
68
|
+
name, email = *name_and_email.collect { |element| element.inner_text.gsub(/\302\240/, '').strip() }
|
69
|
+
members << Member.new(self, name, email)
|
60
70
|
end
|
71
|
+
|
72
|
+
self.new(connection, name_element.inner_text, address, phone_number, image_path, members)
|
61
73
|
end
|
62
74
|
end
|
63
75
|
end
|
data/lib/wagon/phone_number.rb
CHANGED
data/lib/wagon/ward.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -13,6 +13,7 @@ require 'highline/import'
|
|
13
13
|
$user = nil
|
14
14
|
|
15
15
|
def establish_connection
|
16
|
+
puts "Create a connection for testing: "
|
16
17
|
username = ask("What is your lds.org username? ")
|
17
18
|
password = ask("What is your lds.org password? ") { |prompt| prompt.echo = "*" }
|
18
19
|
|
@@ -26,6 +27,11 @@ end
|
|
26
27
|
|
27
28
|
if File.exists?(USER_FILE)
|
28
29
|
restore_connection()
|
30
|
+
|
31
|
+
if $user.expired?
|
32
|
+
puts "Previous connection timed out."
|
33
|
+
establish_connection()
|
34
|
+
end
|
29
35
|
else
|
30
36
|
establish_connection()
|
31
37
|
end
|
@@ -3,16 +3,20 @@ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
|
|
3
3
|
describe "Wagon::Directory" do
|
4
4
|
|
5
5
|
before(:each) do
|
6
|
-
@
|
6
|
+
@directory = Wagon::Directory.new($user, $user.ward.directory_path, $user.ward)
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should find the photo directory link" do
|
10
|
-
@
|
11
|
-
@
|
10
|
+
@directory.instance_variable_get(:@url).should_not be_nil
|
11
|
+
@directory.instance_variable_get(:@url).should match(%r{^/units/a/directory/photoprint})
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should be able to generate a pdf" do
|
15
|
-
@
|
15
|
+
lambda { @directory.to_pdf.render_file("./photo_directory.pdf") }.should_not raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse out the households correctly" do
|
19
|
+
@directory.households.should have_at_least(10).items
|
16
20
|
end
|
17
21
|
|
18
22
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wagon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Devin Christensen
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-13 00:00:00 -07:00
|
13
13
|
default_executable: wagon
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -88,12 +88,10 @@ files:
|
|
88
88
|
- lib/wagon/member.rb
|
89
89
|
- lib/wagon/page.rb
|
90
90
|
- lib/wagon/phone_number.rb
|
91
|
-
- lib/wagon/photo_directory.rb
|
92
91
|
- lib/wagon/ward.rb
|
93
92
|
- spec/spec.opts
|
94
93
|
- spec/spec_helper.rb
|
95
94
|
- spec/wagon/directory_spec.rb
|
96
|
-
- spec/wagon/photo_directory_spec.rb
|
97
95
|
- spec/wagon/ward_spec.rb
|
98
96
|
- spec/wagon_spec.rb
|
99
97
|
has_rdoc: true
|
@@ -127,6 +125,5 @@ summary: Create a PDF from the lds.org ward Photo Directory.
|
|
127
125
|
test_files:
|
128
126
|
- spec/spec_helper.rb
|
129
127
|
- spec/wagon/directory_spec.rb
|
130
|
-
- spec/wagon/photo_directory_spec.rb
|
131
128
|
- spec/wagon/ward_spec.rb
|
132
129
|
- spec/wagon_spec.rb
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'wagon/household'
|
2
|
-
|
3
|
-
module Wagon
|
4
|
-
class PhotoDirectory < Page
|
5
|
-
def households
|
6
|
-
@households ||= _parse_households
|
7
|
-
end
|
8
|
-
|
9
|
-
def members
|
10
|
-
households.collect(&:members).flatten()
|
11
|
-
end
|
12
|
-
|
13
|
-
def to_pdf(options)
|
14
|
-
Prawn::Document.new() do |pdf|
|
15
|
-
households.each do |household|
|
16
|
-
pdf.text household.name
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
def _parse_households
|
23
|
-
self.search('body > table > tr > td.eventsource[@width="25%"]').collect do |household_td|
|
24
|
-
household = Household.create_from_td(connection, household_td)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
|
2
|
-
|
3
|
-
describe "Wagon::PhotoDirectory" do
|
4
|
-
|
5
|
-
before(:each) do
|
6
|
-
@page = Wagon::PhotoDirectory.new($user, $user.ward.directory.photo_directory_path)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should parse out the households correctly" do
|
10
|
-
@page.households.should have_at_least(10).items
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|