line-message-builder 0.7.0 → 0.9.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 +4 -4
- data/.document +3 -0
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +35 -0
- data/CONVENTIONS.md +36 -0
- data/README.md +49 -31
- data/lib/line/message/builder/actions/message.rb +67 -1
- data/lib/line/message/builder/actions/postback.rb +71 -1
- data/lib/line/message/builder/actions.rb +18 -1
- data/lib/line/message/builder/base.rb +113 -3
- data/lib/line/message/builder/container.rb +125 -5
- data/lib/line/message/builder/context.rb +111 -3
- data/lib/line/message/builder/flex/actionable.rb +46 -1
- data/lib/line/message/builder/flex/box.rb +191 -15
- data/lib/line/message/builder/flex/bubble.rb +96 -8
- data/lib/line/message/builder/flex/builder.rb +74 -8
- data/lib/line/message/builder/flex/button.rb +104 -17
- data/lib/line/message/builder/flex/carousel.rb +71 -8
- data/lib/line/message/builder/flex/image.rb +105 -20
- data/lib/line/message/builder/flex/partial.rb +94 -9
- data/lib/line/message/builder/flex/position.rb +122 -12
- data/lib/line/message/builder/flex/separator.rb +41 -0
- data/lib/line/message/builder/flex/size.rb +65 -7
- data/lib/line/message/builder/flex/span.rb +110 -0
- data/lib/line/message/builder/flex/text.rb +176 -28
- data/lib/line/message/builder/flex.rb +56 -12
- data/lib/line/message/builder/quick_reply.rb +16 -4
- data/lib/line/message/builder/text.rb +12 -1
- data/lib/line/message/builder/version.rb +1 -1
- data/lib/line/message/builder.rb +33 -3
- data/lib/line/message/rspec/matchers/have_flex_component.rb +11 -0
- data/lib/line/message/rspec/matchers/have_flex_separator.rb +20 -0
- data/lib/line/message/rspec/matchers.rb +1 -0
- data/lib/line/message/rspec.rb +14 -0
- data/llm.txt +437 -0
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0b31fce5c00d5f47ade90df479d30b79361f73e3e08852e10f4f90996de5bb9
|
4
|
+
data.tar.gz: 6a72a291942bd3f7448f5a294da49dd3321424d5dad057745590e4b96b1a1abb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb358c2a18903395e07bfc878d3befe2048ad23c5d68b4e5cd23e17e1914bb300f7a692858a68f9c71daa3630b1f30761ab5fc603887296c1d1cffd4964b7414
|
7
|
+
data.tar.gz: 342237372588844319052e9be35b1014024f5f93552f99699137f19a5abf7f341bd03eda306f4f2c5d181c50f257f47fdf5f0a7899cc2093312a91d4cd42667f
|
data/.document
ADDED
@@ -1 +1 @@
|
|
1
|
-
{".":"0.
|
1
|
+
{".":"0.9.0"}
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,40 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.9.0](https://github.com/elct9620/line-message-builder/compare/v0.8.0...v0.9.0) (2025-06-03)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* add flex separator matcher and tests for flex message components ([0d34bc9](https://github.com/elct9620/line-message-builder/commit/0d34bc9fcfeef9d2ca519548f4a83a3de046eb33))
|
9
|
+
* add Flex::Span message builder for LINE messaging API ([a8377e9](https://github.com/elct9620/line-message-builder/commit/a8377e93861fa286e95a69d3cb3c9897c1992044))
|
10
|
+
* add have_line_flex_span matcher and comprehensive tests for span component ([b9072cd](https://github.com/elct9620/line-message-builder/commit/b9072cd3e4c56c9346bb3d6cf98ee11374029807))
|
11
|
+
* add Separator builder for Flex messages ([accb2aa](https://github.com/elct9620/line-message-builder/commit/accb2aa41f9a016445f377f97e93f085734764c4))
|
12
|
+
* add separator method to Flex::Box for adding separator elements ([4125ae1](https://github.com/elct9620/line-message-builder/commit/4125ae15fd5666431ec864121cf40d3c4fb0f56f))
|
13
|
+
* add Span component for styled text in Flex Messages ([a458d1d](https://github.com/elct9620/line-message-builder/commit/a458d1d2473e0859bc7e1c81254888a8c8fde9a7))
|
14
|
+
* add span method to flex box builder and remove related specs ([af8dc8f](https://github.com/elct9620/line-message-builder/commit/af8dc8f9f4b8c8a7a12c15db23a50331dfc102cb))
|
15
|
+
* add support for spans within flex text components ([90ab15d](https://github.com/elct9620/line-message-builder/commit/90ab15df7044d15308d23ef864a69f84d71e28e7))
|
16
|
+
|
17
|
+
|
18
|
+
### Bug Fixes
|
19
|
+
|
20
|
+
* add Flex::Separator component and require it in flex.rb ([4152c10](https://github.com/elct9620/line-message-builder/commit/4152c1024a7634b526f94fa4e76a518a6ff0787c))
|
21
|
+
* ensure matcher finds flex separator in all nested containers ([d289ea1](https://github.com/elct9620/line-message-builder/commit/d289ea178e17d4ca00b796a9f666c527982d82f6))
|
22
|
+
* remove duplicate Separator class definition in flex separator.rb ([2c6b6d0](https://github.com/elct9620/line-message-builder/commit/2c6b6d063a2da97a0781591a697cf3034cb135f6))
|
23
|
+
|
24
|
+
## [0.8.0](https://github.com/elct9620/line-message-builder/compare/v0.7.0...v0.8.0) (2025-05-24)
|
25
|
+
|
26
|
+
|
27
|
+
### Features
|
28
|
+
|
29
|
+
* Add GitHub Action for RDoc generation and deployment ([dbb0f79](https://github.com/elct9620/line-message-builder/commit/dbb0f797ae6143bb9f463c8e6c111a5fe1f0a53f))
|
30
|
+
* Add GitHub Action for RDoc generation and deployment ([#9](https://github.com/elct9620/line-message-builder/issues/9)) ([c1a9920](https://github.com/elct9620/line-message-builder/commit/c1a99203b3abef99d149ecc7a055367268f5c2f8))
|
31
|
+
* add mode option to Line::Message::Builder for SDKv2 support ([f44f787](https://github.com/elct9620/line-message-builder/commit/f44f78758f5cac1dda6cf86f4c1945365c6c1018))
|
32
|
+
|
33
|
+
|
34
|
+
### Bug Fixes
|
35
|
+
|
36
|
+
* pass context to quick reply actions to resolve sdkv2 method error ([1bec753](https://github.com/elct9620/line-message-builder/commit/1bec7539421c0c11b10d2e906f9ee7f44a1c726f))
|
37
|
+
|
3
38
|
## [0.7.0](https://github.com/elct9620/line-message-builder/compare/v0.6.1...v0.7.0) (2025-05-21)
|
4
39
|
|
5
40
|
|
data/CONVENTIONS.md
CHANGED
@@ -16,6 +16,42 @@ This gem is designed to provide DSL (Domain Specific Language) for building LINE
|
|
16
16
|
|
17
17
|
Only use comments for RDoc documentation. Do not use comments to explain anything in the code. The code should be self-explanatory. If you find yourself needing to write a comment to explain something, consider refactoring the code instead.
|
18
18
|
|
19
|
+
## DSL
|
20
|
+
|
21
|
+
When using the `Line::Message::Builder` DSL, following is recommended:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
Line::Message::Builder.with do
|
25
|
+
flex alt_text: "Hello, World!" do
|
26
|
+
bubble do
|
27
|
+
header do
|
28
|
+
text "Welcome to LINE Messaging API"
|
29
|
+
end
|
30
|
+
body do
|
31
|
+
text "This is a sample message."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
DO NOT use `do |container|` syntax as following:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
Line::Message::Builder.with do |builder|
|
42
|
+
builder.flex alt_text: "Hello, World!" do
|
43
|
+
builder.bubble do
|
44
|
+
builder.header do
|
45
|
+
builder.text "Welcome to LINE Messaging API"
|
46
|
+
end
|
47
|
+
builder.body do
|
48
|
+
builder.text "This is a sample message."
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
19
55
|
## RSpec
|
20
56
|
|
21
57
|
- Write feature tests instead of unit tests, use `Line::Message::Builder` as test subject to verify the behavior of the DSL.
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[](https://github.com/elct9620/line-message-builder/actions/workflows/main.yml)
|
4
4
|
[](https://codecov.io/gh/elct9620/line-message-builder)
|
5
5
|
[](https://deepwiki.com/elct9620/line-message-builder)
|
6
|
+
[](https://elct9620.github.io/line-message-builder/)
|
6
7
|
|
7
8
|
Build LINE messages using DSL (Domain Specific Language) in Ruby.
|
8
9
|
|
@@ -11,6 +12,7 @@ Build LINE messages using DSL (Domain Specific Language) in Ruby.
|
|
11
12
|
- Build LINE messages using DSL
|
12
13
|
- Validation of properties
|
13
14
|
- RSpec matchers for testing
|
15
|
+
- LINE Bot SDK v2 support (Experimental)
|
14
16
|
|
15
17
|
## Installation
|
16
18
|
|
@@ -31,18 +33,32 @@ gem install line-message-builder
|
|
31
33
|
> [!NOTE]
|
32
34
|
> Working in progress.
|
33
35
|
|
36
|
+
### LLM.txt
|
37
|
+
|
38
|
+
The `llm.txt` is available in document assets.
|
39
|
+
|
40
|
+
You can get it from [http://aotoki.me/line-message-builder/llm.txt](http://aotoki.me/line-message-builder/llm.txt).
|
41
|
+
|
34
42
|
### Builder
|
35
43
|
|
36
44
|
```ruby
|
37
45
|
builder = Line::MessageBuilder::Builder.with do
|
38
|
-
|
46
|
+
text "Hello, world!"
|
39
47
|
end
|
40
48
|
|
41
49
|
pp builder.build
|
42
50
|
# => [{ type: "text", text: "Hello, world!" }]
|
43
51
|
|
44
52
|
puts builder.to_json
|
45
|
-
# => {"type"
|
53
|
+
# => "[{\"type\":\"text",\"text\":\"Hello, world!\"}"
|
54
|
+
```
|
55
|
+
|
56
|
+
To use with [line-bot-sdk-ruby](https://github.com/line/line-bot-sdk-ruby) v2, you can set mode to `sdkv2`:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
builder = Line::MessageBuilder::Builder.with(mode: :sdkv2) do
|
60
|
+
text "Hello, world!"
|
61
|
+
end
|
46
62
|
```
|
47
63
|
|
48
64
|
### Context
|
@@ -51,18 +67,18 @@ The context can make `Builder` to access additional methods and variables.
|
|
51
67
|
|
52
68
|
```ruby
|
53
69
|
context = OpenStruct.new(
|
54
|
-
|
70
|
+
name: "John Doe",
|
55
71
|
)
|
56
72
|
|
57
73
|
builder = Line::MessageBuilder::Builder.with(context) do
|
58
|
-
|
74
|
+
text "Hello, #{name}!"
|
59
75
|
end
|
60
76
|
|
61
77
|
pp builder.build
|
62
78
|
# => [{ type: "text", text: "Hello, John Doe!" }]
|
63
79
|
|
64
80
|
puts builder.to_json
|
65
|
-
# => {"type"
|
81
|
+
# => "[{\"type\":\"text\",\"text\":\"Hello, John Doe!\"}"
|
66
82
|
```
|
67
83
|
|
68
84
|
For Rails, you can use `view_context` to make `Builder` to access Rails helpers.
|
@@ -70,12 +86,12 @@ For Rails, you can use `view_context` to make `Builder` to access Rails helpers.
|
|
70
86
|
```ruby
|
71
87
|
# app/controllers/line_controller.rb
|
72
88
|
builder = Line::MessageBuilder::Builder.with(view_context) do
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
89
|
+
text "Anything you want?" do
|
90
|
+
quick_reply do
|
91
|
+
message "Yes", label: "Yes", image_url: image_url("yes.png")
|
92
|
+
message "No", label: "No", image_url: image_url("no.png")
|
78
93
|
end
|
94
|
+
end
|
79
95
|
end
|
80
96
|
```
|
81
97
|
|
@@ -84,18 +100,18 @@ If not in controller, you can create a `ActionView::Base` instance and pass it t
|
|
84
100
|
```ruby
|
85
101
|
# app/presenters/line_presenter.rb
|
86
102
|
context = ActionView::Base.new(
|
87
|
-
|
88
|
-
|
89
|
-
|
103
|
+
ActionController::Base.view_paths,
|
104
|
+
{},
|
105
|
+
ActionController::Base.new,
|
90
106
|
)
|
91
107
|
|
92
108
|
builder = Line::MessageBuilder::Builder.with(context) do
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
109
|
+
text "Anything you want?" do
|
110
|
+
quick_reply do
|
111
|
+
message "Yes", label: "Yes", image_url: image_url("yes.png")
|
112
|
+
message "No", label: "No", image_url: image_url("no.png")
|
98
113
|
end
|
114
|
+
end
|
99
115
|
end
|
100
116
|
```
|
101
117
|
|
@@ -163,6 +179,7 @@ end
|
|
163
179
|
| `have_line_flex_image` | Match a flex message with image |
|
164
180
|
| `have_line_flex_button` | Match a flex message with button |
|
165
181
|
| `have_line_flex_box` | Match a flex message with box |
|
182
|
+
| `have_line_flex_separator` | Match a flex message with separator |
|
166
183
|
|
167
184
|
|
168
185
|
Add `line/message/rspec` to your `spec_helper.rb` or `rails_helper.rb`:
|
@@ -175,7 +192,7 @@ Include `Line::Message::RSpec::Matchers` in your RSpec configuration:
|
|
175
192
|
|
176
193
|
```ruby
|
177
194
|
RSpec.configure do |config|
|
178
|
-
|
195
|
+
config.include Line::Message::RSpec::Matchers
|
179
196
|
end
|
180
197
|
```
|
181
198
|
|
@@ -183,10 +200,10 @@ Then the matchers are available in your specs:
|
|
183
200
|
|
184
201
|
```ruby
|
185
202
|
let(:builder) do
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
203
|
+
Line::MessageBuilder::Builder.with do
|
204
|
+
text "Hello, world!"
|
205
|
+
text "Nice to meet you!"
|
206
|
+
end
|
190
207
|
end
|
191
208
|
|
192
209
|
subject { builder.build }
|
@@ -199,12 +216,13 @@ The matchers can work with webmock `a_request`:
|
|
199
216
|
|
200
217
|
```ruby
|
201
218
|
it "reply with message" do
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
219
|
+
expect(a_request(:post, "https://api.line.me/v2/bot/message/reply")
|
220
|
+
.with(
|
221
|
+
body: hash_including({
|
222
|
+
messages: have_line_text_message(/Hello, world!/),
|
223
|
+
})
|
224
|
+
)
|
225
|
+
).to have_been_made.once
|
208
226
|
end
|
209
227
|
```
|
210
228
|
|
@@ -263,8 +281,8 @@ end
|
|
263
281
|
| Video | ❌ |
|
264
282
|
| Icon | ❌ |
|
265
283
|
| Text | 🚧 |
|
266
|
-
| Span |
|
267
|
-
| Separator |
|
284
|
+
| Span | ✅ |
|
285
|
+
| Separator | ✅ |
|
268
286
|
| Filler | ❌ Deprecated |
|
269
287
|
|
270
288
|
## Development
|
@@ -3,22 +3,88 @@
|
|
3
3
|
module Line
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
|
+
# The `Actions` module serves as a namespace for action objects that can be
|
7
|
+
# associated with various LINE message components, such as buttons in
|
8
|
+
# quick replies or imagemaps. Each class within this module represents a
|
9
|
+
# specific type of action a user can perform.
|
6
10
|
module Actions
|
7
|
-
#
|
11
|
+
# Represents a "message action" for LINE messages.
|
12
|
+
#
|
13
|
+
# A message action sends a specified text message to the chat from the user
|
14
|
+
# when a button associated with this action is tapped. It's commonly used
|
15
|
+
# in quick replies or other interactive message components.
|
16
|
+
#
|
17
|
+
# @example Creating a message action for a quick reply button
|
18
|
+
# Line::Message::Builder.with do
|
19
|
+
# text "Select your favorite food:"
|
20
|
+
# quick_reply do
|
21
|
+
# # When this button is tapped, the user sends "Pizza"
|
22
|
+
# button action: :message, label: "Pizza", text: "Pizza"
|
23
|
+
# # When this button is tapped, the user sends "Sushi"
|
24
|
+
# button action: :message, label: "Sushi", text: "Sushi"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @see https://developers.line.biz/en/reference/messaging-api/#message-action
|
8
29
|
class Message < Line::Message::Builder::Base
|
30
|
+
# @!attribute [r] text
|
31
|
+
# @return [String] The text that is sent as a message from the user
|
32
|
+
# when the action is performed. This is a required attribute.
|
9
33
|
attr_reader :text
|
10
34
|
|
35
|
+
# Defines an optional `label` for the action.
|
36
|
+
# The label is recommended by LINE for accessibility purposes, but it's
|
37
|
+
# not displayed in all LINE versions. For some message types like buttons,
|
38
|
+
# the label of the button itself is used as the action's label.
|
39
|
+
#
|
40
|
+
# @!method label(value = nil)
|
41
|
+
# @param value [String, nil] The label text for the action.
|
42
|
+
# @return [String, nil] The current label text.
|
11
43
|
option :label, default: nil
|
12
44
|
|
45
|
+
# Initializes a new Message action.
|
46
|
+
#
|
47
|
+
# @param text [String] The text to be sent when the action is performed.
|
48
|
+
# This is a required parameter.
|
49
|
+
# @param context [Object, nil] An optional context object for resolving
|
50
|
+
# method calls within a block, if one is provided.
|
51
|
+
# @param options [Hash] A hash of options to set instance variables.
|
52
|
+
# Can include `:label`.
|
53
|
+
# @param block [Proc, nil] An optional block to be instance-eval'd.
|
54
|
+
# While available, it's not commonly used for simple actions like this.
|
55
|
+
# @raise [RequiredError] if `text` is nil. (This check is done in `to_h`
|
56
|
+
# but `text` is conceptually required on initialization).
|
13
57
|
def initialize(text, context: nil, **options, &)
|
14
58
|
@text = text
|
15
59
|
|
16
60
|
super(context: context, **options, &)
|
17
61
|
end
|
18
62
|
|
63
|
+
# Converts the Message action object to a hash suitable for the LINE
|
64
|
+
# Messaging API.
|
65
|
+
#
|
66
|
+
# @return [Hash] A hash representing the message action.
|
67
|
+
# Includes `:type`, `:label` (if set), and `:text`.
|
68
|
+
# @raise [RequiredError] if `text` is nil.
|
19
69
|
def to_h
|
20
70
|
raise RequiredError, "text is required" if text.nil?
|
21
71
|
|
72
|
+
return to_sdkv2 if context.sdkv2?
|
73
|
+
|
74
|
+
to_api
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def to_api
|
80
|
+
{
|
81
|
+
type: "message",
|
82
|
+
label: label,
|
83
|
+
text: text
|
84
|
+
}.compact
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_sdkv2
|
22
88
|
{
|
23
89
|
type: "message",
|
24
90
|
label: label,
|
@@ -4,22 +4,83 @@ module Line
|
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
6
|
module Actions
|
7
|
-
#
|
7
|
+
# Represents a "postback action" for LINE messages.
|
8
|
+
#
|
9
|
+
# A postback action sends a postback event to your bot's webhook when a
|
10
|
+
# button associated with this action is tapped. The event contains the
|
11
|
+
# specified `data` payload. Optionally, `displayText` can be provided,
|
12
|
+
# which will be shown in the chat as a message from the user.
|
13
|
+
#
|
14
|
+
# This action is useful for triggering specific backend logic or flows
|
15
|
+
# without necessarily displaying a message in the chat, or for displaying
|
16
|
+
# a different message than the data payload.
|
17
|
+
#
|
18
|
+
# @example Creating a postback action for a quick reply button
|
19
|
+
# Line::Message::Builder.with do
|
20
|
+
# text "What do you want to do?"
|
21
|
+
# quick_reply do
|
22
|
+
# button action: :postback,
|
23
|
+
# label: "Track Order",
|
24
|
+
# data: "action=track_order&order_id=123",
|
25
|
+
# display_text: "I want to track my order."
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @see https://developers.line.biz/en/reference/messaging-api/#postback-action
|
8
30
|
class Postback < Line::Message::Builder::Base
|
31
|
+
# @!attribute [r] data
|
32
|
+
# @return [String] The data payload to be sent in the postback event
|
33
|
+
# to the webhook. This is a required attribute. Max 300 characters.
|
9
34
|
attr_reader :data
|
10
35
|
|
36
|
+
# Defines an optional `label` for the action.
|
37
|
+
# The label is recommended by LINE for accessibility. For some message
|
38
|
+
# types (e.g., buttons), the button's label itself is used.
|
39
|
+
#
|
40
|
+
# @!method label(value = nil)
|
41
|
+
# @param value [String, nil] The label text for the action.
|
42
|
+
# @return [String, nil] The current label text.
|
11
43
|
option :label, default: nil
|
44
|
+
|
45
|
+
# Defines an optional `displayText` for the action.
|
46
|
+
# This is the text that will be displayed in the chat as a message from
|
47
|
+
# the user when the action is performed. If not set, no message is displayed.
|
48
|
+
#
|
49
|
+
# @!method display_text(value = nil)
|
50
|
+
# @param value [String, nil] The text to display in the chat. Max 300 characters.
|
51
|
+
# @return [String, nil] The current display text.
|
12
52
|
option :display_text, default: nil
|
13
53
|
|
54
|
+
# Initializes a new Postback action.
|
55
|
+
#
|
56
|
+
# @param data [String] The data to be sent in the postback event. This is required.
|
57
|
+
# @param context [Object, nil] An optional context object.
|
58
|
+
# @param options [Hash] Options for the action, including `:label` and `:display_text`.
|
59
|
+
# @param block [Proc, nil] An optional block for instance_eval.
|
60
|
+
# @raise [RequiredError] if `data` is nil. (This check is done in `to_h`
|
61
|
+
# but `data` is conceptually required on initialization).
|
14
62
|
def initialize(data, context: nil, **options, &)
|
15
63
|
@data = data
|
16
64
|
|
17
65
|
super(context: context, **options, &)
|
18
66
|
end
|
19
67
|
|
68
|
+
# Converts the Postback action object to a hash suitable for the LINE Messaging API.
|
69
|
+
#
|
70
|
+
# @return [Hash] A hash representing the postback action.
|
71
|
+
# Includes `:type`, `:label` (if set), `:data`, and `:displayText` (if set).
|
72
|
+
# @raise [RequiredError] if `data` is nil.
|
20
73
|
def to_h
|
21
74
|
raise RequiredError, "data is required" if data.nil?
|
22
75
|
|
76
|
+
return to_sdkv2 if context.sdkv2?
|
77
|
+
|
78
|
+
to_api
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def to_api
|
23
84
|
{
|
24
85
|
type: "postback",
|
25
86
|
label: label,
|
@@ -27,6 +88,15 @@ module Line
|
|
27
88
|
displayText: display_text
|
28
89
|
}.compact
|
29
90
|
end
|
91
|
+
|
92
|
+
def to_sdkv2
|
93
|
+
{
|
94
|
+
type: "postback",
|
95
|
+
label: label,
|
96
|
+
data: data,
|
97
|
+
display_text: display_text
|
98
|
+
}.compact
|
99
|
+
end
|
30
100
|
end
|
31
101
|
end
|
32
102
|
end
|
@@ -3,7 +3,24 @@
|
|
3
3
|
module Line
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
|
-
# The
|
6
|
+
# The `Line::Message::Builder::Actions` module serves as a central namespace
|
7
|
+
# for all action objects used within the LINE message builder DSL. Actions
|
8
|
+
# represent operations that can be triggered by users interacting with
|
9
|
+
# message components like buttons (in quick replies, templates, etc.) or
|
10
|
+
# imagemap areas.
|
11
|
+
#
|
12
|
+
# This module itself does not define specific action classes directly but
|
13
|
+
# acts as a container that loads them from individual files (e.g., `message.rb`,
|
14
|
+
# `postback.rb`). Each loaded file defines a class corresponding to a
|
15
|
+
# specific action type supported by the LINE Messaging API.
|
16
|
+
#
|
17
|
+
# By organizing actions under this namespace, the builder provides a clear
|
18
|
+
# and consistent way to create and manage different types of interactive
|
19
|
+
# elements in messages.
|
20
|
+
#
|
21
|
+
# @see Line::Message::Builder::Actions::Message
|
22
|
+
# @see Line::Message::Builder::Actions::Postback
|
23
|
+
# @see https://developers.line.biz/en/reference/messaging-api/#action-objects
|
7
24
|
module Actions
|
8
25
|
require_relative "actions/message"
|
9
26
|
require_relative "actions/postback"
|
@@ -3,21 +3,63 @@
|
|
3
3
|
module Line
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
|
-
# The
|
6
|
+
# The `Base` class serves as the foundation for all message builder classes
|
7
|
+
# within the `Line::Message::Builder` DSL. It provides core functionality
|
8
|
+
# for defining options, handling initialization, and delegating method calls
|
9
|
+
# to a context object.
|
10
|
+
#
|
11
|
+
# This class is not typically used directly but is inherited by specific
|
12
|
+
# message type builders (e.g., `Text`, `Flex`).
|
7
13
|
class Base
|
8
14
|
class << self
|
15
|
+
# @!visibility private
|
16
|
+
# @!parse extend ClassMethods
|
9
17
|
def inherited(subclass)
|
10
18
|
super
|
11
19
|
subclass.extend ClassMethods
|
12
20
|
end
|
13
21
|
end
|
14
22
|
|
15
|
-
#
|
23
|
+
# The `ClassMethods` module is automatically extended by any class that
|
24
|
+
# inherits from {Base}. It provides class-level methods for defining
|
25
|
+
# DSL options and configurations.
|
16
26
|
module ClassMethods
|
27
|
+
# Returns an array of option names that have been defined for this class
|
28
|
+
# using the {option} method.
|
29
|
+
#
|
30
|
+
# @return [Array<Symbol>] A list of defined option names.
|
31
|
+
# @!visibility private
|
17
32
|
def options
|
18
33
|
@options ||= []
|
19
34
|
end
|
20
35
|
|
36
|
+
# Defines a new option for the builder class.
|
37
|
+
# This method dynamically creates an instance method on the builder class
|
38
|
+
# with the given `name`. When this instance method is called:
|
39
|
+
# - Without arguments, it returns the current value of the option, or
|
40
|
+
# the `default` value if not set.
|
41
|
+
# - With an argument, it sets the value of the option. If a `validator`
|
42
|
+
# is provided, the value is validated before being set.
|
43
|
+
#
|
44
|
+
# @param name [Symbol] The name of the option to define. This will also
|
45
|
+
# be the name of the generated instance method.
|
46
|
+
# @param default [Object, nil] The default value for the option if not
|
47
|
+
# explicitly set.
|
48
|
+
# @param validator [#valid!?, nil] An optional validator object that must
|
49
|
+
# respond to `valid!(value)`. If the value is invalid, the validator
|
50
|
+
# should raise an error (typically a {ValidationError}).
|
51
|
+
# @return [void]
|
52
|
+
# @example
|
53
|
+
# class MyBuilder < Base
|
54
|
+
# option :color, default: "red"
|
55
|
+
# option :size, validator: SizeValidator.new
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# builder = MyBuilder.new
|
59
|
+
# puts builder.color # => "red"
|
60
|
+
# builder.color "blue"
|
61
|
+
# puts builder.color # => "blue"
|
62
|
+
# builder.size "large" # Assuming SizeValidator allows "large"
|
21
63
|
def option(name, default: nil, validator: nil)
|
22
64
|
options << name
|
23
65
|
|
@@ -34,8 +76,20 @@ module Line
|
|
34
76
|
|
35
77
|
attr_reader :context
|
36
78
|
|
79
|
+
# Initializes a new instance of a builder class.
|
80
|
+
#
|
81
|
+
# @param context [Object, nil] An optional external context object.
|
82
|
+
# Methods not defined in the builder will be delegated to this context
|
83
|
+
# if it responds to them. This allows for using helper methods or
|
84
|
+
# accessing data from the surrounding environment within the builder DSL.
|
85
|
+
# @param options [Hash] A hash of options to set on the builder instance.
|
86
|
+
# These options are typically defined using the {ClassMethods.option .option}
|
87
|
+
# method in the builder class.
|
88
|
+
# @param block [Proc, nil] An optional block that is instance-eval'd
|
89
|
+
# within the new builder instance. This is the primary way the DSL
|
90
|
+
# is used to define message content.
|
37
91
|
def initialize(context: nil, **options, &block)
|
38
|
-
@context =
|
92
|
+
@context = context
|
39
93
|
@quick_reply = nil
|
40
94
|
|
41
95
|
self.class.options.each do |option|
|
@@ -45,14 +99,54 @@ module Line
|
|
45
99
|
instance_eval(&block) if ::Kernel.block_given?
|
46
100
|
end
|
47
101
|
|
102
|
+
# Defines a quick reply for the message.
|
103
|
+
# A quick reply consists of a set of buttons that are displayed along
|
104
|
+
# with the message, allowing users to make quick responses.
|
105
|
+
#
|
106
|
+
# The provided block is executed in the context of a new {QuickReply}
|
107
|
+
# instance, where you can define the quick reply buttons.
|
108
|
+
#
|
109
|
+
# @yield [quick_reply] The block is yielded with a {QuickReply} instance.
|
110
|
+
# @return [QuickReply] The created {QuickReply} object.
|
111
|
+
# @example
|
112
|
+
# text_message do
|
113
|
+
# text "Please choose an option:"
|
114
|
+
# quick_reply do
|
115
|
+
# button action: :message, label: "Option A", text: "You chose A"
|
116
|
+
# button action: :camera, label: "Open Camera"
|
117
|
+
# end
|
118
|
+
# end
|
48
119
|
def quick_reply(&)
|
49
120
|
@quick_reply = QuickReply.new(context: context, &)
|
50
121
|
end
|
51
122
|
|
123
|
+
# Determines if the builder can respond to a given method, including
|
124
|
+
# checking if the context object can respond to it.
|
125
|
+
# This is part of Ruby's mechanism for `method_missing` and is used
|
126
|
+
# here to enable delegation to the `context` object.
|
127
|
+
#
|
128
|
+
# @param method_name [Symbol] The name of the method.
|
129
|
+
# @param include_private [Boolean] Whether to include private methods
|
130
|
+
# in the search.
|
131
|
+
# @return [Boolean] `true` if the builder or its context can respond to
|
132
|
+
# the method, `false` otherwise.
|
133
|
+
# @!visibility private
|
52
134
|
def respond_to_missing?(method_name, include_private = false)
|
53
135
|
context.respond_to?(method_name, include_private) || super
|
54
136
|
end
|
55
137
|
|
138
|
+
# Handles calls to undefined methods by attempting to delegate them to the
|
139
|
+
# `context` object. If the `context` object responds to the method,
|
140
|
+
# it is called. Otherwise, it behaves like the standard `method_missing`.
|
141
|
+
# This allows the DSL to feel more integrated with the surrounding code
|
142
|
+
# by making methods from the `context` directly available within the
|
143
|
+
# builder block.
|
144
|
+
#
|
145
|
+
# @param method_name [Symbol] The name of the missing method.
|
146
|
+
# @param ... [Object] Arguments passed to the method.
|
147
|
+
# @raise [NoMethodError] If neither the builder nor the context can
|
148
|
+
# handle the method call.
|
149
|
+
# @!visibility private
|
56
150
|
def method_missing(method_name, ...)
|
57
151
|
if context.respond_to?(method_name)
|
58
152
|
context.public_send(method_name, ...)
|
@@ -60,6 +154,22 @@ module Line
|
|
60
154
|
super
|
61
155
|
end
|
62
156
|
end
|
157
|
+
|
158
|
+
def to_h
|
159
|
+
return to_sdkv2 if sdkv2?
|
160
|
+
|
161
|
+
to_api
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def to_api
|
167
|
+
raise NotImplementedError, "#{self.class} must implement #to_api"
|
168
|
+
end
|
169
|
+
|
170
|
+
def to_sdkv2
|
171
|
+
raise NotImplementedError, "#{self.class} must implement #to_sdkv2"
|
172
|
+
end
|
63
173
|
end
|
64
174
|
end
|
65
175
|
end
|