postcl 0.1.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
+ SHA256:
3
+ metadata.gz: 3a40d7ff0b0cb441c93466222593734432e962afb5dcdd1a13c79d884c3dd1f2
4
+ data.tar.gz: 964e845c9a3ca0e77f5ec591669c5a0a28201e5ae47fe252bdbc7c7af3800a31
5
+ SHA512:
6
+ metadata.gz: ce86de5496aeb0646a682a2f71b06847f9a0ba1538d16df9a3794bfb6e2a8f342e26e7d2a3dbd93960b096e44c43bd47492824a2b796d3ab2331d32bbcc98d79
7
+ data.tar.gz: a40ac71206fb4ee549b43f1b118fd73d57806d0f0eb9a7bd359a935e4e0e5d2604b460d27347c9a14f13c0f906c560f2b0c9c7c2c4a2b547343ff362d94588f5
data/.gitignore ADDED
@@ -0,0 +1,79 @@
1
+ # Environments
2
+ .env
3
+ .venv
4
+ env/
5
+ venv/
6
+ ENV/
7
+ env.bak/
8
+ venv.bak/
9
+
10
+ # Spyder project settings
11
+ .spyderproject
12
+ .spyproject
13
+
14
+ # Rope project settings
15
+ .ropeproject
16
+
17
+ # mkdocs documentation
18
+ /site
19
+
20
+ # mypy
21
+ .mypy_cache/
22
+
23
+ *.gem
24
+ *.rbc
25
+ /.config
26
+ /coverage/
27
+ /InstalledFiles
28
+ /pkg/
29
+ /spec/reports/
30
+ /spec/examples.txt
31
+ /test/tmp/
32
+ /test/version_tmp/
33
+ /tmp/
34
+
35
+ # Used by dotenv library to load environment variables.
36
+ # .env
37
+
38
+ # Ignore Byebug command history file.
39
+ .byebug_history
40
+
41
+ ## Specific to RubyMotion:
42
+ .dat*
43
+ .repl_history
44
+ build/
45
+ *.bridgesupport
46
+ build-iPhoneOS/
47
+ build-iPhoneSimulator/
48
+
49
+ ## Specific to RubyMotion (use of CocoaPods):
50
+ #
51
+ # We recommend against adding the Pods directory to your .gitignore. However
52
+ # you should judge for yourself, the pros and cons are mentioned at:
53
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
54
+ #
55
+ # vendor/Pods/
56
+
57
+ ## Documentation cache and generated files:
58
+ /.yardoc/
59
+ /_yardoc/
60
+ /doc/
61
+ /rdoc/
62
+
63
+ ## Environment normalization:
64
+ /.bundle/
65
+ /vendor/bundle
66
+ /lib/bundler/man/
67
+
68
+ # for a library or gem, you might want to ignore these files since the code is
69
+ # intended to run in multiple environments; otherwise, check them in:
70
+ # Gemfile.lock
71
+ # .ruby-version
72
+ # .ruby-gemset
73
+
74
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
75
+ .rvmrc
76
+
77
+
78
+ # VSCode
79
+ .vscode/
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+
5
+ ## [0.1.1] - 2019-08-18
6
+
7
+ ### Added
8
+
9
+ -Status command
10
+ -Package list prompt
11
+ -Auto-saving of queried packages
12
+
13
+ ## [0.1.0] - 2019-08-18
14
+
15
+ test release
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+ gem 'httparty'
3
+ gem 'colorize'
4
+ gem 'terminal-table'
5
+ gem 'docopt'
6
+ gem 'tty-prompt'
7
+ gem 'tty-spinner'
data/Gemfile.lock ADDED
@@ -0,0 +1,49 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ colorize (0.8.1)
5
+ docopt (0.6.1)
6
+ equatable (0.6.1)
7
+ httparty (0.17.0)
8
+ mime-types (~> 3.0)
9
+ multi_xml (>= 0.5.2)
10
+ mime-types (3.2.2)
11
+ mime-types-data (~> 3.2015)
12
+ mime-types-data (3.2019.0331)
13
+ multi_xml (0.6.0)
14
+ necromancer (0.5.0)
15
+ pastel (0.7.3)
16
+ equatable (~> 0.6)
17
+ tty-color (~> 0.5)
18
+ terminal-table (1.8.0)
19
+ unicode-display_width (~> 1.1, >= 1.1.1)
20
+ tty-color (0.5.0)
21
+ tty-cursor (0.7.0)
22
+ tty-prompt (0.19.0)
23
+ necromancer (~> 0.5.0)
24
+ pastel (~> 0.7.0)
25
+ tty-reader (~> 0.6.0)
26
+ tty-reader (0.6.0)
27
+ tty-cursor (~> 0.7)
28
+ tty-screen (~> 0.7)
29
+ wisper (~> 2.0.0)
30
+ tty-screen (0.7.0)
31
+ tty-spinner (0.9.1)
32
+ tty-cursor (~> 0.7)
33
+ unicode-display_width (1.6.0)
34
+ wisper (2.0.0)
35
+
36
+ PLATFORMS
37
+ ruby
38
+ x64-mingw32
39
+
40
+ DEPENDENCIES
41
+ colorize
42
+ docopt
43
+ httparty
44
+ terminal-table
45
+ tty-prompt
46
+ tty-spinner
47
+
48
+ BUNDLED WITH
49
+ 2.0.2
data/README.md ADDED
Binary file
data/ascii-sym.txt ADDED
@@ -0,0 +1,26 @@
1
+ _________H
2
+ /\ \
3
+ / \ \
4
+ | | _ |
5
+ | |[] | | []|
6
+ `-_| |`| |
7
+
8
+ _________
9
+ | |_\
10
+ |PostNL \___
11
+ | |
12
+ --( )-----( )-
13
+
14
+ __________
15
+ | ~~ |
16
+ --| |--
17
+ |__________|
18
+ ================
19
+ ( ) ( ) ( )
20
+
21
+ __________
22
+ |\ \ \
23
+ | \____\____\
24
+ | | ~~ |
25
+ \ | |
26
+ \|_________|
data/bin/postcl ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'docopt'
4
+ require 'postcl'
5
+
6
+ doc = <<DOCOPT
7
+ PostCL
8
+
9
+ Usage:
10
+ postcl (info|status) (<barcode> <postcode>)... | -p <barcode>...
11
+ postcl (info|status) -l [-a]
12
+ postcl (info|status) -e
13
+ postcl volg (<barcode> <postcode>)... | -p <barcode>...
14
+ postcl -h | --help
15
+ postcl -v
16
+
17
+ Options:
18
+ -a --alles
19
+ -l --lijst
20
+ -e --eerstvolgende
21
+ -h --help
22
+ -v
23
+
24
+ DOCOPT
25
+
26
+
27
+ begin
28
+ doc_parse = Docopt::docopt(doc)
29
+ rescue Docopt::Exit => e
30
+ puts e.message
31
+ exit 1
32
+ end
33
+
34
+ # Otherwise gets won't work
35
+ ARGV.clear
36
+
37
+ PostCL::Session.new(doc_parse)
38
+
data/lib/postcl/api.rb ADDED
@@ -0,0 +1,69 @@
1
+ class PostCL::API
2
+ class InvalidRequestError < Exception
3
+ end
4
+
5
+ def self.API_URI
6
+ "https://jouw.postnl.nl/web/api/default/shipmentStatus/"
7
+ end
8
+
9
+ def self.request(b_code, p_code)
10
+ r = HTTParty.get(self.API_URI + b_code + "-NL-" + p_code, format: :plain)
11
+ raise InvalidRequestError if r.code != 200
12
+ stat_dict = JSON.parse r.body, symbolize_names: true
13
+ PostCL::API::Response.new(stat_dict)
14
+ end
15
+ end
16
+
17
+ class PostCL::API::Response
18
+ def initialize(stat_dict)
19
+ @stat_dict = stat_dict
20
+ @info = stat_dict[:shipments][stat_dict[:barcode].to_sym]
21
+ end
22
+
23
+ private
24
+
25
+ def format_location(entity)
26
+ "#{entity[:street]} #{entity[:houseNumber]}, #{entity[:postalCode]} #{entity[:town]}"
27
+ end
28
+
29
+ def format_name(entity)
30
+ name = "#{entity[]}"
31
+ end
32
+
33
+ public
34
+
35
+ def stat_dict
36
+ @stat_dict
37
+ end
38
+
39
+ def info
40
+ @info
41
+ end
42
+
43
+ def location(mode)
44
+ nil unless mode == :sender || mode == :receiver
45
+ format_location(@info[mode])
46
+ end
47
+
48
+ def name(mode)
49
+ nil unless mode == :sender || mode == :receiver
50
+ format_name(@info[mode])
51
+ end
52
+
53
+ def stat_index
54
+ @info[:delivery][:phase][:index]
55
+ end
56
+
57
+ def stat_msg
58
+ @info[:delivery][:phase][:message]
59
+ end
60
+
61
+ def delivered?
62
+ @info[:delivery][:isDelivered]
63
+ end
64
+
65
+ def delivery_date
66
+ t = Time.parse(@info[:delivery][:deliveryDate])
67
+ t.strftime("%A %d %B, om %k:%M")
68
+ end
69
+ end
@@ -0,0 +1,60 @@
1
+ class Status < PostCL::Command
2
+ @@ART = {
3
+ 1 => [" __________", " |\\ \\ \\", " | \\____\\____\\", " | | ~~ |", " \\ | |", " \\|_________|"],
4
+ 2 => [" __________", " | ~~ |", "--| |--", " |__________|", "================", " ( ) ( ) ( )"],
5
+ 3 => [" _________", " | |_\\", " |PostNL \\___", " | |", " --( )-----( )-", ""],
6
+ 4 => [" _________H", " /\\ \\", " / \\ \\", " | | _ |", " | |[] | | []|", " `-_| |`| |"],
7
+ }
8
+
9
+ def initialize(post)
10
+ super(post)
11
+ end
12
+
13
+ private
14
+
15
+ def stat_info(row, resp)
16
+ case row
17
+ when 1
18
+ return resp.stat_msg.bold
19
+ when 2
20
+ if resp.delivered?
21
+ return "Bezorgd op: #{resp.delivery_date}"
22
+ else
23
+ return "Bezorging verwacht op: "
24
+ end
25
+ when 3
26
+ return "Bestemming: #{resp.location(:receiver)}"
27
+ else
28
+ return ""
29
+ end
30
+ end
31
+
32
+ public
33
+
34
+ def run
35
+ @args["<barcode>"].zip(@args["<postcode>"]).each do |barcode, postcode|
36
+ spin = TTY::Spinner.new("Zending #{barcode} wordt geladen :spinner...", format: :bouncing_ball, clear: true)
37
+ spin.auto_spin
38
+ begin
39
+ resp = PostCL::API.request(barcode, postcode)
40
+ spin.stop()
41
+ rescue PostCL::API::InvalidRequestError
42
+ spin.stop("Ongeldige aanvraag met barcode: #{barcode} en postcode: #{postcode}")
43
+ next
44
+ end
45
+
46
+ @store.prompt_add(resp) unless @store.include?(barcode, postcode) || @args["-n"]
47
+
48
+ puts "Status van zending: " + barcode.bold
49
+ stat_banner = Array(6)
50
+ art = @@ART[resp.stat_index]
51
+ (0..5).each do |i|
52
+ stat_banner[i] = art[i].ljust(20, " ") + stat_info(i, resp)
53
+ end
54
+ puts stat_banner.join("\n")
55
+ # puts "Van " + resp.location(:sender).red +
56
+ # " naar " + resp.location(:receiver).green
57
+ puts
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,15 @@
1
+ class Volg < PostCL::Command
2
+ def initialize(post)
3
+ super(post)
4
+ end
5
+
6
+ private
7
+
8
+
9
+
10
+ public
11
+
12
+ def run
13
+
14
+ end
15
+ end
@@ -0,0 +1,45 @@
1
+
2
+
3
+ class PostCL::Command
4
+ ARG_MATCH = {
5
+ barcode: /(3S|KG)[A-Z0-9]{13}/,
6
+ postcode: /[0-9]{4}[a-zA-Z]{2}/
7
+ }
8
+
9
+ class UnknownCommandError < Exception
10
+ end
11
+
12
+ def initialize(session)
13
+ @args = session.args
14
+ @prompt = session.prompt
15
+ @store = session.store
16
+ end
17
+
18
+ def self.validate_args(args)
19
+ args.each_key do |key|
20
+ key_sym = key[1...-1].to_sym
21
+ if ARG_MATCH.keys.include?(key_sym)
22
+ args[key].each do |arg|
23
+ next if arg.match(ARG_MATCH[key_sym])
24
+ puts "Ongeldige #{key_sym}: #{arg}"
25
+ exit 1
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def self.run(session)
32
+ if session.args["status"]
33
+ Status.new(session).run
34
+ # elsif post.args["info"]
35
+ # Info.new(post).run
36
+ elsif post.args["volg"]
37
+ Volg.new(session).run
38
+ else
39
+ raise UnknownCommandError
40
+ end
41
+ end
42
+ end
43
+
44
+ # Require all Command classes
45
+ Dir["#{File.expand_path("lib/postcl/command/")}/*.rb"].each { |f| require f }
@@ -0,0 +1,90 @@
1
+ class PostCL::Store
2
+ def initialize(session, name = "store.yaml", dir = "#{File.expand_path('~')}/.config/postcl/")
3
+ @session = session
4
+ @args = session.args
5
+ @prompt = session.prompt
6
+ @dir = dir
7
+ @path = dir + name
8
+ load
9
+
10
+ end
11
+
12
+ private
13
+
14
+ def load
15
+ begin
16
+ @data = YAML.load(File.open(@path))
17
+ rescue Errno::ENOENT
18
+ FileUtils.mkdir_p(@dir)
19
+ @data = { postcode: nil, packages: [] }
20
+ save
21
+ end
22
+ end
23
+
24
+ def save
25
+ File.open(@path, "w") { |f| f.write(@data.to_yaml) }
26
+ end
27
+
28
+ public
29
+
30
+ def add(resp)
31
+ p_elem = {
32
+ barcode: resp.info[:barcode],
33
+ postcode: resp.info[:postalCode],
34
+ undelivered: resp.info[:delivery][:isDelivered]
35
+ }
36
+ @data[:packages] << p_elem
37
+ save
38
+ end
39
+
40
+ def postcode
41
+ @data[:postcode]
42
+ end
43
+
44
+ def postcode=(postcode)
45
+ @data[:postcode] = postcode
46
+ save
47
+ end
48
+
49
+ def packages
50
+ @data[:packages]
51
+ end
52
+
53
+ def filter(f_proc)
54
+ @data[:packages].select(&f_proc)
55
+ end
56
+
57
+ def undelivered
58
+ filter(proc { |p| p[:undelivered] })
59
+ end
60
+
61
+ def package(barcode, postcode)
62
+ filter(proc { |p| p[:barcode].upcase == barcode.upcase && p[:postcode].upcase == postcode.upcase })[0]
63
+ end
64
+
65
+ def include?(barcode, postcode)
66
+ package(barcode, postcode) != nil
67
+ end
68
+
69
+ def prompt_add(resp)
70
+ if TTY::Prompt.new.yes?("Het lijkt er op dat deze zending nog niet is opgeslagen, wilt u hem toevoegen?")
71
+ add(resp)
72
+ end
73
+ end
74
+
75
+ def promt_list
76
+ p_list = @args["--alles"] ? packages : undelivered
77
+
78
+ @session.error_exit("Geen zendingen in huidige selectie.") unless p_list.size > 0
79
+
80
+ choices = []
81
+ p_list.each_with_index do |p, i|
82
+ choices << {name: "#{p[:barcode]}, #{p[:postcode]}", value: i}
83
+ end
84
+ input = @prompt.multi_select("Selecteer een of meerdere zendingen:", choices)
85
+ input.each do |i|
86
+ @args["<barcode>"] << p_list[i][:barcode]
87
+ @args["<postcode>"] << p_list[i][:postcode]
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,3 @@
1
+ module PostCL
2
+ VERSION = "0.1.1"
3
+ end
data/lib/postcl.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'colorize'
2
+ require 'fileutils'
3
+ require 'httparty'
4
+ require 'time'
5
+ require 'tty-prompt'
6
+ require 'tty-spinner'
7
+ require 'yaml'
8
+
9
+ module PostCL
10
+ class Session
11
+ attr_reader :args, :store, :prompt
12
+
13
+ def initialize(doc_parse)
14
+ @args = doc_parse
15
+ @prompt = TTY::Prompt.new
16
+ @store = Store.new(self)
17
+
18
+ @store.promt_list if @args["--lijst"]
19
+
20
+ Command.validate_args(@args)
21
+
22
+ begin
23
+ Command.run(self)
24
+ rescue Command::UnknownCommandError
25
+ puts "ongelding commando"
26
+ end
27
+ end
28
+
29
+ def error_exit(msg)
30
+ puts msg
31
+ exit 1
32
+ end
33
+ end
34
+
35
+ require_relative 'postcl/api'
36
+ require_relative 'postcl/command'
37
+ require_relative 'postcl/store'
38
+ require_relative 'postcl/version'
39
+ end
data/postcl.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "postcl/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "postcl"
7
+ spec.version = PostCL::VERSION
8
+ spec.authors = ["flevosap", "maximvdberg"]
9
+ spec.email = ["info@bami.party"]
10
+
11
+ spec.summary = %q{PostCL is een simpel terminal-script waarmee informatie een PostNL-zending opgevraagd kan worden.}
12
+ # spec.description = %q{TODO: Write a longer description or delete this line.}
13
+ spec.homepage = "https://postcl.bami.party"
14
+
15
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/SirYuSuk/postcl"
19
+ spec.metadata["changelog_uri"] = "https://github.com/SirYuSuk/postcl/blob/master/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|dev)/}) }
25
+ end
26
+
27
+ spec.executables << "postcl"
28
+ spec.require_paths = ["lib"]
29
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: postcl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - flevosap
8
+ - maximvdberg
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-08-18 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email:
16
+ - info@bami.party
17
+ executables:
18
+ - postcl
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".gitignore"
23
+ - CHANGELOG.md
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - README.md
27
+ - ascii-sym.txt
28
+ - bin/postcl
29
+ - lib/postcl.rb
30
+ - lib/postcl/api.rb
31
+ - lib/postcl/command.rb
32
+ - lib/postcl/command/status.rb
33
+ - lib/postcl/command/volg.rb
34
+ - lib/postcl/store.rb
35
+ - lib/postcl/version.rb
36
+ - postcl.gemspec
37
+ homepage: https://postcl.bami.party
38
+ licenses: []
39
+ metadata:
40
+ homepage_uri: https://postcl.bami.party
41
+ source_code_uri: https://github.com/SirYuSuk/postcl
42
+ changelog_uri: https://github.com/SirYuSuk/postcl/blob/master/CHANGELOG.md
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubygems_version: 3.0.4
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: PostCL is een simpel terminal-script waarmee informatie een PostNL-zending
62
+ opgevraagd kan worden.
63
+ test_files: []