kuroneko 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bf2d1cc3857d488435e9c5efa8ce9b6523e848ad
4
+ data.tar.gz: 272673dc919d28a7577b4ef66b4b7cd320401c5c
5
+ SHA512:
6
+ metadata.gz: 93cd11cea58a67c145aa1e415e5b9355d3ea6c262aa81f058ad09d9e302121838ec7114f348128119d3cdbed7c36192aa686115e2238e3ff437aec3c38f8121a
7
+ data.tar.gz: 35bdec0ab36607c3eaa837d73ece53cd1b561837be441b003d6d543c68d991e3ef4ab362f4e3c1d5e29293dbe9443055ebc37287d4a88456c02b7e5a6288f271
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kuroneko.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 wktk
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Kuroneko
2
+
3
+ クロネコヤマトの荷物追跡を照会する
4
+
5
+ See also: http://toi.kuronekoyamato.co.jp/cgi-bin/tneko
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'kuroneko'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install kuroneko
20
+
21
+ ## Usage
22
+
23
+ ``` ruby
24
+ require "kuroneko"
25
+
26
+ neko = Kuroneko.new
27
+
28
+ # 1 つの荷物の状態履歴
29
+ history = neko.history("1234-5678-9012")
30
+
31
+ # 複数の荷物の状態履歴
32
+ histories = neko.histories("1234-5678-9012", "1234-5678-9013", ... )
33
+
34
+ # 1 つの荷物の最新状態
35
+ status = neko.status("1234-5678-9012")
36
+ # OR
37
+ status = history.latest
38
+ status = history.find(&:latest?)
39
+
40
+ # 複数の荷物の最新状態
41
+ statuses = neko.statuses("1234-5678-9012", "1234-5678-9013", ... )
42
+
43
+ ```
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/kuroneko.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kuroneko/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kuroneko"
8
+ spec.version = Kuroneko::VERSION
9
+ spec.authors = ["wktk"]
10
+ spec.email = ["mail@wktk.jp"]
11
+ spec.description = %q{クロネコヤマトの荷物追跡を照会する}
12
+ spec.summary = spec.description
13
+ spec.homepage = "https://github.com/wktk/kuroneko"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "mechanize", "~> 2.7"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
@@ -0,0 +1,65 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ class Kuroneko
4
+ # 状態情報
5
+ Status = Struct.new(:number, :status, :date, :time, :branch, :branch_code)
6
+
7
+ class Status
8
+ # @!attribute number
9
+ # @return [String] 伝票番号
10
+ # @example
11
+ # "123456789012"
12
+ # @note 数字以外 (ハイフン等) は含まない
13
+
14
+ # @!attribute status
15
+ # @return [String] 状態名
16
+ # @example
17
+ # "配達完了"
18
+
19
+ # @!attribute date
20
+ # @return [String] 状態発生日
21
+ # @example
22
+ # "12/31"
23
+
24
+ # @!attribute time
25
+ # @return [String] 状態発生時刻
26
+ # @example
27
+ # "12:59"
28
+
29
+ # @!attribute branch
30
+ # @return [String] 担当店
31
+ # @example
32
+ # "北東京ベース店"
33
+
34
+ # @!attribute branch_code
35
+ # @return [String] 担当店コード
36
+ # @example
37
+ # "030990"
38
+
39
+ # @param [String] number 伝票番号
40
+ # @param [Nokogiri::XML::Element] status 状態情報のテーブル行
41
+ # @param [Boolean] latest 最新の状態であるか
42
+ def initialize(number, status, latest=nil)
43
+ super(number, *parse(status))
44
+ @latest = latest unless latest.nil?
45
+ end
46
+
47
+ # @return [Boolean] 最新の状態であるか
48
+ def latest?
49
+ @latest
50
+ end
51
+
52
+ private
53
+
54
+ # 状態を解析する
55
+ #
56
+ # @param [Nokogiri::XML::Element] status 状態情報のテーブル行
57
+ # @return [Array<String>] 状態
58
+ def parse(status)
59
+ return status unless status.is_a?(Nokogiri::XML::Element)
60
+ attrs = status.css('td').to_a
61
+ @latest = attrs.shift.css('img').attribute('alt').value == '最新'
62
+ attrs.map! { |elem| elem.text.encode('utf-8') }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ class Kuroneko
4
+ # 状態履歴
5
+ class StatusHistory < Array
6
+ # @return [String] 伝票番号
7
+ # @note 数字以外 (ハイフン等) は含まない
8
+ attr_reader :number
9
+
10
+ # @param [String] number 伝票番号
11
+ # @param [Nokogiri::XML::Element] table 状態履歴テーブル
12
+ def initialize(number, table)
13
+ @number = number
14
+ super(parse(table))
15
+ end
16
+
17
+ # @return [Kuroneko::Status] 履歴のうち最新の状態
18
+ def latest
19
+ find(&:latest?) || last
20
+ end
21
+
22
+ private
23
+
24
+ # 状態履歴テーブルを解析する
25
+ #
26
+ # @param [Nokogiri::XML::Element] table 状態履歴テーブル
27
+ # @return [Array<Kuroneko::Status>] 状態
28
+ def parse(table)
29
+ return table unless table.is_a?(Nokogiri::XML::Element)
30
+ statuses = table.css('tr').to_a
31
+ statuses.shift
32
+ statuses.map! { |status| Status.new(number, status) }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,4 @@
1
+ class Kuroneko
2
+ # @return [String] バージョン
3
+ VERSION = '0.0.1'
4
+ end
data/lib/kuroneko.rb ADDED
@@ -0,0 +1,110 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'mechanize'
4
+ require 'kuroneko/status'
5
+ require 'kuroneko/status_history'
6
+ require 'kuroneko/version'
7
+
8
+ # クロネコヤマトの荷物を追跡する
9
+ #
10
+ # @see http://toi.kuronekoyamato.co.jp/cgi-bin/tneko
11
+ class Kuroneko
12
+ # @return [Mechanize] 使用する Mechanize インスタンス
13
+ attr_accessor :agent
14
+
15
+ # @return [String] 問い合わせフォームの URL
16
+ attr_accessor :url
17
+
18
+ # インスタンスを初期化する
19
+ #
20
+ # @param [Hash] options
21
+ # @option options [Mechanize] :agent 使用する Mechanize インスタンス
22
+ # @option options [String] :url 問い合わせフォームの URL
23
+ def initialize(options={})
24
+ @agent = options[:agent] || Mechanize.new
25
+ @url = options[:url] || 'http://toi.kuronekoyamato.co.jp/cgi-bin/tneko'
26
+ end
27
+
28
+ # 1 つの荷物の状態履歴を照会する
29
+ #
30
+ # @param [String, #to_s] number 伝票番号
31
+ # @return [Kuroneko::StatusHistory<Kuroneko::Status>] 状態履歴
32
+ def history(number)
33
+ histories(number).first
34
+ end
35
+
36
+ # 複数の荷物の状態履歴を照会する
37
+ #
38
+ # @param [Array<String, #to_s>] numbers 伝票番号
39
+ # @return [Array<Kuroneko::StatusHistory<Kuroneko::Status>>] 状態履歴
40
+ def histories(*numbers)
41
+ numbers.flatten!
42
+ results = []
43
+ results.concat(query(numbers.shift(10))) until numbers.empty?
44
+ results
45
+ end
46
+
47
+ # 1 つの荷物の最新状態を照会する
48
+ #
49
+ # @param [String, #to_s] number 伝票番号
50
+ # @return [Kuroneko::Status] 最新状態
51
+ def status(number)
52
+ history(number).latest
53
+ end
54
+
55
+ # 複数の荷物の最新状態を取得する
56
+ #
57
+ # @param [Array<String, #to_s>] numbers 伝票番号
58
+ # @return [Array<Kuroneko::Status>] 最新状態
59
+ def statuses(*numbers)
60
+ histories(*numbers).map(&:latest)
61
+ end
62
+
63
+ private
64
+
65
+ # ページをから情報を抽出する
66
+ #
67
+ # @param [Mechanize::Page] page 照会結果のページ
68
+ # @return [Array<Kuroneko::StatusHistory<Kuroneko::Status>>] 状態履歴
69
+ def parse(page)
70
+ page.parser.css('table.saisin').map do |summary|
71
+ rows = summary.css('tr')
72
+ number = rows[0].css('td')[2].text.gsub(/\D/, '')
73
+ status = rows[1].css('td')[2].text
74
+
75
+ history = summary.parent.css('table.meisai').first
76
+ history ||= [Status.new(number, [status], true)] # 伝票番号誤りなど
77
+ StatusHistory.new(number, history)
78
+ end
79
+ end
80
+
81
+ # フォームパラメータをセットする
82
+ #
83
+ # @param [Mechanize::Form] form
84
+ # @param [Array<String, #to_s>] numbers 伝票番号
85
+ # @return [void]
86
+ def prepare_form(form, numbers)
87
+ numbers.each.with_index(1) do |number, index|
88
+ form["number%02d" % index] = number
89
+ end
90
+ end
91
+
92
+ # リクエストを送信して状態を抽出する
93
+ #
94
+ # @param [Array<String, #to_s>] numbers 伝票番号
95
+ # @return [Array<Kuroneko::StatusHistory<Kuroneko::Status>>] 状態履歴
96
+ def query(numbers)
97
+ result_page = request(numbers)
98
+ parse(result_page)
99
+ end
100
+
101
+ # 照会リクエストを送る
102
+ #
103
+ # @param [Array<String, #to_s>] numbers 伝票番号、1 度に 10 件まで
104
+ # @return [Mechanize::Page] 照会結果のページ
105
+ def request(numbers)
106
+ form = agent.get(url).form
107
+ prepare_form(form, numbers)
108
+ form.submit
109
+ end
110
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kuroneko
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - wktk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mechanize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: "クロネコヤマトの荷物追跡を照会する"
56
+ email:
57
+ - mail@wktk.jp
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - kuroneko.gemspec
68
+ - lib/kuroneko.rb
69
+ - lib/kuroneko/status.rb
70
+ - lib/kuroneko/status_history.rb
71
+ - lib/kuroneko/version.rb
72
+ homepage: https://github.com/wktk/kuroneko
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.0.3
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: "クロネコヤマトの荷物追跡を照会する"
96
+ test_files: []
97
+ has_rdoc: