stalkr 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0
1
+ 0.9.1
data/lib/stalkr.rb CHANGED
@@ -11,6 +11,8 @@ require 'date'
11
11
 
12
12
  require 'stalkr/base'
13
13
  require 'stalkr/result'
14
+ require 'stalkr/error'
15
+
14
16
  require 'stalkr/ups'
15
17
  require 'stalkr/usps'
16
18
  require 'stalkr/fedex'
@@ -23,16 +25,17 @@ if not DateTime.new.public_methods.include? "to_time" then
23
25
  t = d.instance_eval do
24
26
  Time.utc(year, mon, mday, hour, min, sec +
25
27
  sec_fraction)
26
- end.getlocal
28
+ end
29
+ t.getlocal
27
30
  end
28
31
  end
29
32
  end
30
33
 
31
34
  module Stalkr
32
35
 
33
- def self.shippers
34
- return [ Stalkr::UPS, Stalkr::USPS, Stalkr::FEDEX ]
35
- end
36
+ def self.shippers
37
+ return [ Stalkr::UPS, Stalkr::USPS, Stalkr::FEDEX ]
38
+ end
36
39
 
37
40
  def self.track(id)
38
41
  shipper = nil
@@ -0,0 +1,16 @@
1
+
2
+ module Stalkr
3
+
4
+ class Error < ::Exception
5
+
6
+ attr_accessor :html
7
+
8
+ def initialize(ex, html)
9
+ super(ex.message)
10
+ self.set_backtrace(ex.backtrace)
11
+ self.html = html
12
+ end
13
+
14
+ end
15
+
16
+ end
data/lib/stalkr/fedex.rb CHANGED
@@ -6,7 +6,7 @@ module Stalkr
6
6
 
7
7
  class FEDEX < Base
8
8
 
9
- self.regex = /\b((96\d\d\d\d\d ?\d\d\d\d|96\d\d) ?\d\d\d\d ?d\d\d\d( ?\d\d\d)?)|(\d{12}|\d{15})\b/i
9
+ self.regex = /\b((96\d\d\d\d\d ?\d\d\d\d|96\d\d) ?\d\d\d\d ?d\d\d\d( ?\d\d\d)?)\b|\b(\d{12}|\d{15})\b/i
10
10
 
11
11
  def track(id)
12
12
 
@@ -15,68 +15,54 @@ class FEDEX < Base
15
15
  url.gsub!(/%CODE%/, id)
16
16
  html = fetchurl(url)
17
17
 
18
- if html =~ /invalid._header/ then
19
- ret = Result.new(:FEDEX)
20
- ret.status = UNKNOWN
21
- return ret
22
- end
18
+ begin
23
19
 
24
- info_scraper = Scraper.define do
20
+ if html =~ /invalid._header/ then
21
+ ret = Result.new(:FEDEX)
22
+ ret.status = UNKNOWN
23
+ return ret
24
+ end
25
25
 
26
- array :dates
26
+ info_scraper = Scraper.define do
27
27
 
28
- process "div.detailshipmentstatus", :status => :text
29
- process "div.detailshipdates > div.fielddata", :dates => :text
30
- process "div.detaildestination > div.fielddata", :destination => :text
31
- process_first "div.detailshipfacts div.dataentry", :service_type => :text
28
+ array :dates
32
29
 
33
- result :status, :dates, :destination, :service_type
30
+ process "div.detailshipmentstatus", :status => :text
31
+ process "div.detailshipdates > div.fielddata", :dates => :text
32
+ process "div.detaildestination > div.fielddata", :destination => :text
33
+ process_first "div.detailshipfacts div.dataentry", :service_type => :text
34
34
 
35
- end
35
+ result :status, :dates, :destination, :service_type
36
36
 
37
- ret = Result.new(:FEDEX)
37
+ end
38
38
 
39
- info = info_scraper.scrape(html)
39
+ ret = Result.new(:FEDEX)
40
40
 
41
- if info.status.strip.downcase == "delivered" then
42
- ret.status = DELIVERED
43
- end
44
- ret.location = info.destination.strip
41
+ info = info_scraper.scrape(html)
42
+
43
+ if info.status.strip.downcase == "delivered" then
44
+ ret.status = DELIVERED
45
+ end
46
+ ret.location = info.destination.strip
47
+
48
+ # obj.service_type = info.service_type.strip
49
+
50
+ # try to get dates
51
+ shipped_date = info.dates[0].strip
52
+ delivery_date = info.dates[1].strip if info.dates.length == 2
53
+ if shipped_date.empty? then
54
+ shipped_date = DateTime.strptime( $1, "%b %d, %Y" ).to_time if html =~ /var shipDate = "(.*?);$"/
55
+ delivery_date = DateTime.strptime( "#{$1} -5", "%b %d, %Y %I:%M %p %z" ).to_time if html =~ /var deliveryDateTime = "(.*?)";$/
56
+ end
57
+ ret.delivered_at = delivery_date
58
+ ret.updated_at = delivery_date
59
+
60
+ return ret
45
61
 
46
- # obj.service_type = info.service_type.strip
62
+ rescue Exception => ex
63
+ raise Stalkr::Error.new(ex, html)
47
64
 
48
- # try to get dates
49
- shipped_date = info.dates[0].strip
50
- delivery_date = info.dates[1].strip if info.dates.length == 2
51
- if shipped_date.empty? then
52
- shipped_date = DateTime.strptime( $1, "%b %d, %Y" ).to_time if html =~ /var shipDate = "(.*?);$"/
53
- delivery_date = DateTime.strptime( "#{$1} -5", "%b %d, %Y %I:%M %p %z" ).to_time if html =~ /var deliveryDateTime = "(.*?)";$/
54
65
  end
55
- ret.delivered_at = delivery_date
56
- ret.updated_at = delivery_date
57
-
58
- # pull progress from JSON
59
- # if html =~ /^var detailInfoObject = (.*);$/ then
60
- # json = $1
61
- # progress = JSON.parse(json)
62
- # scans = progress['scans']
63
- #
64
- # progress = []
65
- #
66
- # scans.each { |scan|
67
- # o = OpenStruct.new
68
- # o.location = scan['scanLocation']
69
- # o.date = scan['scanDate']
70
- # o.local_time = scan['scanTime']
71
- # o.desc = scan['scanStatus']
72
- # progress << o
73
- # }
74
- #
75
- # obj.progress = progress
76
- #
77
- # end
78
-
79
- return ret
80
66
 
81
67
  end
82
68
 
data/lib/stalkr/ups.rb CHANGED
@@ -25,53 +25,60 @@ class UPS < Base
25
25
  url.gsub!(/%CODE%/, id)
26
26
  html = fetchurl(url)
27
27
 
28
- detail_scraper = Scraper.define do
28
+ begin
29
29
 
30
- array :keys
31
- array :vals
32
- array :lists
30
+ detail_scraper = Scraper.define do
33
31
 
34
- process "#trkNum", :trackingNumber => :text
35
- process "#tt_spStatus", :status => :text
36
- process "#fontControl dt", :keys => :text
37
- process "#fontControl dd", :vals => :text
38
- process "#fontControl ul.clearfix li", :lists => :text
32
+ array :keys
33
+ array :vals
34
+ array :lists
39
35
 
40
- result :keys, :vals, :trackingNumber, :status, :lists
36
+ process "#trkNum", :trackingNumber => :text
37
+ process "#tt_spStatus", :status => :text
38
+ process "#fontControl dt", :keys => :text
39
+ process "#fontControl dd", :vals => :text
40
+ process "#fontControl ul.clearfix li", :lists => :text
41
41
 
42
- end
42
+ result :keys, :vals, :trackingNumber, :status, :lists
43
43
 
44
- details = detail_scraper.scrape(html)
44
+ end
45
45
 
46
- if not details.trackingNumber then
47
- raise "UPS scraper failed"
48
- end
46
+ details = detail_scraper.scrape(html)
49
47
 
50
- ret = Result.new(:UPS)
48
+ if not details.trackingNumber then
49
+ raise "UPS scraper failed"
50
+ end
51
51
 
52
- ret.status = case details.status.strip.downcase
53
- when "in transit"
54
- IN_TRANSIT
55
- when "delivered"
56
- DELIVERED
57
- else
58
- UNKNOWN
59
- end
52
+ ret = Result.new(:UPS)
60
53
 
61
- hash = {}
62
- details.keys.each_with_index do |k,i|
63
- hash[k] = details.vals[i]
64
- end
54
+ ret.status = case details.status.strip.downcase
55
+ when "in transit"
56
+ IN_TRANSIT
57
+ when "delivered"
58
+ DELIVERED
59
+ else
60
+ UNKNOWN
61
+ end
65
62
 
66
- if ret.status == DELIVERED then
67
- delivered_at = cleanup_html( hash["Delivered On:"] )
68
- ret.delivered_at = DateTime.strptime( delivered_at, "%A, %m/%d/%Y at %I:%M %p" ).to_time
69
- end
63
+ hash = {}
64
+ details.keys.each_with_index do |k,i|
65
+ hash[k] = details.vals[i]
66
+ end
70
67
 
71
- cleanup_html( details.lists[3] ) =~ /Updated: (.*?)$/
72
- ret.updated_at = DateTime.strptime( $1, "%m/%d/%Y %I:%M %p" ).to_time
68
+ if ret.status == DELIVERED then
69
+ delivered_at = cleanup_html( hash["Delivered On:"] )
70
+ ret.delivered_at = DateTime.strptime( delivered_at, "%A, %m/%d/%Y at %I:%M %p" ).to_time
71
+ end
73
72
 
74
- return ret
73
+ cleanup_html( details.lists[3] ) =~ /Updated: (.*?)$/
74
+ ret.updated_at = DateTime.strptime( $1, "%m/%d/%Y %I:%M %p" ).to_time
75
+
76
+ return ret
77
+
78
+ rescue Exception => ex
79
+ raise Stalkr::Error.new(ex, html)
80
+
81
+ end
75
82
 
76
83
  end
77
84
 
data/lib/stalkr/usps.rb CHANGED
@@ -3,8 +3,10 @@ module Stalkr
3
3
 
4
4
  class USPS < Base
5
5
 
6
- # 20 or 22 digits, beginning with 91 (and with or without spaces between groupings)
7
- self.regex = /\b(91\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4} ?\d{2}|91\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4})\b/i
6
+ # 1) 20 or 22 digits, beginning with 91 (and with or without spaces between groupings)
7
+ # 2) 20 digits (no real pattern)
8
+ # TODO: 2nd pattern is too generic. Could also match other carriers.
9
+ self.regex = /\b(91\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4} ?\d{2}|91\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4})\b|\b(\d{20})\b/i
8
10
 
9
11
  def track(id)
10
12
 
@@ -16,62 +18,70 @@ class USPS < Base
16
18
  url.gsub!(/%CODE%/, id)
17
19
  html = fetchurl(url)
18
20
 
19
- info_scraper = Scraper.define do
21
+ begin
20
22
 
21
- array :details
22
- array :info
23
- array :txt
23
+ info_scraper = Scraper.define do
24
24
 
25
- process "span.mainTextbold", :info => :text
26
- process "td.mainTextbold", :details => :text
27
- process "td.mainText", :txt => :text
25
+ array :details
26
+ array :info
27
+ array :txt
28
28
 
29
- result :details, :info, :txt
29
+ process "span.mainTextbold", :info => :text
30
+ process "td.mainTextbold", :details => :text
31
+ process "td.mainText", :txt => :text
30
32
 
31
- end
33
+ result :details, :info, :txt
32
34
 
33
- scrape = info_scraper.scrape(html)
35
+ end
34
36
 
35
- # verify its the correct response page
36
- if scrape.info[0].gsub(/ /, '') != id then
37
- raise "USPS scraper failed"
38
- end
37
+ scrape = info_scraper.scrape(html)
39
38
 
40
- # extract and return
41
- ret = Result.new(:USPS)
42
- if scrape.txt.find{ |t| t =~ /There is no record of this item/ } then
43
- ret.status = UNKNOWN
44
- elsif scrape.info.find{ |i| i.downcase == "delivered" } then
45
- ret.status = DELIVERED
46
- else
47
- ret.status = UNKNOWN
48
- end
39
+ # verify its the correct response page
40
+ if scrape.info[0].gsub(/ /, '') != id then
41
+ raise "USPS scraper failed"
42
+ end
49
43
 
50
- if scrape.details and not scrape.details.empty? then
51
- if scrape.details[0] =~ /^(.*?), (.*? \d+, \d+), (\d+:\d+ .m), (.*?)$/ then
52
- ret.location = $4
44
+ # extract and return
45
+ ret = Result.new(:USPS)
46
+ if scrape.txt.find{ |t| t =~ /There is no record of this item/ } then
47
+ ret.status = UNKNOWN
48
+ elsif scrape.info.find{ |i| i.downcase == "delivered" } then
49
+ ret.status = DELIVERED
50
+ else
51
+ ret.status = UNKNOWN
52
+ end
53
+
54
+ if scrape.details and not scrape.details.empty? then
55
+ if scrape.details[0] =~ /^(.*?), (.*? \d+, \d+), (\d+:\d+ .m), (.*?)$/ then
56
+ ret.location = $4
57
+ # not sure if this time is always in EST or the time of the area in which it was delivered?
58
+ ret.updated_at = DateTime.strptime( "#{$2} #{$3} -0500", "%B %d, %Y %I:%M %p %z" ).to_time
59
+ if ret.status == DELIVERED then
60
+ ret.delivered_at = ret.updated_at
61
+ end
62
+
63
+ elsif scrape.details[0] =~ /Electronic Shipping Info Received/ then
64
+ ret.status = IN_TRANSIT
65
+ end
66
+
67
+ elsif s = scrape.txt.find{ |t| t =~ /files offline/ }
68
+ s =~ /at (\d+:\d+ .m) on (.*? \d+, \d+) in (.*?)\.$/
69
+ ret.location = $3
53
70
  # not sure if this time is always in EST or the time of the area in which it was delivered?
54
- ret.updated_at = DateTime.strptime( "#{$2} #{$3} -0500", "%B %d, %Y %I:%M %p %z" ).to_time
71
+ ret.updated_at = DateTime.strptime( "#{$2} #{$1} -0500", "%B %d, %Y %I:%M %p %z" ).to_time
55
72
  if ret.status == DELIVERED then
56
73
  ret.delivered_at = ret.updated_at
57
74
  end
58
75
 
59
- elsif scrape.details[0] =~ /Electronic Shipping Info Received/ then
60
- ret.status = IN_TRANSIT
61
76
  end
62
77
 
63
- elsif s = scrape.txt.find{ |t| t =~ /files offline/ }
64
- s =~ /at (\d+:\d+ .m) on (.*? \d+, \d+) in (.*?)\.$/
65
- ret.location = $3
66
- # not sure if this time is always in EST or the time of the area in which it was delivered?
67
- ret.updated_at = DateTime.strptime( "#{$2} #{$1} -0500", "%B %d, %Y %I:%M %p %z" ).to_time
68
- if ret.status == DELIVERED then
69
- ret.delivered_at = ret.updated_at
70
- end
78
+ return ret
79
+
80
+ rescue Exception => ex
81
+ raise Stalkr::Error.new(ex, html)
71
82
 
72
83
  end
73
84
 
74
- return ret
75
85
  end
76
86
 
77
87
  end # class USPS
@@ -18,9 +18,29 @@ class FEDEX_Test < Test::Unit::TestCase
18
18
 
19
19
  end
20
20
 
21
+ def test_track_bad_code_numeric
22
+
23
+ begin
24
+ id = "200793242831442"
25
+ info = Stalkr::FEDEX.new.track(id)
26
+ flunk("no exception raised")
27
+
28
+ rescue Exception => ex
29
+ assert(ex.kind_of? Stalkr::Error)
30
+ assert(!(ex.html.nil? || ex.html.empty?))
31
+ end
32
+
33
+ end
34
+
21
35
  def test_extract_id
22
36
  str = "asdf 106050761498748 asdfas"
23
37
  assert(Stalkr::FEDEX.extract_id(str) == "106050761498748")
24
38
  end
25
39
 
40
+ def test_should_not_extract
41
+ str = "Your tracking number is: 02185456301085740874. "
42
+ id = Stalkr::FEDEX.extract_id(str)
43
+ assert(id.nil?)
44
+ end
45
+
26
46
  end
@@ -30,4 +30,10 @@ class USPS_Test < Test::Unit::TestCase
30
30
  assert(Stalkr::USPS.extract_id(str) == "9102901001299192824023")
31
31
  end
32
32
 
33
+ def test_extract_id_2
34
+ str = "Your tracking number is: 02185456301085740874. "
35
+ id = Stalkr::USPS.extract_id(str)
36
+ assert(!id.nil? && id == "02185456301085740874")
37
+ end
38
+
33
39
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stalkr
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 57
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 0
10
- version: 0.9.0
9
+ - 1
10
+ version: 0.9.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Chetan Sarva
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-02 00:00:00 -05:00
18
+ date: 2011-02-16 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -111,6 +111,7 @@ files:
111
111
  - VERSION
112
112
  - lib/stalkr.rb
113
113
  - lib/stalkr/base.rb
114
+ - lib/stalkr/error.rb
114
115
  - lib/stalkr/fedex.rb
115
116
  - lib/stalkr/result.rb
116
117
  - lib/stalkr/ups.rb