From ec8eb996c264e113376d79c67c47e987848f860f Mon Sep 17 00:00:00 2001 From: Tomachi <8929706+book000@users.noreply.github.com> Date: Wed, 27 Jul 2022 00:43:55 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20ChatBot=E5=AE=9F=E8=A3=85=20(#886)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: ChatBot実装 * fix: 5文字未満の通常会話の場合はAPIに投げない * fix: 通信含めて非同期に変更 --- src/main/java/com/jaoafa/mymaid4/Main.java | 8 ++ .../jaoafa/mymaid4/command/Cmd_ChatBot.java | 70 +++++++++++++++ .../jaoafa/mymaid4/event/Event_ChatBot.java | 59 ++++++++++++ .../mymaid4/event/Event_WhereAreYou.java | 77 ---------------- .../com/jaoafa/mymaid4/lib/MeboChatBot.java | 89 +++++++++++++++++++ .../com/jaoafa/mymaid4/lib/MyMaidConfig.java | 22 +++++ 6 files changed, 248 insertions(+), 77 deletions(-) create mode 100644 src/main/java/com/jaoafa/mymaid4/command/Cmd_ChatBot.java create mode 100644 src/main/java/com/jaoafa/mymaid4/event/Event_ChatBot.java delete mode 100644 src/main/java/com/jaoafa/mymaid4/event/Event_WhereAreYou.java create mode 100644 src/main/java/com/jaoafa/mymaid4/lib/MeboChatBot.java diff --git a/src/main/java/com/jaoafa/mymaid4/Main.java b/src/main/java/com/jaoafa/mymaid4/Main.java index 4c7986bfe..aafd4a27a 100644 --- a/src/main/java/com/jaoafa/mymaid4/Main.java +++ b/src/main/java/com/jaoafa/mymaid4/Main.java @@ -73,6 +73,7 @@ public final class Main extends JavaPlugin { private static MyMaidConfig config = null; private static Rollbar rollbar = null; private MinecraftHelp minecraftHelp; + private static MeboChatBot meboChatBot = null; @Override public void onEnable() { @@ -105,6 +106,10 @@ public void onEnable() { MyMaidData.setBlacklist(new Blacklist()); initCreativeInventoryItems(); + + if (config.getMeboApiKey() != null && config.getMeboAgentId() != null) { + meboChatBot = new MeboChatBot(config.getMeboApiKey(), config.getMeboAgentId()); + } } @Override @@ -511,4 +516,7 @@ public static Rollbar getRollbar() { return rollbar; } + public static MeboChatBot getMeboChatBot() { + return meboChatBot; + } } diff --git a/src/main/java/com/jaoafa/mymaid4/command/Cmd_ChatBot.java b/src/main/java/com/jaoafa/mymaid4/command/Cmd_ChatBot.java new file mode 100644 index 000000000..6ba07a939 --- /dev/null +++ b/src/main/java/com/jaoafa/mymaid4/command/Cmd_ChatBot.java @@ -0,0 +1,70 @@ +/* + * jaoLicense + * + * Copyright (c) 2022 jao Minecraft Server + * + * The following license applies to this project: jaoLicense + * + * Japanese: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE.md + * English: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE-en.md + */ + +package com.jaoafa.mymaid4.command; + +import cloud.commandframework.Command; +import cloud.commandframework.arguments.standard.StringArgument; +import cloud.commandframework.context.CommandContext; +import cloud.commandframework.meta.CommandMeta; +import com.jaoafa.mymaid4.Main; +import com.jaoafa.mymaid4.lib.CommandPremise; +import com.jaoafa.mymaid4.lib.MeboChatBot; +import com.jaoafa.mymaid4.lib.MyMaidCommand; +import com.jaoafa.mymaid4.lib.MyMaidLibrary; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; + +public class Cmd_ChatBot extends MyMaidLibrary implements CommandPremise { + @Override + public MyMaidCommand.Detail details() { + return new MyMaidCommand.Detail( + "chatbot", + List.of("q", "question", "質問", "しつもん"), + "よくある質問への応対をします。" + ); + } + + @Override + public MyMaidCommand.Cmd register(Command.Builder builder) { + return new MyMaidCommand.Cmd( + builder + .meta(CommandMeta.DESCRIPTION, "よくある質問への応対をします。") + .argument(StringArgument.greedy("text")) + .handler(this::question) + .build() + ); + } + + void question(CommandContext context) { + Player player = (Player) context.getSender(); + String text = context.get("text"); + + if (Main.getMeboChatBot() == null) { + SendMessage(player, details(), "チャットに必要な情報が定義されていません。"); + return; + } + + MeboChatBot chatBot = Main.getMeboChatBot(); + MeboChatBot.MeboResponse response = chatBot.chat(player, text); + if (response == null) { + SendMessage(player, details(), "チャットに必要な情報が定義されていません。"); + return; + } + if (!response.status()) { + SendMessage(player, details(), "なんかうまくいきませんでした。"); + return; + } + SendMessage(player, details(), response.message()); + } +} diff --git a/src/main/java/com/jaoafa/mymaid4/event/Event_ChatBot.java b/src/main/java/com/jaoafa/mymaid4/event/Event_ChatBot.java new file mode 100644 index 000000000..215318c34 --- /dev/null +++ b/src/main/java/com/jaoafa/mymaid4/event/Event_ChatBot.java @@ -0,0 +1,59 @@ +/* + * jaoLicense + * + * Copyright (c) 2022 jao Minecraft Server + * + * The following license applies to this project: jaoLicense + * + * Japanese: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE.md + * English: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE-en.md + */ + +package com.jaoafa.mymaid4.event; + +import com.jaoafa.mymaid4.Main; +import com.jaoafa.mymaid4.lib.EventPremise; +import com.jaoafa.mymaid4.lib.MeboChatBot; +import com.jaoafa.mymaid4.lib.MyMaidLibrary; +import io.papermc.paper.event.player.AsyncChatEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitRunnable; + +public class Event_ChatBot extends MyMaidLibrary implements Listener, EventPremise { + @Override + public String description() { + return "ChatBotに関する処理を行います。"; + } + + @EventHandler + public void onAsyncPlayerChatEvent(AsyncChatEvent event) { + Player player = event.getPlayer(); + String content = PlainTextComponentSerializer.plainText().serialize(event.message()); + + if (content.length() < 5) { + return; + } + + new BukkitRunnable() { + public void run() { + MeboChatBot chatBot = Main.getMeboChatBot(); + MeboChatBot.MeboResponse response = chatBot.chat(player, content); + if (response == null) { + return; + } + if (!response.status()) { + return; + } + if (response.score() < 85) { + return; + } + + MyMaidLibrary.chatFake(NamedTextColor.GOLD, "jaotan", response.message(), true); + } + }.runTaskLaterAsynchronously(Main.getMain(), 10L); + } +} \ No newline at end of file diff --git a/src/main/java/com/jaoafa/mymaid4/event/Event_WhereAreYou.java b/src/main/java/com/jaoafa/mymaid4/event/Event_WhereAreYou.java deleted file mode 100644 index 1083acdb1..000000000 --- a/src/main/java/com/jaoafa/mymaid4/event/Event_WhereAreYou.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * jaoLicense - * - * Copyright (c) 2022 jao Minecraft Server - * - * The following license applies to this project: jaoLicense - * - * Japanese: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE.md - * English: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE-en.md - */ - -package com.jaoafa.mymaid4.event; - -import com.jaoafa.mymaid4.Main; -import com.jaoafa.mymaid4.lib.EventPremise; -import com.jaoafa.mymaid4.lib.MyMaidLibrary; -import io.papermc.paper.event.player.AsyncChatEvent; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.event.HoverEvent; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.List; - -public class Event_WhereAreYou extends MyMaidLibrary implements Listener, EventPremise { - List> whereAreYou = List.of( - List.of( - "みんな", - "どこ" - ), - List.of( - "mina", - "doko" - ), - List.of( - "minna", - "doko" - ), - List.of( - "minnna", - "doko" - ) - ); - - @Override - public String description() { - return "「みんなどこ」に自動返信します。"; - } - - @EventHandler - public void onChatWhereAreYou(AsyncChatEvent event) { - Player player = event.getPlayer(); - Component component = event.message(); - String message = PlainTextComponentSerializer.plainText().serialize(component); - - // 各項目のいずれか、そのうちのすべてに一致する場合 - if (whereAreYou.stream().noneMatch(list -> list.stream().allMatch(message::contains))) { - return; - } - new BukkitRunnable() { - public void run() { - chatFake(NamedTextColor.YELLOW, "jaotan", Component.join(JoinConfiguration.noSeparators(), - Component.text(player.getName() + "さん、ほかの人の場所を知るには、Dynmapというマップを使うのがおすすめです!"), - Component.text("https://map.jaoafa.com/", NamedTextColor.AQUA, TextDecoration.UNDERLINED) - .hoverEvent(HoverEvent.showText(Component.text("クリックすると「map.jaoafa.com」をブラウザで開きます。"))) - .clickEvent(ClickEvent.openUrl("https://map.jaoafa.com/"))), true); - } - }.runTaskLater(Main.getJavaPlugin(), 20L); - } -} diff --git a/src/main/java/com/jaoafa/mymaid4/lib/MeboChatBot.java b/src/main/java/com/jaoafa/mymaid4/lib/MeboChatBot.java new file mode 100644 index 000000000..7969fb46e --- /dev/null +++ b/src/main/java/com/jaoafa/mymaid4/lib/MeboChatBot.java @@ -0,0 +1,89 @@ +/* + * jaoLicense + * + * Copyright (c) 2022 jao Minecraft Server + * + * The following license applies to this project: jaoLicense + * + * Japanese: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE.md + * English: https://github.com/jaoafa/jao-Minecraft-Server/blob/master/jaoLICENSE-en.md + */ + +package com.jaoafa.mymaid4.lib; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import okhttp3.*; +import org.bukkit.entity.Player; +import org.json.JSONObject; + +import java.io.IOException; + +public class MeboChatBot { + private final String apiKey; + private final String agentId; + + public MeboChatBot(String apiKey, String agentId) { + this.apiKey = apiKey; + this.agentId = agentId; + } + + public MeboResponse chat(Player player, String text) { + try { + String url = "https://api-mebo.dev/api"; + OkHttpClient client = new OkHttpClient(); + JSONObject json = new JSONObject(); + json.put("api_key", apiKey); + json.put("agent_id", agentId); + json.put("utterance", text); + json.put("uid", player.getUniqueId().toString()); + + RequestBody requestBody = RequestBody.create(json.toString(), MediaType.parse("application/json; charset=UTF-8")); + Request request = new Request.Builder().url(url).post(requestBody).build(); + Response response = client.newCall(request).execute(); + if (response.code() != 200) { + response.close(); + return new MeboResponse(false, 0, "HTTP Error: " + response.code(), null); + } + + ResponseBody body = response.body(); + if (body == null) throw new RuntimeException(); + + JSONObject jsonObject = new JSONObject(body.string()); + response.close(); + + if (!jsonObject.has("bestResponse")) { + return new MeboResponse(false, 0, "No bestResponse", null); + } + // Main.getMyMaidLogger().info("MeboChatBot: " + jsonObject.getJSONObject("bestResponse").toString()); + + return new MeboResponse( + true, + jsonObject.getJSONObject("bestResponse").getDouble("score"), + jsonObject.getJSONObject("bestResponse").getString("utterance"), + jsonObject.getJSONObject("bestResponse").getString("url") + ); + } catch (IOException e) { + e.printStackTrace(); + return new MeboResponse(false, 0, "IOException", null); + } + } + + public record MeboResponse(boolean status, double score, String rawMessage, String url) { + public Component message() { + if (url != null) { + return Component + .text(rawMessage) + .append( + Component.text(url, NamedTextColor.AQUA, TextDecoration.UNDERLINED) + .hoverEvent(HoverEvent.showText(Component.text("クリックすると「" + url + "」をブラウザで開きます。"))) + .clickEvent(ClickEvent.openUrl(url)) + ); + } + return Component.text(rawMessage); + } + } +} diff --git a/src/main/java/com/jaoafa/mymaid4/lib/MyMaidConfig.java b/src/main/java/com/jaoafa/mymaid4/lib/MyMaidConfig.java index 01cf75c29..eb4ee5791 100644 --- a/src/main/java/com/jaoafa/mymaid4/lib/MyMaidConfig.java +++ b/src/main/java/com/jaoafa/mymaid4/lib/MyMaidConfig.java @@ -34,6 +34,8 @@ public class MyMaidConfig { private Long serverChatChannelId = null; private String githubAccessToken = null; private String rollbarAccessToken = null; + private String meboApiKey = null; + private String meboAgentId = null; public void init() { JavaPlugin plugin = Main.getJavaPlugin(); @@ -136,6 +138,18 @@ public void init() { } else { plugin.getLogger().warning(notFoundConfigKey("rollbarAccessToken")); } + + if (config.contains("meboApiKey")) { + meboApiKey = config.getString("meboApiKey"); + } else { + plugin.getLogger().warning(notFoundConfigKey("meboApiKey")); + } + + if (config.contains("meboAgentId")) { + meboAgentId = config.getString("meboAgentId"); + } else { + plugin.getLogger().warning(notFoundConfigKey("meboAgentId")); + } } String notFoundConfigKey(String key) { @@ -174,4 +188,12 @@ public String getGitHubAccessToken() { public String getRollbarAccessToken() { return rollbarAccessToken; } + + public String getMeboApiKey() { + return meboApiKey; + } + + public String getMeboAgentId() { + return meboAgentId; + } }