stalkr 0.9.0 → 0.9.1

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 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