Skip to content

Commit 66a89ad

Browse files
authored
Sample code for manage audience (#463)
1 parent 7000727 commit 66a89ad

38 files changed

+1878
-2
lines changed

line-bot-model/src/test/java/com/linecorp/bot/model/message/MessageJsonReconstructionTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,9 @@ public void narrowcast() {
239239
GenderDemographicFilter
240240
.builder()
241241
.oneOf(Collections.singletonList(Gender.MALE))
242-
.build()
243-
).build());
242+
.build())
243+
.build()
244+
);
244245
test(narrowcast);
245246

246247
test(AgeDemographicFilter.builder()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2020 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
apply plugin: 'org.springframework.boot'
18+
19+
dependencies {
20+
implementation project(':line-bot-spring-boot')
21+
22+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
23+
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
24+
implementation 'org.springframework.boot:spring-boot-starter-web'
25+
implementation 'com.squareup.okhttp3:okhttp'
26+
compileOnly 'org.projectlombok:lombok'
27+
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
28+
annotationProcessor 'org.projectlombok:lombok'
29+
testImplementation "org.springframework.boot:spring-boot-starter-test"
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2020 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*
16+
*/
17+
18+
package com.linecorp.bot.messagingapidemoapp;
19+
20+
import org.springframework.boot.SpringApplication;
21+
import org.springframework.boot.autoconfigure.SpringBootApplication;
22+
23+
@SpringBootApplication
24+
public class SampleManageAudienceApplication {
25+
26+
public static void main(String[] args) {
27+
SpringApplication.run(SampleManageAudienceApplication.class, args);
28+
}
29+
}
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* Copyright 2020 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*
16+
*/
17+
18+
package com.linecorp.bot.messagingapidemoapp.configuration;
19+
20+
import java.io.IOException;
21+
import java.nio.charset.Charset;
22+
import java.nio.charset.StandardCharsets;
23+
import java.util.ArrayList;
24+
import java.util.Collections;
25+
import java.util.List;
26+
import java.util.stream.Collectors;
27+
28+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
29+
import org.springframework.context.annotation.Bean;
30+
import org.springframework.context.annotation.Configuration;
31+
32+
import com.linecorp.bot.client.ChannelTokenSupplier;
33+
import com.linecorp.bot.client.LineMessagingClient;
34+
import com.linecorp.bot.spring.boot.LineBotProperties;
35+
36+
import lombok.AllArgsConstructor;
37+
import lombok.Builder;
38+
import lombok.Getter;
39+
import lombok.Value;
40+
import okhttp3.Headers;
41+
import okhttp3.Interceptor;
42+
import okhttp3.MediaType;
43+
import okhttp3.Request;
44+
import okhttp3.RequestBody;
45+
import okhttp3.Response;
46+
import okhttp3.ResponseBody;
47+
import okio.Buffer;
48+
import okio.BufferedSource;
49+
50+
@Configuration(proxyBeanMethods = false)
51+
@EnableConfigurationProperties(LineBotProperties.class)
52+
@AllArgsConstructor
53+
public class LineBotConfiguration {
54+
private LineBotProperties lineBotProperties;
55+
56+
@Bean
57+
public MyInterceptor myInterceptor() {
58+
return new MyInterceptor();
59+
}
60+
61+
@Bean
62+
public LineMessagingClient lineMessagingClient(ChannelTokenSupplier channelTokenSupplier,
63+
MyInterceptor myInterceptor) {
64+
return LineMessagingClient
65+
.builder(channelTokenSupplier)
66+
.apiEndPoint(lineBotProperties.getApiEndPoint())
67+
.blobEndPoint(lineBotProperties.getBlobEndPoint())
68+
.connectTimeout(lineBotProperties.getConnectTimeout())
69+
.readTimeout(lineBotProperties.getReadTimeout())
70+
.writeTimeout(lineBotProperties.getWriteTimeout())
71+
.additionalInterceptors(Collections.singletonList(myInterceptor))
72+
.build();
73+
}
74+
75+
public static class MyInterceptor implements Interceptor {
76+
private List<ApiCallLog> logs = new ArrayList<>();
77+
78+
@Override
79+
public Response intercept(Chain chain) throws IOException {
80+
Request request = chain.request();
81+
ApiCallRequest apiCallRequest = ApiCallRequest.create(request);
82+
Response response = chain.proceed(request);
83+
ApiCallResponse apiCallResponse = ApiCallResponse.create(response);
84+
ApiCallLog apiCallLog = new ApiCallLog(apiCallRequest, apiCallResponse);
85+
logs.add(apiCallLog);
86+
if (logs.size() > 40) {
87+
logs.remove(0);
88+
}
89+
return response;
90+
}
91+
92+
public List<ApiCallLog> getLogs() {
93+
return Collections.unmodifiableList(logs);
94+
}
95+
}
96+
97+
@Value
98+
public static class ApiCallLog {
99+
ApiCallRequest request;
100+
ApiCallResponse response;
101+
}
102+
103+
@Builder
104+
@Getter
105+
public static class ApiCallRequest {
106+
public static ApiCallRequest create(Request request) throws IOException {
107+
return ApiCallRequest.builder()
108+
.method(request.method())
109+
.url(request.url().toString())
110+
.headers(buildHeaders(request.headers()))
111+
.body(buildBody(request.body()))
112+
.build();
113+
}
114+
115+
private static String buildBody(RequestBody body) throws IOException {
116+
if (body == null) {
117+
return "<EMPTY>";
118+
}
119+
if (body.isDuplex()) {
120+
return "<DUPLEX>";
121+
}
122+
if (body.isOneShot()) {
123+
return "<ONESHOT>";
124+
}
125+
boolean result = false;
126+
MediaType mediaType = body.contentType();
127+
if (mediaType != null) {
128+
String type = mediaType.type();
129+
result = "text".equals(type) || "application".equals(type);
130+
}
131+
if (result) {
132+
Buffer buffer = new Buffer();
133+
body.writeTo(buffer);
134+
return buffer.readString(StandardCharsets.UTF_8);
135+
} else {
136+
return "<BINARY: " + body.contentType() + ">";
137+
}
138+
}
139+
140+
String method;
141+
String url;
142+
List<HeaderEntry> headers;
143+
String body;
144+
}
145+
146+
@Value
147+
public static class HeaderEntry {
148+
String name;
149+
String value;
150+
}
151+
152+
private static List<HeaderEntry> buildHeaders(Headers headers) {
153+
return headers.names()
154+
.stream()
155+
.flatMap(name -> headers.values(name)
156+
.stream()
157+
.map(value -> new HeaderEntry(name, value)))
158+
.collect(Collectors.toList());
159+
}
160+
161+
@Builder
162+
@Getter
163+
public static class ApiCallResponse {
164+
public static ApiCallResponse create(Response response) throws IOException {
165+
return ApiCallResponse.builder()
166+
.code(response.code())
167+
.message(response.message())
168+
.headers(buildHeaders(response.headers()))
169+
.body(buildBody(response.body()))
170+
.build();
171+
}
172+
173+
int code;
174+
String message;
175+
List<HeaderEntry> headers;
176+
String body;
177+
}
178+
179+
private static String buildBody(ResponseBody body) throws IOException {
180+
if (body == null) {
181+
return "<EMPTY>";
182+
}
183+
184+
MediaType contentType = body.contentType();
185+
if (contentType == null) {
186+
return "<BINARY>";
187+
}
188+
String type = contentType.type();
189+
Charset charset = contentType.charset();
190+
if (("text".equals(type) || "application".equals(type))) {
191+
if (charset == null) {
192+
if ("application".equals(type)) {
193+
charset = StandardCharsets.UTF_8;
194+
} else {
195+
return "<BINARY: " + contentType + ">";
196+
}
197+
}
198+
BufferedSource source = body.source();
199+
source.request(Long.MAX_VALUE); // Buffer the entire body.
200+
Buffer buffer = source.getBuffer();
201+
return buffer.clone().readString(charset);
202+
} else {
203+
return "<BINARY: " + body.contentType() + ">";
204+
}
205+
}
206+
}

0 commit comments

Comments
 (0)