Skip to content
This repository has been archived by the owner on Nov 12, 2023. It is now read-only.

Commit

Permalink
Merge pull request #242 from book000/feat/bug-reaction
Browse files Browse the repository at this point in the history
feat: バグリアクションの実装
  • Loading branch information
book000 authored Mar 29, 2022
2 parents 7295970 + e127296 commit bb9b41a
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 2 deletions.
125 changes: 125 additions & 0 deletions src/main/java/com/jaoafa/javajaotan2/event/Event_BugReaction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* 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.javajaotan2.event;

import com.jaoafa.javajaotan2.Main;
import com.jaoafa.javajaotan2.lib.Channels;
import com.jaoafa.javajaotan2.lib.JavajaotanLibrary;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class Event_BugReaction extends ListenerAdapter {
String targetReaction = "\uD83D\uDC1B"; // :bug:
String repo = "jaoafa/jao-Minecraft-Server";

@Override
public void onMessageReactionAdd(@NotNull MessageReactionAddEvent event) {
if (Main.getConfig().getGuildId() != event.getGuild().getIdLong()) return;

User user = event.getUser();

if (user == null) user = event.retrieveUser().complete();
if (user.isBot()) return;

MessageReaction.ReactionEmote emote = event.getReactionEmote();

if (!emote.isEmoji()) return;
if (!emote.getEmoji().equals(targetReaction)) return;

Message message = event.retrieveMessage().complete();
List<User> users = message.retrieveReactionUsers(targetReaction).complete();

if (users.size() != 1) {
// 1人以外 = 0もしくは2人以上 = 既に報告済み
return;
}
TextChannel channel = event.getTextChannel();

// Issueを作成する
ZonedDateTime createdAt = message.getTimeCreated().atZoneSameInstant(ZoneId.of("Asia/Tokyo"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
String title = user.getAsTag() + " による #" + message.getChannel().getName() + " での不具合報告";
String body = """
## 不具合と思われるメッセージ (または報告)
%s
URL: %s
## 不具合報告者
%s
""".formatted(
createdAt.format(formatter) + " に送信された `" + message.getAuthor().getAsTag() + "` による `#" + message.getChannel().getName() + "` でのメッセージ",
message.getJumpUrl(),
"`" + user.getAsTag() + "`"
);

JavajaotanLibrary.CreateIssueResponse response = JavajaotanLibrary.createIssue(repo, title, body);
JavajaotanLibrary.IssueResponseType responseType = response.responseType();
int issueNumber = response.issueNumber();

// スレッドを立てる
TextChannel developmentChannel = Channels.development.getChannel();
if (developmentChannel == null) {
// チャンネルが見つからない
channel
.sendMessage(user.getAsMention() + " スレッドの作成に失敗しました。developmentチャンネルが見つかりません。")
.delay(1, TimeUnit.MINUTES, Main.getScheduler()) // delete 1 minute later
.flatMap(Message::delete)
.queue();
return;
}

String mainMessage = """
## 不具合と思われるメッセージ (または報告)
%s
URL: %s
## 不具合報告者
%s
""".formatted(
createdAt.format(formatter) + " に送信された " + message.getAuthor().getAsMention() + " による " + message.getChannel().getAsMention() + " でのメッセージ",
message.getJumpUrl(),
user.getAsMention()
);

List<String> messages = new ArrayList<>();
if (responseType == JavajaotanLibrary.IssueResponseType.SUCCESS) {
messages.add("[LINKED-ISSUE:jaoafa/jao-Minecraft-Server#" + issueNumber + "]");
messages.add("");
}
messages.add(":bug: リアクションにより、不具合の報告がなされました。");
messages.add(mainMessage);
if (responseType == JavajaotanLibrary.IssueResponseType.SUCCESS) {
messages.add("Issue: https://github.com/jaoafa/jao-Minecraft-Server/issues/" + issueNumber);
}

String threadTitle = (responseType == JavajaotanLibrary.IssueResponseType.SUCCESS ? "*" + issueNumber + " " : "") + title;
ThreadChannel thread = developmentChannel.createThreadChannel(threadTitle).complete();
thread.sendMessage(String.join("\n", messages)).queue();

message.addReaction(targetReaction).queue();
}
}
1 change: 1 addition & 0 deletions src/main/java/com/jaoafa/javajaotan2/lib/Channels.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public enum Channels {
invite_checker(893166232772161577L),
c659(621632815599190016L), // 最初を数字にできない…
meeting_vote(597423974816808970L),
development(597765518501478401L),
vc_speech_log(927666435336056862L);

private long channel_id;
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/jaoafa/javajaotan2/lib/JavajaotanConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* jaoLicense
*
* Copyright (c) 2021 jao Minecraft Server
* Copyright (c) 2022 jao Minecraft Server
*
* The following license applies to this project: jaoLicense
*
Expand Down Expand Up @@ -29,6 +29,7 @@ public class JavajaotanConfig {
String customSearchCX;
String gasTranslateAPIUrl;
String detectLanguageAPIToken;
String githubAPIToken;

public JavajaotanConfig() throws RuntimeException {
logger = Main.getLogger();
Expand All @@ -53,6 +54,7 @@ public JavajaotanConfig() throws RuntimeException {
customSearchCX = config.optString("customSearchCX");
gasTranslateAPIUrl = config.optString("gasTranslateAPIUrl");
detectLanguageAPIToken = config.optString("detectLanguageAPIToken");
githubAPIToken = config.optString("githubAPIToken");

// -- データベース関連
if (config.has("main_database")) {
Expand Down Expand Up @@ -130,7 +132,13 @@ public String getGASTranslateAPIUrl() {
return gasTranslateAPIUrl;
}

@Nullable
public String getDetectLanguageAPIToken() {
return detectLanguageAPIToken;
}

@Nullable
public String getGitHubAPIToken() {
return githubAPIToken;
}
}
118 changes: 117 additions & 1 deletion src/main/java/com/jaoafa/javajaotan2/lib/JavajaotanLibrary.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* jaoLicense
*
* Copyright (c) 2021 jao Minecraft Server
* Copyright (c) 2022 jao Minecraft Server
*
* The following license applies to this project: jaoLicense
*
Expand All @@ -11,10 +11,17 @@

package com.jaoafa.javajaotan2.lib;

import com.jaoafa.javajaotan2.Main;
import net.dv8tion.jda.api.entities.*;
import okhttp3.*;
import org.json.JSONArray;
import org.json.JSONObject;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -117,4 +124,113 @@ public static String getContentDisplay(Message message, String raw) {
}
return tmp;
}

@Nonnull
public static CreateIssueResponse createIssue(String repo, String title, String body) {
String githubToken = Main.getConfig().getGitHubAPIToken();
if (githubToken == null || githubToken.isEmpty()) {
return new CreateIssueResponse(
IssueResponseType.FAILED,
"GitHub API Token が設定されていません。",
-1
);
}
String url = String.format("https://api.github.com/repos/%s/issues", repo);
JSONObject json = new JSONObject()
.put("title", title)
.put("body", body)
.put("labels", new JSONArray()
.put("\uD83D\uDC1Bbug"));

try {
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = RequestBody.create(json.toString(), MediaType.parse("application/json; charset=UTF-8"));
Request request = new Request.Builder()
.url(url)
.header("Authorization", String.format("token %s", githubToken))
.post(requestBody)
.build();
JSONObject obj;
try (Response response = client.newCall(request).execute()) {
if (response.code() != 201) {
return new CreateIssueResponse(
IssueResponseType.FAILED,
"Issue の作成に失敗しました。",
-1
);
}
obj = new JSONObject(Objects.requireNonNull(response.body()).string());
}

int issueNum = obj.getInt("number");
return new CreateIssueResponse(
IssueResponseType.SUCCESS,
"Issue の作成に成功しました。",
issueNum
);
} catch (IOException e) {
e.printStackTrace();
return new CreateIssueResponse(
IssueResponseType.FAILED,
"Issue の作成に失敗しました。" + e.getMessage(),
-1
);
}
}

public record CreateIssueResponse(IssueResponseType responseType, String message, int issueNumber) {
}

@Nonnull
public static CreateIssueCommentResponse createIssueComment(String repo, int issueNum, String body) {
String githubToken = Main.getConfig().getGitHubAPIToken();
if (githubToken == null || githubToken.isEmpty()) {
return new CreateIssueCommentResponse(
IssueResponseType.FAILED,
"GitHub API Token が設定されていません。"
);
}
String url = String.format("https://api.github.com/repos/%s/issues/%s/comments", repo, issueNum);
JSONObject json = new JSONObject()
.put("body", body);

try {
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = RequestBody.create(json.toString(), MediaType.parse("application/json; charset=UTF-8"));
Request request = new Request.Builder()
.url(url)
.header("Authorization", String.format("token %s", githubToken))
.post(requestBody)
.build();
JSONObject obj;
try (Response response = client.newCall(request).execute()) {
if (response.code() != 201) {
return new CreateIssueCommentResponse(
IssueResponseType.FAILED,
"Issue コメントの作成に失敗しました。"
);
}
obj = new JSONObject(Objects.requireNonNull(response.body()).string());
}

return new CreateIssueCommentResponse(
IssueResponseType.SUCCESS,
"Issue コメントの作成に成功しました。"
);
} catch (IOException e) {
e.printStackTrace();
return new CreateIssueCommentResponse(
IssueResponseType.FAILED,
"Issue コメントの作成に失敗しました。" + e.getMessage()
);
}
}

public record CreateIssueCommentResponse(IssueResponseType responseType, String message) {
}

public enum IssueResponseType {
SUCCESS,
FAILED
}
}

0 comments on commit bb9b41a

Please sign in to comment.