mitake 0.1.2

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.
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'mitake/credential'
5
+
6
+ module Mitake
7
+ module API
8
+ # @since 0.1.0
9
+ # @api private
10
+ class Base
11
+ # @param path [String] the api endpoint
12
+ # @param params [Hash] the request body
13
+ #
14
+ # @since 0.1.0
15
+ # @api private
16
+ def initialize(path, params = {})
17
+ @path = path
18
+ @params = params
19
+ end
20
+
21
+ # @since 0.1.0
22
+ # @api private
23
+ def request
24
+ raise NotImplementedError, 'Request not defined!'
25
+ end
26
+
27
+ # Execute HTTP Request
28
+ #
29
+ # @return [Net::HTTPResponse] the request result
30
+ #
31
+ # @since 0.1.0
32
+ # @api private
33
+ def execute
34
+ Net::HTTP.start(uri.host, uri.port, use_ssl: ssl?) do |http|
35
+ http.request request
36
+ end
37
+ end
38
+
39
+ # @return [URI] the request URI
40
+ #
41
+ # @since 0.1.0
42
+ # @api private
43
+ def uri
44
+ @uri ||= URI("#{Mitake.credential.server}#{@path}")
45
+ end
46
+
47
+ # @return [TrueClass|FalseClass] is the SSL request
48
+ #
49
+ # @since 0.1.0
50
+ # @api private
51
+ def ssl?
52
+ @uri.scheme == 'https'
53
+ end
54
+
55
+ # Return the request params
56
+ #
57
+ # @return [Hash] the query params
58
+ #
59
+ # @since 0.1.0
60
+ # @api private
61
+ def params
62
+ @params.merge(
63
+ username: Mitake.credential.username,
64
+ password: Mitake.credential.password
65
+ )
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mitake/api/base'
4
+
5
+ module Mitake
6
+ module API
7
+ # Create HTTP Get Request
8
+ #
9
+ # @since 0.1.0
10
+ # @api private
11
+ class Get < Base
12
+ # Create HTTP Get Request
13
+ #
14
+ # @since 0.1.0
15
+ # @api private
16
+ def request
17
+ return @request unless @request.nil?
18
+
19
+ @request ||= Net::HTTP::Get.new(uri)
20
+ end
21
+
22
+ # @see Mitake::API::Base#uri
23
+ #
24
+ # @since 0.1.0
25
+ # @api private
26
+ def uri
27
+ @uri ||=
28
+ URI("#{Mitake.credential.server}" \
29
+ "#{@path}?#{URI.encode_www_form(params)}")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mitake/api/base'
4
+
5
+ module Mitake
6
+ module API
7
+ # Create HTTP Get Request
8
+ #
9
+ # @since 0.1.0
10
+ # @api private
11
+ class Post < Base
12
+ # Create HTTP Post Request
13
+ #
14
+ # @since 0.1.0
15
+ # @api private
16
+ def request
17
+ return @request unless @request.nil?
18
+
19
+ @request ||= Net::HTTP::Post.new(uri)
20
+ @request.body = URI.encode_www_form(params)
21
+ @request
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mitake/api'
4
+ require 'mitake/model'
5
+
6
+ module Mitake
7
+ # Get the current balance
8
+ #
9
+ # @since 0.1.0
10
+ class Balance
11
+ class << self
12
+ # Get account point
13
+ #
14
+ # @see Mitake::Balance#amount
15
+ # @return [Integer]
16
+ #
17
+ # @since 0.1.0
18
+ def amount
19
+ execute&.first&.amount
20
+ end
21
+ end
22
+
23
+ include API
24
+ include Model
25
+
26
+ path '/api/mtk/SmQuery'
27
+ map 'AccountPoint', 'amount'
28
+
29
+ # @!attribute [r] amount
30
+ # @return [Integer] the amount of account point
31
+ #
32
+ # @since 0.1.0
33
+ attribute :amount, Integer
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mitake
4
+ # The helper object to define boolean value
5
+ #
6
+ # @since 0.1.0
7
+ # @api private
8
+ class Boolean
9
+ TRUE_VALUES = %w[Y 1 yes true].freeze
10
+
11
+ class << self
12
+ # Parse boolean value
13
+ #
14
+ # @since 0.1.0
15
+ # @api private
16
+ def parse(value)
17
+ return true if value == true
18
+ return true if TRUE_VALUES.include?(value)
19
+
20
+ false
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mitake
4
+ # The Mitake SMS Client
5
+ #
6
+ # @since 0.1.
7
+ class Credential
8
+ # @since 0.1.0
9
+ # @api private
10
+ DEFAULT_SERVER = 'https://smsapi.mitake.com.tw'
11
+
12
+ # @since 0.1.0
13
+ attr_reader :username, :password, :server
14
+
15
+ # Return Mitake::Client instance
16
+ #
17
+ # @param username [String] the username, default is `MITAKE_USERNAME`
18
+ # @param password [String] the password, default is `MITAKE_PASSWORD`
19
+ # @param server [String] the API server url
20
+ # @return [Mitake::Client] the api instance
21
+ #
22
+ # @since 0.1.0
23
+ def initialize(username = nil, password = nil, server = nil)
24
+ @username = username || ENV['MITAKE_USERNAME']
25
+ @password = password || ENV['MITAKE_PASSWORD']
26
+ @server = server || ENV['MITAKE_SERVER'] || DEFAULT_SERVER
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mitake/model'
4
+ require 'mitake/recipient'
5
+ require 'mitake/response'
6
+ require 'mitake/boolean'
7
+ require 'mitake/status'
8
+
9
+ module Mitake
10
+ # Create Sort Message
11
+ #
12
+ # @since 0.1.0
13
+ class Message
14
+ include API
15
+ include Model
16
+
17
+ method 'Post'
18
+ path '/api/mtk/SmSend?CharsetURL=UTF8'
19
+ map 'msgid', 'id'
20
+ map 'Duplicate', 'duplicate'
21
+ map 'statuscode', 'status_code'
22
+
23
+ # @!attribute [r] id
24
+ # @return [String] the message id
25
+ attribute :id, String, readonly: true
26
+
27
+ # @!attribute source_id
28
+ # @return [String] the customize identity
29
+ attribute :source_id, String
30
+
31
+ # @!attribute receipient
32
+ # @return [Mitake::Recipient] the message recipient
33
+ attribute :recipient, Recipient
34
+
35
+ # @!attribute body
36
+ # @return [String] the message body
37
+ attribute :body, String
38
+
39
+ # @!attribute schedule_at
40
+ # @return [Time|NilClass] the schedule time to send message
41
+ attribute :schedule_at, Time
42
+
43
+ # @!attribute expired_at
44
+ # @return [Time|NilClass] the valid time for this message
45
+ attribute :expired_at, Time
46
+
47
+ # @!attribute webhook_url
48
+ # @return [String|NilClass] the response callback url
49
+ attribute :webhook_url, String
50
+
51
+ # @!attribute [r] duplicate
52
+ # @return [TrueClass|FalseClass] is the message duplicate
53
+ attribute :duplicate, Boolean, readonly: true
54
+
55
+ # @!attribute [r] status_code
56
+ # @return [Integer] the status code
57
+ attribute :status_code, Integer, readonly: true
58
+
59
+ # Send message
60
+ #
61
+ # @since 0.1.0
62
+ # @api private
63
+ def delivery
64
+ return self if sent?
65
+
66
+ self.class.execute(params) do |items|
67
+ attrs = items&.first&.slice(*self.class.attribute_names)
68
+ assign_attributes(attrs)
69
+ end
70
+
71
+ self
72
+ end
73
+
74
+ # Does message is sent
75
+ #
76
+ # @return [TrueClass|FalseClass] is the message sent
77
+ #
78
+ # @since 0.1.0
79
+ def sent?
80
+ !@id.nil?
81
+ end
82
+
83
+ # Does message is duplicate
84
+ #
85
+ # @return [TrueClass|FalseClass] is the message duplicate
86
+ #
87
+ # @since 0.1.0
88
+ def duplicate?
89
+ @duplicate == true
90
+ end
91
+
92
+ # Readable status code
93
+ #
94
+ # @return [String] the status code description
95
+ #
96
+ # @since 0.1.0
97
+ def status
98
+ Status::CODES[@status_code]
99
+ end
100
+
101
+ private
102
+
103
+ # The request params
104
+ #
105
+ # @since 0.1.0
106
+ # @api private
107
+ def params
108
+ {
109
+ clientid: @source_id,
110
+ smbody: @body,
111
+ dlvtime: @schedule_at&.strftime('%Y%m%d%H%M%S'),
112
+ vldtime: @expired_at&.strftime('%Y%m%d%H%M%S'),
113
+ dstaddr: @recipient.phone_number,
114
+ destname: @recipient.name,
115
+ response: @webhook_url
116
+ }.reject { |_, v| v.nil? }.to_h
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mitake/model/attributes'
4
+ require 'mitake/model/accessor'
5
+
6
+ module Mitake
7
+ # Provide attributes accessor
8
+ #
9
+ # @since 0.1.0
10
+ # @api private
11
+ module Model
12
+ # @since 0.1.0
13
+ # @api private
14
+ def self.included(base)
15
+ base.class_eval do
16
+ include Attributes
17
+ extend Accessor
18
+ end
19
+ end
20
+
21
+ # Get attributes as hash
22
+ #
23
+ # @return [Hash] the object attributes
24
+ #
25
+ # @since 0.1.0
26
+ def attributes
27
+ self
28
+ .class
29
+ .attribute_names
30
+ .map { |attr| [attr, send(attr)] }
31
+ .reject { |_, value| value.nil? }
32
+ .map do |attr, value|
33
+ [attr, value.respond_to?(:attributes) ? value.attributes : value]
34
+ end
35
+ .to_h
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+ require 'date'
5
+
6
+ module Mitake
7
+ module Model
8
+ # @since 0.1.0
9
+ # @api private
10
+ module Accessor
11
+ # Get attributes
12
+ #
13
+ # @return [Hash] the list of attributes and type
14
+ #
15
+ # @since 0.1.0
16
+ def attributes
17
+ @attributes ||= {}
18
+ end
19
+
20
+ # Get attribute names
21
+ #
22
+ # @return [Array] the list of attribute names
23
+ #
24
+ # @since 0.1.0
25
+ def attribute_names
26
+ attributes.keys
27
+ end
28
+
29
+ # Define attribute
30
+ #
31
+ # @param name [String|Symbol] the attribute name
32
+ # @param type [Class] the attribute type
33
+ # @param readonly [TrueClass|FalseClass] is attribute readonly
34
+ #
35
+ # @since 0.1.0
36
+ def attribute(name, type = 'String', readonly: false)
37
+ @attributes ||= {}
38
+ @attributes[name.to_s] = type.to_s
39
+
40
+ define_method name do
41
+ instance_variable_get("@#{name}")
42
+ end
43
+ return if readonly
44
+
45
+ define_method "#{name}=" do |value|
46
+ instance_variable_set("@#{name}", self.class.cast(value, type.to_s))
47
+ end
48
+ end
49
+
50
+ # Casting type
51
+ #
52
+ # @param value [Object] the source value
53
+ # @param type [Class] the cast type
54
+ #
55
+ # @since 0.1.0
56
+ # @api private
57
+ def cast(value, type = 'String')
58
+ case type.to_s
59
+ when 'String', 'Integer', 'Float'
60
+ Kernel.method(type).call(value)
61
+ when 'Time', 'DateTime', 'Date'
62
+ Kernel.const_get(type).parse("#{value}+8")
63
+ else
64
+ klass = Kernel.const_get(type)
65
+ return klass.parse(value) if klass.respond_to?(:parse)
66
+
67
+ value
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end