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