From f5bfc6f0c167737482d9ff9a6fe144024c76849f Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 12 Feb 2023 10:21:17 +0900
Subject: [PATCH] enhance(client): improve api error handling

---
 locales/ja-JP.yml           |  3 +++
 packages/frontend/src/os.ts | 27 +++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 4ef9fd5ae..14693439b 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -952,6 +952,9 @@ thisPostMayBeAnnoyingHome: "ホームに投稿"
 thisPostMayBeAnnoyingCancel: "やめる"
 thisPostMayBeAnnoyingIgnore: "このまま投稿"
 collapseRenotes: "見たことのあるRenoteを省略して表示"
+internalServerError: "サーバー内部エラー"
+internalServerErrorDescription: "サーバー内部で予期しないエラーが発生しました。"
+copyErrorInfo: "エラー情報をコピー"
 
 _achievements:
   earnedAt: "獲得日時"
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 639f4eaf1..6bff12661 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -17,6 +17,7 @@ import MkEmojiPickerWindow from '@/components/MkEmojiPickerWindow.vue';
 import MkPopupMenu from '@/components/MkPopupMenu.vue';
 import MkContextMenu from '@/components/MkContextMenu.vue';
 import { MenuItem } from '@/types/menu';
+import copyToClipboard from './scripts/copy-to-clipboard';
 
 export const openingWindowsCount = ref(0);
 
@@ -26,10 +27,32 @@ export const apiWithDialog = ((
 	token?: string | null | undefined,
 ) => {
 	const promise = api(endpoint, data, token);
-	promiseDialog(promise, null, (err) => {
+	promiseDialog(promise, null, async (err) => {
 		let title = null;
 		let text = err.message + '\n' + (err as any).id;
-		if (err.code === 'RATE_LIMIT_EXCEEDED') {
+		if (err.code === 'INTERNAL_ERROR') {
+			title = i18n.ts.internalServerError;
+			text = i18n.ts.internalServerErrorDescription;
+			const date = new Date().toISOString();
+			const { result } = await actions({
+				type: 'error',
+				title,
+				text,
+				actions: [{
+					value: 'ok',
+					text: i18n.ts.gotIt,
+					primary: true,
+				}, {
+					value: 'copy',
+					text: i18n.ts.copyErrorInfo,
+				}],
+			});
+			if (result === 'copy') {
+				copyToClipboard(`Endpoint: ${endpoint}\nInfo: ${JSON.stringify(err.info)}\nDate: ${date}`);
+				success();
+			}
+			return;
+		} else if (err.code === 'RATE_LIMIT_EXCEEDED') {
 			title = i18n.ts.cannotPerformTemporary;
 			text = i18n.ts.cannotPerformTemporaryDescription;
 		} else if (err.code.startsWith('TOO_MANY')) {