OSDN Git Service

[Feature] エラー情報をWebhookで送信する機能
authorHabu <habu1010+github@gmail.com>
Fri, 7 Jul 2023 11:31:24 +0000 (20:31 +0900)
committerHabu <habu1010+github@gmail.com>
Fri, 7 Jul 2023 12:53:31 +0000 (21:53 +0900)
エラー情報をWebhookで送信する機能を実装する。Webhook送信先はDiscordの
Webhook URLを想定しており、https://hengband.github.io/api/report-error
より送信先URLを取得する。

Hengband/Hengband/Hengband.vcxproj
Hengband/Hengband/Hengband.vcxproj.filters
src/Makefile.am
src/net/report-error.cpp [new file with mode: 0644]
src/net/report-error.h [new file with mode: 0644]

index 586dd94..325fb1c 100644 (file)
     <ClCompile Include="..\..\src\net\curl-easy-session.cpp" />\r
     <ClCompile Include="..\..\src\net\curl-slist.cpp" />\r
     <ClCompile Include="..\..\src\net\http-client.cpp" />\r
+    <ClCompile Include="..\..\src\net\report-error.cpp" />\r
     <ClCompile Include="..\..\src\object-enchant\enchanter-factory.cpp" />\r
     <ClCompile Include="..\..\src\mspell\mspell-attack\abstract-mspell.cpp" />\r
     <ClCompile Include="..\..\src\mspell\mspell-data.cpp" />\r
     <ClInclude Include="..\..\src\net\curl-easy-session.h" />\r
     <ClInclude Include="..\..\src\net\curl-slist.h" />\r
     <ClInclude Include="..\..\src\net\http-client.h" />\r
+    <ClInclude Include="..\..\src\net\report-error.h" />\r
     <ClInclude Include="..\..\src\object-enchant\enchanter-factory.h" />\r
     <ClInclude Include="..\..\src\object-enchant\protector\apply-magic-soft-armor.h" />\r
     <ClInclude Include="..\..\src\object-enchant\others\apply-magic-lite.h" />\r
index 9608cc3..47f64e5 100644 (file)
     <ClCompile Include="..\..\src\util\sha256.cpp">\r
       <Filter>util</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\src\net\report-error.cpp">\r
+      <Filter>net</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\..\src\combat\shoot.h">\r
     <ClInclude Include="..\..\src\external-lib\include-json.h">\r
       <Filter>external-lib</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\src\net\report-error.h">\r
+      <Filter>net</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="..\..\src\wall.bmp" />\r
index 52167ff..bdce87e 100644 (file)
@@ -576,6 +576,7 @@ hengband_SOURCES = \
        net/curl-easy-session.cpp net/curl-easy-session.h \
        net/curl-slist.cpp net/curl-slist.h \
        net/http-client.cpp net/http-client.h \
+       net/report-error.cpp net/report-error.h \
        \
        object/item-tester-hooker.cpp object/item-tester-hooker.h \
        object/object-broken.cpp object/object-broken.h \
diff --git a/src/net/report-error.cpp b/src/net/report-error.cpp
new file mode 100644 (file)
index 0000000..1976383
--- /dev/null
@@ -0,0 +1,72 @@
+#include "external-lib/include-json.h"
+#include "locale/japanese.h"
+#include "net/http-client.h"
+#include "system/angband-version.h"
+#include <sstream>
+#include <string_view>
+
+#if !defined(DISABLE_NET)
+
+namespace {
+
+/*!
+ * @brief エラーレポート送信用のWebhook URLを取得する
+ * @return 取得に成功した場合はWebhook URL、失敗した場合は空文字列
+ */
+std::string fetch_webhook_url_for_sending_error_report()
+{
+    http::Client client;
+    constexpr auto url = "https://hengband.github.io/api/report-error";
+    const auto response = client.get(url);
+    if (!response || (response->status != 200)) {
+        return "";
+    }
+
+    const auto json = nlohmann::json::parse(response->body);
+    return json["webhook_url"];
+}
+
+/*!
+ * @brief 送信するエラーレポートのJSONオブジェクトを作成する
+ *
+ * @param message エラーメッセージ
+ * @return 作成したJSONオブジェクト
+ */
+nlohmann::json create_report_json(std::string_view message)
+{
+    nlohmann::json webhook;
+    webhook["username"] = "Hengband Error Report";
+    constexpr auto conv_error_msg = "Cannot convert to UTF-8";
+    nlohmann::json embed;
+    embed["title"] = sys_to_utf8(get_version()).value_or(conv_error_msg);
+    embed["description"] = sys_to_utf8(message).value_or(conv_error_msg);
+    embed["color"] = 0xff0000; // red
+    webhook["embeds"].push_back(std::move(embed));
+
+    return webhook;
+}
+
+}
+
+/*!
+ * @brief エラーレポートを送信する
+ *
+ * @param description 送信するエラーの説明
+ * @return 送信に成功した場合はtrue、失敗した場合はfalse
+ */
+bool report_error(std::string_view description)
+{
+    const auto webhook_url = fetch_webhook_url_for_sending_error_report();
+    if (webhook_url.empty()) {
+        return false;
+    }
+
+    const auto report_json = create_report_json(description);
+
+    http::Client client;
+    const auto response = client.post(webhook_url, report_json.dump(), "application/json");
+
+    return (response && (response->status == 200));
+}
+
+#endif // !defined(DISABLE_NET)
diff --git a/src/net/report-error.h b/src/net/report-error.h
new file mode 100644 (file)
index 0000000..94c5365
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "system/angband.h"
+
+#if !defined(DISABLE_NET)
+
+#include <string_view>
+
+bool report_error(std::string_view description);
+
+#endif // !defined(DISABLE_NET)