line-bot-api 0.1.0
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.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/LICENSE +202 -0
- data/README.md +216 -0
- data/lib/line/bot.rb +11 -0
- data/lib/line/bot/api/errors.rb +7 -0
- data/lib/line/bot/api/version.rb +7 -0
- data/lib/line/bot/builder/multiple_message.rb +102 -0
- data/lib/line/bot/builder/rich_message.rb +138 -0
- data/lib/line/bot/client.rb +249 -0
- data/lib/line/bot/event_type.rb +15 -0
- data/lib/line/bot/message.rb +7 -0
- data/lib/line/bot/message/audio.rb +25 -0
- data/lib/line/bot/message/base.rb +29 -0
- data/lib/line/bot/message/content_type.rb +16 -0
- data/lib/line/bot/message/image.rb +23 -0
- data/lib/line/bot/message/location.rb +28 -0
- data/lib/line/bot/message/sticker.rb +26 -0
- data/lib/line/bot/message/text.rb +22 -0
- data/lib/line/bot/message/video.rb +23 -0
- data/lib/line/bot/operation.rb +3 -0
- data/lib/line/bot/operation/add_friend.rb +10 -0
- data/lib/line/bot/operation/base.rb +17 -0
- data/lib/line/bot/operation/block_account.rb +10 -0
- data/lib/line/bot/operation/op_type.rb +10 -0
- data/lib/line/bot/receive/message.rb +60 -0
- data/lib/line/bot/receive/operation.rb +42 -0
- data/lib/line/bot/receive/request.rb +35 -0
- data/lib/line/bot/request.rb +72 -0
- data/lib/line/bot/response/user/contact.rb +22 -0
- data/lib/line/bot/response/user/profile.rb +30 -0
- data/line-bot-api.gemspec +27 -0
- metadata +147 -0
data/lib/line/bot.rb
ADDED
@@ -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,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
|