使用line-bot-sdk-java构建聊天机器人
总结
「LINE Messaging API」在9月29日发布。这个新API与之前的「LINE BOT API Trial Account」相比,更加简洁。为了配合这个API的发布,官方已经提供了各种语言的SDK。我们使用Java版本来创建一个简单的聊天机器人。
我想做的事情 (Wǒ zuò de
当收到文本消息时,会根据消息类型在Twitter上搜索声优村川梨衣的图片并回复。
这里是GitHub
环境
-
- jdk1.8
-
- Spring Boot
- Heroku
准备好

由于Heroku账户设置并不是主要讨论内容,故将其省略不提。
源代码
本次的聊天机器人将使用Spring Boot进行开发。SDK中有专门用于Spring Boot的项目,使用起来非常方便。
build.gradle -> 构建.gradle
dependencies {
compile('org.springframework.boot:spring-boot-starter-social-twitter')
runtime('org.springframework.boot:spring-boot-devtools')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
// LINE BOT SDK
compile group: 'com.linecorp.bot', name: 'line-bot-spring-boot', version: '1.3.0'
}
虽然MVNRepository只有1.1.0版本,但截至2016年11月16日,已经有1.3.0版本了,所以我们选择使用那个版本。
由于使用了Twitter搜索API,我们还将Spring Social Twitter作为依赖关系添加进去。
终结点 jié
import java.io.IOException;
import com.linecorp.bot.model.event.Event;
import com.linecorp.bot.model.event.MessageEvent;
import com.linecorp.bot.model.event.message.TextMessageContent;
import com.linecorp.bot.model.response.BotApiResponse;
import com.linecorp.bot.spring.boot.annotation.EventMapping;
import com.linecorp.bot.spring.boot.annotation.LineMessageHandler;
@LineMessageHandler
public class MessageHandler {
private final ReplyMessageHandler replyMessageHandler;
public MessageHandler(ReplyMessageHandler replyMessageHandler) {
super();
this.replyMessageHandler = replyMessageHandler;
}
@EventMapping
public void handleTextMessageEvent(MessageEvent<TextMessageContent> event) throws IOException {
System.out.println("event: " + event);
BotApiResponse response = replyMessageHandler.reply(event);
System.out.println("Sent messages: " + response);
}
@EventMapping
public void defaultMessageEvent(Event event) {
System.out.println("event: " + event);
}
}
这是API的终端点,不是使用Spring MVC的@Controller + @RequestMapping来定义,而是使用@LineMessageHandler + @EventMapping。
将@LineMessageHandler应用于类,并为每个方法添加@EventMapping。这样,它会根据发送的消息类型自动调用匹配相应参数类型的方法。
例如,在上述代码中,如果发送了文本类型的消息,则会调用handleTextMessageEvent方法,如果是其他类型,则会调用defaultMessageEvent方法。
另外,URL为/callback。
发送回复
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.stereotype.Service;
import com.linecorp.bot.client.LineMessagingService;
import com.linecorp.bot.model.ReplyMessage;
import com.linecorp.bot.model.event.MessageEvent;
import com.linecorp.bot.model.event.message.TextMessageContent;
import com.linecorp.bot.model.message.ImageMessage;
import com.linecorp.bot.model.message.Message;
import com.linecorp.bot.model.message.TextMessage;
import com.linecorp.bot.model.response.BotApiResponse;
import github.rshindo.rlb.util.TwitterApiUtils;
@Service
public class ReplyMessageHandler {
private static final String RIETION = "りえしょん";
private static final String MURAKAWA_RIE = "村川梨衣";
private static final String ROBOT = "ロボ";
@Value("${rietionbot.twitter.robot}")
@NotNull
private String robotAccountId;
@Value("${rietionbot.twitter.riemagic}")
@NotNull
private String riemagicAccountId;
private final Twitter twitter;
private final LineMessagingService lineMessagingService;
public ReplyMessageHandler(Twitter twitter, LineMessagingService lineMessagingService) {
super();
this.twitter = twitter;
this.lineMessagingService = lineMessagingService;
}
public BotApiResponse reply(MessageEvent<TextMessageContent> event) throws IOException {
String receivedMessage = event.getMessage().getText();
String replyToken = event.getReplyToken();
List<Message> messages = null;
switch (receivedMessage) {
case RIETION:
messages = searchRietionImages();
break;
case MURAKAWA_RIE:
messages = searchRieMurakawaImages();
break;
case ROBOT:
messages = searchRobotTexts();
break;
default:
messages = searchRiemagicTexts();
break;
}
return lineMessagingService
.replyMessage(new ReplyMessage(replyToken, messages))
.execute()
.body();
}
protected List<Message> searchRietionImages() {
return searchImages(RIETION + TwitterApiUtils.IMAGE_FILTER);
}
protected List<Message> searchRieMurakawaImages() {
return searchImages(MURAKAWA_RIE + TwitterApiUtils.IMAGE_FILTER);
}
protected List<Message> searchImages(String searchKey) {
SearchResults results = twitter.searchOperations().search(
new SearchParameters(searchKey)
.count(10));
List<Tweet> tweets = results.getTweets();
List<Message> messages = tweets.stream()
.flatMap(tweet -> TwitterApiUtils.getImageUrlList(tweet).stream())
.limit(3)
.map(url -> new ImageMessage(url, url))
.collect(Collectors.toList());
if(messages.isEmpty()) {
return Arrays.asList(new TextMessage("画像が見つかりませんでした"));
} else {
return messages;
}
}
protected List<Message> searchRobotTexts() {
return searchTexts(robotAccountId);
}
protected List<Message> searchRiemagicTexts() {
return searchTexts(riemagicAccountId);
}
protected List<Message> searchTexts(String searchKey) {
SearchResults results = twitter.searchOperations().search(
new SearchParameters(searchKey)
.count(1));
List<Message> messages = results.getTweets().stream()
.map(tweet -> new TextMessage(tweet.getText()))
.collect(Collectors.toList());
if(messages.isEmpty()) {
return Arrays.asList(new TextMessage("ツイートが見つかりません"));
} else {
return messages;
}
}
}
对于消息的回复,不是使用Spring MVC功能,而是使用SDK的功能。
只需使用LineMessagingService自动装配,按照上述方法调用,就完成了回复的实现。很简单!
但是有一个要点,就是必须将接收到的消息中包含的ReplyToken放入回复中。我相信你不会迷失方向的。。
構築和部署
在这里进入LINE的管理界面。


首先,请在Webhook URL中设置终端点。
然后,确认Channel Secret和Channel Access Token。尽管我们在这次实现中没有自己实施,但是LINE发送的消息是加密的,所以需要使用Secret和Token进行解密。
Secret和Token分别在“line.bot.channelToken”和“line.bot.channelSecret”中进行设置。在Spring Boot的属性设置中,有以下的一种方法,例如:
-
- propertiesファイル
-
- ymlファイル
-
- システムプロパティ
- 環境変数
这次我们在Heroku的系统属性中进行了设置。
执行
由于涉及肖像权问题,我们将不展示实际的LINE界面。
另外,在回复发送时可能出现“请将IP地址添加到白名单”之类的错误。
在这种情况下,需要从管理界面添加到服务器IP白名单中。
但是,对于我个人来说,我遇到了一种奇怪的现象:当我注册一次后,却无法正常工作,但如果将其删除后,就可以回复了…
总结
使用LINE BOT SDK,我们可以轻松实现聊天机器人。它具有许多有趣的应用场景。