Skip to content

Commit 0c43ce6

Browse files
committed
NO-ISSUE Add unified client
1 parent 53de7f6 commit 0c43ce6

19 files changed

Lines changed: 7284 additions & 72 deletions

File tree

.github/workflows/generate-code.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ jobs:
3333
distribution: 'temurin'
3434
java-version: 17
3535
architecture: x64
36+
- uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1.299.0
37+
with:
38+
ruby-version: '4.0'
39+
- run: bundle install
3640

3741
# Generate codes
3842
- name: Generate code

.rubocop.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ AllCops:
22
TargetRubyVersion: 2.4
33
Exclude:
44
- 'examples/**/*'
5+
- 'generator/target/**/*'
56
- 'lib/line/bot/v2/channel_access_token/**/*'
67
- 'lib/line/bot/v2/insight/**/*'
78
- 'lib/line/bot/v2/liff/**/*'
@@ -11,6 +12,8 @@ AllCops:
1112
- 'lib/line/bot/v2/module_attach/**/*'
1213
- 'lib/line/bot/v2/shop/**/*'
1314
- 'lib/line/bot/v2/webhook/**/*'
15+
- 'lib/line/bot/v2/client.generated.rb'
16+
- 'lib/line/bot/v2/client.factory.generated.rb'
1417
NewCops: disable
1518

1619
Gemspec/RequiredRubyVersion:

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Thus, you can't edit almost all code under `lib/line/bot/v2/<dir>.rb` and `sig/l
2727

2828
You need to edit the pebble template under [resources](generator/src/main/resources) instead.
2929

30-
After editing the templates, run `generate-code.py` to generate the code, and then commit all affected files.
30+
After editing the templates, run `generate-code.py` to generate the code (including the unified client), and then commit all affected files.
3131
If not, CI status will be red.
3232

3333
When you update code, be sure to check consistencies between `lib/**.rb` and `sig/**.rbs`.

README.md

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ You can code with type support in the corresponding IDE or editor.
5454

5555
### Basic Usage
5656

57+
The unified `Line::Bot::V2::Client` wraps all individual API clients into a single object.
58+
You no longer need to create separate clients for MessagingApi, Insight, Liff, etc.
59+
5760
```ruby
5861
# app.rb
5962
require 'sinatra'
@@ -62,13 +65,7 @@ require 'line-bot-api'
6265
set :environment, :production
6366

6467
def client
65-
@client ||= Line::Bot::V2::MessagingApi::ApiClient.new(
66-
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN")
67-
)
68-
end
69-
70-
def blob_client
71-
@blob_client ||= Line::Bot::V2::MessagingApi::ApiBlobClient.new(
68+
@client ||= Line::Bot::V2::Client.new(
7269
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN")
7370
)
7471
end
@@ -109,9 +106,9 @@ post '/callback' do
109106
)
110107
client.reply_message(reply_message_request: request)
111108
end
112-
109+
113110
when Line::Bot::V2::Webhook::ImageMessageContent, Line::Bot::V2::Webhook::VideoMessageContent
114-
response = blob_client.get_message_content(message_id: event.message.message_id)
111+
response = client.get_message_content(message_id: event.message.message_id)
115112
tf = Tempfile.open("content")
116113
tf.write(response)
117114
end
@@ -123,6 +120,9 @@ post '/callback' do
123120
end
124121
```
125122

123+
> **Note:** You can still use the individual clients (e.g. `Line::Bot::V2::MessagingApi::ApiClient`) if you prefer.
124+
> For channel access token operations, use `Line::Bot::V2::ChannelAccessToken::ApiClient` directly.
125+
126126
### Main classes
127127
You may use this classes to use LINE Messaging API features.
128128

@@ -132,6 +132,26 @@ You may use this classes to use LINE Messaging API features.
132132

133133
### Clients
134134

135+
#### Unified Client (recommended)
136+
137+
`Line::Bot::V2::Client` wraps all API clients below (except ChannelAccessToken and ModuleAttach) into one object.
138+
You only need a single `channel_access_token` to call any API.
139+
140+
```ruby
141+
client = Line::Bot::V2::Client.new(
142+
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN")
143+
)
144+
145+
# MessagingApi, Insight, Liff, ManageAudience, Module, Shop — all available:
146+
client.push_message(push_message_request: request)
147+
client.get_number_of_followers(date: '20240101')
148+
client.get_message_content(message_id: '12345')
149+
```
150+
151+
#### Individual Clients
152+
153+
You can also use the individual clients directly if you need finer control.
154+
135155
| Class(YARD documentation) | API EndPoint | LINE Developers |
136156
|----------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
137157
| [Line::Bot::V2::ChannelAccessToken::ApiClient](https://line.github.io/line-bot-sdk-ruby/Line/Bot/V2/ChannelAccessToken/ApiClient.html) | https://api.line.me/** (related to oauth) | https://developers.line.biz/en/reference/messaging-api/#channel-access-token |
@@ -173,7 +193,7 @@ require 'json'
173193
require 'line-bot-api'
174194

175195
def client
176-
@client ||= Line::Bot::V2::MessagingApi::ApiClient.new(
196+
@client ||= Line::Bot::V2::Client.new(
177197
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
178198
)
179199
end
@@ -219,7 +239,7 @@ This is useful, for example, in migrating from v1 or building Flex Message.
219239
**But this is not recommended because you lose type checking by RBS.**
220240

221241
```ruby
222-
client = Line::Bot::V2::MessagingApi::ApiClient.new(
242+
client = Line::Bot::V2::Client.new(
223243
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
224244
)
225245

examples/v2/audience/app.rb

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
11
require 'line-bot-api'
22

33
def client
4-
@client ||= Line::Bot::V2::ManageAudience::ApiClient.new(
5-
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
6-
)
7-
end
8-
9-
def blob_client
10-
@blob_client ||= Line::Bot::V2::ManageAudience::ApiBlobClient.new(
11-
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
12-
)
13-
end
14-
15-
def api_client
16-
@api_client ||= Line::Bot::V2::MessagingApi::ApiClient.new(
4+
@client ||= Line::Bot::V2::Client.new(
175
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
186
)
197
end
@@ -71,7 +59,7 @@ def add_audience_by_ids(audience_group_id:)
7159
def add_audience_by_file(audience_group_id:)
7260
# TODO: replace with your user ID in audience.txt
7361
File.open('audience.txt', 'r') do |f|
74-
_body, status_code, _http_headers = blob_client.add_user_ids_to_audience_with_http_info(
62+
_body, status_code, _http_headers = client.add_user_ids_to_audience_with_http_info(
7563
audience_group_id: audience_group_id,
7664
file: f
7765
)
@@ -120,7 +108,7 @@ def push_narrowcast(audience_group_id:)
120108
audience_group_id: audience_group_id,
121109
)
122110
)
123-
_body, status_code, _http_headers = api_client.narrowcast_with_http_info(narrowcast_request: request)
111+
_body, status_code, _http_headers = client.narrowcast_with_http_info(narrowcast_request: request)
124112

125113
if status_code == 202
126114
puts '=== Push narrowcast successfully ==='

examples/v2/echobot/app.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
set :app_base_url, ENV.fetch('APP_BASE_URL')
66

77
def client
8-
@client ||= Line::Bot::V2::MessagingApi::ApiClient.new(
8+
@client ||= Line::Bot::V2::Client.new(
99
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN")
1010
)
1111
end

examples/v2/kitchensink/app.rb

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
QUICK_REPLY_ICON_URL = 'https://via.placeholder.com/64x64'
1111

1212
def client
13-
@client ||= Line::Bot::V2::MessagingApi::ApiClient.new(
13+
@client ||= Line::Bot::V2::Client.new(
1414
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
1515
http_options: {
1616
open_timeout: 5,
@@ -19,22 +19,6 @@ def client
1919
)
2020
end
2121

22-
def blob_client
23-
@blob_client ||= Line::Bot::V2::MessagingApi::ApiBlobClient.new(
24-
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
25-
http_options: {
26-
open_timeout: 5,
27-
read_timeout: 5
28-
}
29-
)
30-
end
31-
32-
def insight_client
33-
@insight_client ||= Line::Bot::V2::Insight::ApiClient.new(
34-
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
35-
)
36-
end
37-
3822
def parser
3923
@parser ||= Line::Bot::V2::WebhookParser.new(channel_secret: ENV.fetch("LINE_CHANNEL_SECRET"))
4024
end
@@ -136,7 +120,7 @@ def storeContent(message_id:, message_type:)
136120
max_retries = 10
137121

138122
max_retries.times do |i|
139-
body, status_code, _headers = blob_client.get_message_content_transcoding_by_message_id_with_http_info(
123+
body, status_code, _headers = client.get_message_content_transcoding_by_message_id_with_http_info(
140124
message_id: message_id
141125
)
142126

@@ -165,7 +149,7 @@ def storeContent(message_id:, message_type:)
165149
end
166150
end
167151

168-
content, _, headers = blob_client.get_message_content_with_http_info(message_id: message_id)
152+
content, _, headers = client.get_message_content_with_http_info(message_id: message_id)
169153
content_type = headers['content-type']
170154
ext = case content_type
171155
when 'image/jpeg' then 'jpg'
@@ -936,12 +920,12 @@ def rich_menu_request_b
936920

937921
create_rich_menu_a_response = client.create_rich_menu(rich_menu_request: rich_menu_request_a)
938922
logger.info "Create rich menu A: #{create_rich_menu_a_response.rich_menu_id}"
939-
a = blob_client.set_rich_menu_image(rich_menu_id: create_rich_menu_a_response.rich_menu_id, body: File.open('./richmenu/richmenu-a.png'))
923+
a = client.set_rich_menu_image(rich_menu_id: create_rich_menu_a_response.rich_menu_id, body: File.open('./richmenu/richmenu-a.png'))
940924
logger.info "Set rich menu image A: #{a}"
941925

942926
create_rich_menu_b_response = client.create_rich_menu(rich_menu_request: rich_menu_request_b)
943927
logger.info "Create rich menu B: #{create_rich_menu_b_response.rich_menu_id}"
944-
a = blob_client.set_rich_menu_image(rich_menu_id: create_rich_menu_b_response.rich_menu_id, body: File.open('./richmenu/richmenu-b.png'))
928+
a = client.set_rich_menu_image(rich_menu_id: create_rich_menu_b_response.rich_menu_id, body: File.open('./richmenu/richmenu-b.png'))
945929
logger.info "Set rich menu image B: #{a}"
946930

947931
client.set_default_rich_menu(rich_menu_id: create_rich_menu_a_response.rich_menu_id)
@@ -1057,7 +1041,7 @@ def rich_menu_request_b
10571041

10581042
when /\Astats\s+(?<request_id>.+)/
10591043
request_id = Regexp.last_match[:request_id]
1060-
stats = insight_client.get_message_event(request_id: request_id)
1044+
stats = client.get_message_event(request_id: request_id)
10611045

10621046
reply_text(event, "[STATS]\n#{stats}")
10631047

examples/v2/rich_menu/app.rb

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
require 'line-bot-api'
22

33
def client
4-
@client ||= Line::Bot::V2::MessagingApi::ApiClient.new(
5-
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
6-
)
7-
end
8-
9-
def blob_client
10-
@blob_client ||= Line::Bot::V2::MessagingApi::ApiBlobClient.new(
4+
@client ||= Line::Bot::V2::Client.new(
115
channel_access_token: ENV.fetch("LINE_CHANNEL_ACCESS_TOKEN"),
126
)
137
end
148

159
def main
1610
create_rich_menu_a_response = client.create_rich_menu(rich_menu_request: rich_menu_request_a)
1711
puts "created: #{create_rich_menu_a_response.rich_menu_id}"
18-
blob_client.set_rich_menu_image(rich_menu_id: create_rich_menu_a_response.rich_menu_id, body: File.open('./public/richmenu-a.png'))
12+
client.set_rich_menu_image(rich_menu_id: create_rich_menu_a_response.rich_menu_id, body: File.open('./public/richmenu-a.png'))
1913

2014
create_rich_menu_b_response = client.create_rich_menu(rich_menu_request: rich_menu_request_b)
2115
puts "created: #{create_rich_menu_b_response.rich_menu_id}"
22-
blob_client.set_rich_menu_image(rich_menu_id: create_rich_menu_b_response.rich_menu_id, body: File.open('./public/richmenu-b.png'))
16+
client.set_rich_menu_image(rich_menu_id: create_rich_menu_b_response.rich_menu_id, body: File.open('./public/richmenu-b.png'))
2317

2418
client.set_default_rich_menu(rich_menu_id: create_rich_menu_a_response.rich_menu_id)
2519

generate-code.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,18 @@ def generate_clients():
6262
run_command("rm -rf lib/line/bot/v2/webhook/api")
6363
run_command("rm -rf sig/line/bot/v2/webhook/api")
6464

65+
def generate_unified_client():
66+
"""Generate the unified client that wraps all individual API clients."""
67+
run_command('bundle exec ruby scripts/unified-client-generator/main.rb')
68+
6569
def main():
6670
"""Main function to package and generate clients."""
6771
os.chdir("generator")
6872
run_command('mvn package -DskipTests=true')
6973
os.chdir("..")
7074

7175
generate_clients()
76+
generate_unified_client()
7277

7378
if __name__ == "__main__":
7479
main()

lib/line/bot.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@
2525
require 'line/bot/v2/module_attach/core'
2626
require 'line/bot/v2/shop/core'
2727
require 'line/bot/v2/webhook/core'
28+
require 'line/bot/v2/client'

0 commit comments

Comments
 (0)