line-bot-api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ require 'line/bot/client'
2
+ require 'line/bot/api/errors'
3
+ require 'line/bot/event_type'
4
+ require 'line/bot/message'
5
+ require 'line/bot/operation'
6
+ require 'line/bot/receive/message'
7
+ require 'line/bot/receive/operation'
8
+ require 'line/bot/receive/request'
9
+ require 'line/bot/response/user/profile'
10
+ require 'line/bot/request'
11
+ require 'line/bot/api/version'
@@ -0,0 +1,7 @@
1
+ module Line
2
+ module Bot
3
+ module API
4
+ class InvalidCredentialsError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Line
2
+ module Bot
3
+ module API
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,102 @@
1
+ require 'line/bot/message'
2
+
3
+ module Line
4
+ module Bot
5
+ module Builder
6
+ class MultipleMessage
7
+
8
+ def initialize client
9
+ @messages ||= []
10
+ @client = client
11
+ end
12
+
13
+ def add_text(attrs = {})
14
+ tap {
15
+ message = Message::Text.new(
16
+ text: attrs[:text],
17
+ )
18
+ push_message(message)
19
+ }
20
+ end
21
+
22
+ def add_image(attrs = {})
23
+ tap {
24
+ message = Message::Image.new(
25
+ image_url: attrs[:image_url],
26
+ preview_url: attrs[:preview_url],
27
+ )
28
+ push_message(message)
29
+ }
30
+ end
31
+
32
+ def add_video(attrs = {})
33
+ tap {
34
+ message = Message::Video.new(
35
+ video_url: attrs[:video_url],
36
+ preview_url: attrs[:preview_url],
37
+ )
38
+ push_message(message)
39
+ }
40
+ end
41
+
42
+ def add_audio(attrs = {})
43
+ tap {
44
+ message = Message::Audio.new(
45
+ audio_url: attrs[:audio_url],
46
+ duration: attrs[:duration],
47
+ )
48
+ push_message(message)
49
+ }
50
+ end
51
+
52
+ def add_location(attrs = {})
53
+ tap {
54
+ message = Message::Location.new(
55
+ title: attrs[:title],
56
+ latitude: attrs[:latitude],
57
+ longitude: attrs[:longitude],
58
+ )
59
+ push_message(message)
60
+ }
61
+ end
62
+
63
+ def add_sticker(attrs = {})
64
+ tap {
65
+ message = Message::Sticker.new(
66
+ stkpkgid: attrs[:stkpkgid],
67
+ stkid: attrs[:stkid],
68
+ stkver: attrs[:stkver],
69
+ )
70
+ push_message(message)
71
+ }
72
+ end
73
+
74
+ def push_message(message)
75
+ raise ArgumentError, "Invalid arguments" unless message.valid?
76
+ @messages << message.content
77
+ end
78
+
79
+ def send(attrs = {})
80
+ to_mid = attrs.instance_of?(Hash) ? attrs[:to_mid] : attrs
81
+ @client.send_message(to_mid, self)
82
+ end
83
+
84
+ def event_type
85
+ 140177271400161403
86
+ end
87
+
88
+ def content
89
+ {
90
+ messageNotified: 0,
91
+ messages: @messages
92
+ }
93
+ end
94
+
95
+ def valid?
96
+ @messages.size > 0
97
+ end
98
+
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,138 @@
1
+ require 'line/bot/message'
2
+ require 'json'
3
+
4
+ module Line
5
+ module Bot
6
+ module Builder
7
+ class RichMessage
8
+
9
+ def initialize client
10
+ @actions ||= {}
11
+ @listeners ||= []
12
+ @client = client
13
+ end
14
+
15
+ def set_action(attrs = {})
16
+ tap {
17
+ attrs.each { |key, value|
18
+ raise ArgumentError, 'Invalid arguments, :text, :link_url keys.' unless validate_action_attributes(value)
19
+
20
+ @actions[key.to_s] ||= {}
21
+ @actions[key.to_s] = {
22
+ type: 'web',
23
+ text: value[:text].to_s,
24
+ params: {
25
+ linkUri: value[:link_url].to_s
26
+ },
27
+ }
28
+ }
29
+ }
30
+ end
31
+
32
+ def validate_action_attributes(attrs = {})
33
+ attrs[:text] && attrs[:link_url]
34
+ end
35
+
36
+ def add_listener(attrs = {})
37
+ tap {
38
+ raise ArgumentError, 'Invalid arguments, :x [Fixnum], :y [Fixnum], :width [Fixnum], :height [Fixnum] keys.' unless validate_listener_attributes(attrs)
39
+
40
+ listener = {
41
+ type: 'touch', # Fixed "touch".
42
+ params: [attrs[:x], attrs[:y], attrs[:width], attrs[:height]],
43
+ action: attrs[:action],
44
+ }
45
+ @listeners << listener
46
+ }
47
+ end
48
+
49
+ def validate_listener_attributes(attrs = {})
50
+ attrs[:action].instance_of?(String) &&
51
+ attrs[:x].instance_of?(Fixnum) &&
52
+ attrs[:y].instance_of?(Fixnum) &&
53
+ attrs[:width].instance_of?(Fixnum) &&
54
+ attrs[:height].instance_of?(Fixnum)
55
+ end
56
+
57
+ # send rich message to line server and to users
58
+ #
59
+ # @param attrs [Hash]
60
+ # @param attrs [:to_mid] [String or Array] line user's mids
61
+ # @param attrs [:image_url] [String] image file's url
62
+ # @param attrs [:alt_text] [String] alt text for image file's url
63
+ # @raise [ArgumentError] Error raised when supplied argument are missing :to_mid, :image_url, :preview_url keys.
64
+ #
65
+ # @return [Net::HTTPResponse] response for a request to line server
66
+ def send(attrs = {})
67
+ @image_url = attrs[:image_url]
68
+ @alt_text = attrs[:alt_text]
69
+
70
+ @client.send_message(attrs[:to_mid], self)
71
+ end
72
+
73
+ def height
74
+ height = 0
75
+ @listeners.each { |listener|
76
+ h = listener[:params][1] + listener[:params][3] # params.y + params.height
77
+ height = h if height < h
78
+ }
79
+
80
+ height > 2080 ? 2080 : height
81
+ end
82
+
83
+ def event_type
84
+ 138311608800106203
85
+ end
86
+
87
+ def content
88
+ {
89
+ contentType: Line::Bot::Message::ContentType::RICH_MESSAGE,
90
+ toType: 1,
91
+ contentMetadata: {
92
+ DOWNLOAD_URL: @image_url,
93
+ SPEC_REV: "1", # Fixed "1".
94
+ ALT_TEXT: @alt_text,
95
+ MARKUP_JSON: markup_json,
96
+ },
97
+ }
98
+ end
99
+
100
+ def valid?
101
+ @image_url && @alt_text
102
+ end
103
+
104
+ def markup_json
105
+ {
106
+ canvas: {
107
+ height: height,
108
+ width: 1040, # Integer fixed value: 1040
109
+ initialScene: 'scene1',
110
+ },
111
+ images: {
112
+ image1: {
113
+ x: 0,
114
+ y: 0,
115
+ width: 1040, # Integer fixed value: 1040
116
+ height: height
117
+ },
118
+ },
119
+ actions: @actions,
120
+ scenes: {
121
+ scene1: {
122
+ draws: {
123
+ image: 'image1', # Use the image ID "image1".
124
+ x: 0,
125
+ y: 0,
126
+ width: 1040, # Integer fixed value: 1040
127
+ height: height
128
+ },
129
+ listeners: @listeners
130
+ }
131
+ }
132
+ }.to_json
133
+ end
134
+
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,249 @@
1
+ require 'line/bot/message'
2
+ require 'line/bot/request'
3
+ require 'line/bot/builder/rich_message'
4
+ require 'line/bot/builder/multiple_message'
5
+ require 'line/bot/api/errors'
6
+ require 'base64'
7
+ require 'net/http'
8
+
9
+ module Line
10
+ module Bot
11
+ class Client
12
+ attr_accessor :channel_id, :channel_secret, :channel_mid
13
+
14
+ # Initializes a new Bot Client
15
+ #
16
+ # @param options [Hash]
17
+ # @return [LINE::Bot::Client]
18
+ def initialize
19
+ yield(self) if block_given?
20
+ end
21
+
22
+ # @return [Hash]
23
+ def credentials
24
+ {
25
+ 'X-Line-ChannelID' => channel_id,
26
+ 'X-Line-ChannelSecret' => channel_secret,
27
+ 'X-Line-Trusted-User-With-ACL' => channel_mid,
28
+ }
29
+ end
30
+
31
+ def credentials?
32
+ credentials.values.all?
33
+ end
34
+
35
+ # Sends text to users
36
+ #
37
+ # @param attrs [Hash]
38
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
39
+ # @param attrs [:text] [String]
40
+ # @raise [ArgumentError] Error raised when supplied argument are missing :to_mid, :text keys.
41
+ #
42
+ # @return [Net::HTTPResponse]
43
+ def send_text(attrs = {})
44
+ message = Message::Text.new(
45
+ text: attrs[:text],
46
+ )
47
+ send_message(attrs[:to_mid], message)
48
+ end
49
+
50
+ # Sends image to users
51
+ #
52
+ # @param attrs [Hash]
53
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
54
+ # @param attrs [:image_url] [String] Image file's url
55
+ # @param attrs [:preview_url] [String] Preview image file's url
56
+ # @raise [ArgumentError] Error raised when supplied argument are missing :to_mid, :image_url, :preview_url keys.
57
+ #
58
+ # @return [Net::HTTPResponse]
59
+ def send_image(attrs = {})
60
+ message = Message::Image.new(
61
+ image_url: attrs[:image_url],
62
+ preview_url: attrs[:preview_url],
63
+ )
64
+ send_message(attrs[:to_mid], message)
65
+ end
66
+
67
+ # Sends video to users
68
+ #
69
+ # @param attrs [Hash]
70
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
71
+ # @param attrs [:video_url] [String] Video file's url
72
+ # @param attrs [:preview_url] [String] Preview image file's url
73
+ # @raise [ArgumentError] Error raised when supplied argument are missing :to_mid, :video_url, :preview_url keys.
74
+ #
75
+ # @return [Net::HTTPResponse]
76
+ def send_video(attrs = {})
77
+ message = Message::Video.new(
78
+ video_url: attrs[:video_url],
79
+ preview_url: attrs[:preview_url],
80
+ )
81
+ send_message(attrs[:to_mid], message)
82
+ end
83
+
84
+ # Sends audio to users
85
+ #
86
+ # @param attrs [Hash]
87
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
88
+ # @param attrs [:audio_url] [String] Audio file's url
89
+ # @param attrs [:duration] [String or Integer] Voice message's length, milliseconds
90
+ # @raise [ArgumentError] Error raised when supplied argument are missing :to_mid, :audio_url, :duration keys.
91
+ #
92
+ # @return [Net::HTTPResponse]
93
+ def send_audio(attrs = {})
94
+ message = Message::Audio.new(
95
+ audio_url: attrs[:audio_url],
96
+ duration: attrs[:duration],
97
+ )
98
+ send_message(attrs[:to_mid], message)
99
+ end
100
+
101
+ # Sends location to users
102
+ #
103
+ # @param attrs [Hash]
104
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
105
+ # @param attrs [:title] [String] Location's title
106
+ # @param attrs [:address] [String] Location's address
107
+ # @param attrs [:latitude] [Float] Location's latitude
108
+ # @param attrs [:longitude] [Float] Location's longitude
109
+ # @raise [ArgumentError] Error raised when supplied argument are missing :to_mid, :title, :latitude, :longitude keys.
110
+ #
111
+ # @return [Net::HTTPResponse]
112
+ def send_location(attrs = {})
113
+ message = Message::Location.new(
114
+ title: attrs[:title],
115
+ address: attrs[:address],
116
+ latitude: attrs[:latitude],
117
+ longitude: attrs[:longitude],
118
+ )
119
+ send_message(attrs[:to_mid], message)
120
+ end
121
+
122
+ # Sends sticker to users
123
+ #
124
+ # @param attrs [Hash]
125
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
126
+ # @param attrs [:stkpkgid] [String or Integer] Sticker's package identifier
127
+ # @param attrs [:stkid] [String or Integer] Sticker's identifier
128
+ # @param attrs [:stkver] [String or Integer] Sticker's version number
129
+ # @raise [ArgumentError] Error raised when supplied argument are missing :to_mid, :stkpkgid, :stkid, :stkver keys.
130
+ #
131
+ # @return [Net::HTTPResponse]
132
+ def send_sticker(attrs = {})
133
+ message = Message::Sticker.new(
134
+ stkpkgid: attrs[:stkpkgid],
135
+ stkid: attrs[:stkid],
136
+ stkver: attrs[:stkver],
137
+ )
138
+ send_message(attrs[:to_mid], message)
139
+ end
140
+
141
+ # Sends message to line server and to users
142
+ #
143
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
144
+ # @param message [Line::Bot::Message]
145
+ # @raise [ArgumentError] Error raised when supplied argument are missing message.
146
+ #
147
+ # @return [Net::HTTPResponse]
148
+ def send_message(to_mid, message)
149
+ raise Line::Bot::API::InvalidCredentialsError, 'Invalidates credentials' unless credentials?
150
+
151
+ request = Request.new do |config|
152
+ config.endpoint_path = '/v1/events'
153
+ config.credentials = credentials
154
+ config.to_mid = to_mid
155
+ config.message = message
156
+ end
157
+
158
+ request.post
159
+ end
160
+
161
+ # Gets message content
162
+ #
163
+ # @param identifer [String] Message's identifier
164
+ #
165
+ # @raise [ArgumentError] Error raised when supplied argument are missing message.
166
+ #
167
+ # @return [Net::HTTPResponse]
168
+ def get_message_content(identifer)
169
+ endpoint_path = "/v1/bot/message/#{identifer}/content"
170
+ get(endpoint_path)
171
+ end
172
+
173
+ # Gets preview of message content
174
+ #
175
+ # @param identifer [String] Message's identifier
176
+ #
177
+ # @raise [ArgumentError] Error raised when supplied argument are missing message.
178
+ #
179
+ # @return [Net::HTTPResponse]
180
+ def get_message_content_preview(identifer)
181
+ endpoint_path = "/v1/bot/message/#{identifer}/content/preview"
182
+ get(endpoint_path)
183
+ end
184
+
185
+ # Gets user profile
186
+ #
187
+ # @param attrs [:to_mid] [String or Array] User's indentifiers
188
+ #
189
+ # @raise [ArgumentError] Error raised when supplied argument are missing message.
190
+ # @raise [HTTPError]
191
+ #
192
+ # @return [Line::Bot::Response::User::Profile]
193
+ def get_user_profile(mids)
194
+ mids = mids.instance_of?(String) ? [mids] : mids
195
+ endpoint_path = "/v1/profiles?mids=#{mids.join(',')}"
196
+
197
+ response = get(endpoint_path)
198
+
199
+ Line::Bot::Response::User::Profile.new(response) if !response.value
200
+ end
201
+
202
+ # Fetches data
203
+ #
204
+ # @param endpoint_path [String]
205
+ #
206
+ # @return [Net::HTTPResponse]
207
+ def get(endpoint_path)
208
+ raise Line::Bot::API::InvalidCredentialsError, 'Invalidates credentials' unless credentials?
209
+
210
+ request = Request.new do |config|
211
+ config.endpoint_path = endpoint_path
212
+ config.credentials = credentials
213
+ end
214
+
215
+ request.get
216
+ end
217
+
218
+ # Creates rich message to line server and to users
219
+ #
220
+ # @return [Line::Bot::Builder::RichMessage]
221
+ def rich_message
222
+ Line::Bot::Builder::RichMessage.new(self)
223
+ end
224
+
225
+ # Creates multiple message to line server and to users
226
+ #
227
+ # @return [Line::Bot::Builder::MultipleMessage]
228
+ def multiple_message
229
+ Line::Bot::Builder::MultipleMessage.new(self)
230
+ end
231
+
232
+ # Validates signature
233
+ #
234
+ # @param content [String] Request's body
235
+ # @param channel_signature [String] Request'header 'X-LINE-ChannelSignature' # HTTP_X_LINE_CHANNELSIGNATURE
236
+ #
237
+ # @return [Boolean]
238
+ def validate_signature(content = "", channel_signature)
239
+ return false unless !channel_signature.nil? && credentials?
240
+
241
+ hash = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA256.new, channel_secret, content)
242
+ signature = Base64.strict_encode64(hash)
243
+
244
+ channel_signature == signature
245
+ end
246
+ end
247
+
248
+ end
249
+ end