line-message-builder 0.7.0 → 0.8.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 +14 -0
- data/README.md +8 -0
- 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 +115 -3
- data/lib/line/message/builder/flex/actionable.rb +46 -1
- data/lib/line/message/builder/flex/box.rb +166 -14
- 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 +106 -20
- data/lib/line/message/builder/flex/partial.rb +89 -9
- data/lib/line/message/builder/flex/position.rb +122 -12
- data/lib/line/message/builder/flex/size.rb +65 -7
- data/lib/line/message/builder/flex/text.rb +131 -27
- data/lib/line/message/builder/flex.rb +54 -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.rb +14 -0
- data/llm.txt +356 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c49876bd79a2b1e98639a5e709a41736ebc11e8c7b5bf811ca478c52df762183
|
4
|
+
data.tar.gz: 65ceed1d2fbef231161bc7eb131269354875c39b202da96bb6fcd42edce4bf86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf2111f3470856dc021330c2fa73e3275842596d858e636d198f3dd8dcea7bddf9a60a252e4a80eb5e6297126b0ec3afeeaf143181ef565db06af9cf558c93c6
|
7
|
+
data.tar.gz: e98ec6e6696268c00f599de55e6b6acb09067c2370c6fc5357f8d1ee7f74b9b6e7d2c9b59a527ae5bc806ca6c685163311648b3a78641bd028d8ba6b71dc3bf1
|
data/.document
ADDED
@@ -1 +1 @@
|
|
1
|
-
{".":"0.
|
1
|
+
{".":"0.8.0"}
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.8.0](https://github.com/elct9620/line-message-builder/compare/v0.7.0...v0.8.0) (2025-05-24)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* Add GitHub Action for RDoc generation and deployment ([dbb0f79](https://github.com/elct9620/line-message-builder/commit/dbb0f797ae6143bb9f463c8e6c111a5fe1f0a53f))
|
9
|
+
* 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))
|
10
|
+
* add mode option to Line::Message::Builder for SDKv2 support ([f44f787](https://github.com/elct9620/line-message-builder/commit/f44f78758f5cac1dda6cf86f4c1945365c6c1018))
|
11
|
+
|
12
|
+
|
13
|
+
### Bug Fixes
|
14
|
+
|
15
|
+
* pass context to quick reply actions to resolve sdkv2 method error ([1bec753](https://github.com/elct9620/line-message-builder/commit/1bec7539421c0c11b10d2e906f9ee7f44a1c726f))
|
16
|
+
|
3
17
|
## [0.7.0](https://github.com/elct9620/line-message-builder/compare/v0.6.1...v0.7.0) (2025-05-21)
|
4
18
|
|
5
19
|
|
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 (WIP)
|
14
16
|
|
15
17
|
## Installation
|
16
18
|
|
@@ -31,6 +33,12 @@ 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
|
@@ -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 |root|
|
19
|
+
# root.text "Select your favorite food:"
|
20
|
+
# root.quick_reply do |qr|
|
21
|
+
# # When this button is tapped, the user sends "Pizza"
|
22
|
+
# qr.button action: :message, label: "Pizza", text: "Pizza"
|
23
|
+
# # When this button is tapped, the user sends "Sushi"
|
24
|
+
# qr.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 |root|
|
20
|
+
# root.text "What do you want to do?"
|
21
|
+
# root.quick_reply do |qr|
|
22
|
+
# qr.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
|
@@ -3,31 +3,151 @@
|
|
3
3
|
module Line
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
|
-
# The
|
7
|
-
|
6
|
+
# The `Container` class is the top-level entry point for constructing a batch
|
7
|
+
# of LINE messages using the builder DSL. It acts as a holder for one or
|
8
|
+
# more individual message objects (such as {Text} or {Flex} messages).
|
9
|
+
#
|
10
|
+
# When you use `Line::Message::Builder.with {}`, you are operating within
|
11
|
+
# the context of a `Container` instance. This container allows you to define
|
12
|
+
# multiple messages that can be sent together in a single API call to LINE,
|
13
|
+
# although the LINE API typically expects an array of message objects,
|
14
|
+
# which this container helps to build.
|
15
|
+
#
|
16
|
+
# Each message added to the container can also have its own quick reply.
|
17
|
+
#
|
18
|
+
# @example Building multiple messages
|
19
|
+
# message_payload = Line::Message::Builder.with do |root|
|
20
|
+
# root.text "Hello, this is the first message!"
|
21
|
+
# root.flex alt_text: "This is a Flex Message" do |flex_builder|
|
22
|
+
# flex_builder.bubble do |bubble|
|
23
|
+
# bubble.body do |body|
|
24
|
+
# body.text "This is a Flex Message body."
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
# end.build # => Returns an array of message hashes
|
29
|
+
#
|
30
|
+
# @see Base
|
31
|
+
# @see Text
|
32
|
+
# @see Flex::Builder
|
33
|
+
# @see QuickReply
|
34
|
+
class Container
|
35
|
+
# @!attribute [r] context
|
36
|
+
# @return [Context] The context object, which can hold external data or
|
37
|
+
# helper methods accessible within the builder blocks.
|
8
38
|
attr_reader :context
|
9
39
|
|
10
|
-
|
11
|
-
|
40
|
+
# Initializes a new message container.
|
41
|
+
# This is typically not called directly but through `Line::Message::Builder.with`.
|
42
|
+
# The provided block is instance-eval'd, allowing DSL methods like
|
43
|
+
# {#text} and {#flex} to be called directly on the container instance.
|
44
|
+
#
|
45
|
+
# @param context [Object, nil] An optional context object that can be used
|
46
|
+
# to share data or helper methods within the builder block. It's wrapped
|
47
|
+
# in a {Context} object.
|
48
|
+
# @param mode [Symbol] The mode to use for building messages. Can be either
|
49
|
+
# `:api` (default) for direct LINE Messaging API format or `:sdkv2` for
|
50
|
+
# LINE Bot SDK v2 compatible format.
|
51
|
+
# @param block [Proc] A block containing DSL calls to define messages
|
52
|
+
# (e.g., `text "Hello"`, `flex { ... }`).
|
53
|
+
def initialize(context: nil, mode: :api, &block)
|
54
|
+
@messages = [] # Initializes an empty array to store message objects
|
55
|
+
@context = Context.new(context, mode:)
|
12
56
|
|
13
|
-
|
57
|
+
instance_eval(&block) if ::Kernel.block_given?
|
14
58
|
end
|
15
59
|
|
60
|
+
# Creates a new {Text} message and adds it to this container.
|
61
|
+
#
|
62
|
+
# @param text [String] The text content of the message.
|
63
|
+
# @param options [Hash] Additional options for the text message,
|
64
|
+
# such as `:quick_reply`. See {Text#initialize}.
|
65
|
+
# @param block [Proc, nil] An optional block that will be instance-eval'd
|
66
|
+
# in the context of the new {Text} message instance. This can be used
|
67
|
+
# to add a quick reply to the text message.
|
68
|
+
# @return [Text] The newly created {Text} message object.
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# root.text "Hello, world!" do
|
72
|
+
# quick_reply do
|
73
|
+
# button action: :message, label: "Hi!", text: "Hi!"
|
74
|
+
# end
|
75
|
+
# end
|
16
76
|
def text(text, **options, &)
|
17
77
|
@messages << Text.new(text, context: context, **options, &)
|
18
78
|
end
|
19
79
|
|
80
|
+
# Creates a new {Flex::Builder} for constructing a Flex Message and adds it
|
81
|
+
# to this container. The block is mandatory and is used to define the
|
82
|
+
# content of the Flex Message using the Flex Message DSL.
|
83
|
+
#
|
84
|
+
# @param options [Hash] Options for the Flex Message, primarily `:alt_text`.
|
85
|
+
# See {Flex::Builder#initialize}. It's important to provide `alt_text`.
|
86
|
+
# @param block [Proc] A block that will be instance-eval'd in the context
|
87
|
+
# of the new {Flex::Builder} instance. This block is used to define the
|
88
|
+
# structure and content of the Flex Message (e.g., bubbles, carousels).
|
89
|
+
# @return [Flex::Builder] The newly created {Flex::Builder} object.
|
90
|
+
# @raise [ArgumentError] if `alt_text` is not provided in options (validation
|
91
|
+
# is typically within Flex::Builder).
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# root.flex alt_text: "Important information" do |fb|
|
95
|
+
# fb.bubble do |bubble|
|
96
|
+
# bubble.header { |h| h.text "Header" }
|
97
|
+
# bubble.body { |b| b.text "Body" }
|
98
|
+
# end
|
99
|
+
# end
|
20
100
|
def flex(**options, &)
|
21
101
|
@messages << Flex::Builder.new(context: context, **options, &)
|
22
102
|
end
|
23
103
|
|
104
|
+
# Converts all messages held by this container into their hash representations.
|
105
|
+
# This method iterates over each message object (e.g., {Text}, {Flex::Builder})
|
106
|
+
# stored in the container and calls its `to_h` method. The result is an
|
107
|
+
# array of hashes, where each hash represents a single LINE message object
|
108
|
+
# ready for JSON serialization and sending to the LINE Messaging API.
|
109
|
+
#
|
110
|
+
# @return [Array<Hash>] An array of message objects, each represented as a hash.
|
111
|
+
# This is the format expected by the LINE API for the `messages` field
|
112
|
+
# in a request body.
|
24
113
|
def build
|
25
114
|
@messages.map(&:to_h)
|
26
115
|
end
|
27
116
|
|
117
|
+
# Converts the array of message hashes (obtained from {#build}) into a
|
118
|
+
# JSON string. This is a convenience method for serializing the messages
|
119
|
+
# payload.
|
120
|
+
#
|
121
|
+
# @param args [Object] Optional arguments that are passed along to `to_json`
|
122
|
+
# method of the underlying array.
|
123
|
+
# @return [String] A JSON string representing the array of message objects.
|
28
124
|
def to_json(*args)
|
29
125
|
build.to_json(*args)
|
30
126
|
end
|
127
|
+
|
128
|
+
# Checks if a method is defined in the context object.
|
129
|
+
# This is part of Ruby's method_missing mechanism.
|
130
|
+
#
|
131
|
+
# @param method_name [Symbol] The name of the method being checked
|
132
|
+
# @param include_private [Boolean] Whether to include private methods
|
133
|
+
# @return [Boolean] True if the method exists in the context, false otherwise
|
134
|
+
def respond_to_missing?(method_name, include_private = false)
|
135
|
+
context.respond_to?(method_name, include_private) || super
|
136
|
+
end
|
137
|
+
|
138
|
+
# Delegates method calls to the context object if they exist there.
|
139
|
+
# This allows helper methods defined in the context to be called directly
|
140
|
+
# from within the builder DSL.
|
141
|
+
#
|
142
|
+
# @param method_name [Symbol] The name of the method being called
|
143
|
+
# @param args [Array] The arguments passed to the method
|
144
|
+
# @return [Object] The result of calling the method on the context
|
145
|
+
# @raise [NoMethodError] If the method doesn't exist in the context
|
146
|
+
def method_missing(method_name, ...)
|
147
|
+
return context.send(method_name, ...) if context.respond_to?(method_name)
|
148
|
+
|
149
|
+
super
|
150
|
+
end
|
31
151
|
end
|
32
152
|
end
|
33
153
|
end
|