From 502196429a52c960f21e33606bc9223d79eb18b1 Mon Sep 17 00:00:00 2001 From: wood chen Date: Fri, 7 Mar 2025 07:10:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20API=20=E5=AF=86=E9=92=A5?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在设置页面新增"测试连接"按钮 - 实现 testApiKey 方法验证 Discourse API 凭据 - 添加连接测试的成功和失败消息处理 - 更新中英文国际化文案支持新功能 --- src/config.ts | 43 ++++++++++++++++++++++++++++++++++++- src/i18n/en.ts | 5 +++++ src/i18n/zh-CN.ts | 5 +++++ src/main.ts | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index ed74568..1fc33af 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,4 @@ -import { PluginSettingTab, Setting, App } from 'obsidian'; +import { PluginSettingTab, Setting, App, Notice, ButtonComponent } from 'obsidian'; import DiscourseSyncPlugin from './main'; import { t } from './i18n'; @@ -66,5 +66,46 @@ export class DiscourseSyncSettingsTab extends PluginSettingTab { await this.plugin.saveSettings(); }), ); + + new Setting(containerEl) + .setName(t('TEST_API_KEY')) + .setDesc('') + .addButton((button: ButtonComponent) => { + button + .setButtonText(t('TEST_API_KEY')) + .setCta() + .onClick(async () => { + button.setButtonText(t('TESTING')); + button.setDisabled(true); + + const result = await this.plugin.testApiKey(); + + button.setButtonText(t('TEST_API_KEY')); + button.setDisabled(false); + + if (result.success) { + new Notice(result.message, 5000); + } else { + const errorEl = containerEl.createDiv('discourse-api-error'); + errorEl.createEl('h3', { text: t('API_TEST_FAILED') }); + + const formattedMessage = typeof result.message === 'string' + ? result.message + : JSON.stringify(result.message, null, 2); + + errorEl.createEl('p', { text: formattedMessage }); + + errorEl.style.backgroundColor = 'rgba(255, 0, 0, 0.1)'; + errorEl.style.border = '1px solid rgba(255, 0, 0, 0.3)'; + errorEl.style.borderRadius = '5px'; + errorEl.style.padding = '10px'; + errorEl.style.marginTop = '10px'; + + setTimeout(() => { + errorEl.remove(); + }, 10000); + } + }); + }); } } diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 73a40bd..627dfc3 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -6,6 +6,11 @@ export default { 'API_KEY_DESC': "API key created in '/admin/api/keys'", 'USERNAME': 'Username', 'USERNAME_DESC': 'Your Discourse username', + 'TEST_API_KEY': 'Test Connection', + 'TESTING': 'Testing...', + 'API_TEST_SUCCESS': 'Connection successful! API key is valid', + 'API_TEST_FAILED': 'API key test failed', + 'MISSING_CREDENTIALS': 'Please fill in Forum URL, API Key and Username first', // Publish page 'PUBLISH_TO_DISCOURSE': 'Publish to Discourse', diff --git a/src/i18n/zh-CN.ts b/src/i18n/zh-CN.ts index f3e1087..be1cffd 100644 --- a/src/i18n/zh-CN.ts +++ b/src/i18n/zh-CN.ts @@ -6,6 +6,11 @@ export default { 'API_KEY_DESC': "在'/admin/api/keys'中创建的 API 密钥", 'USERNAME': '用户名', 'USERNAME_DESC': 'Discourse 用户名', + 'TEST_API_KEY': '测试连接', + 'TESTING': '测试中...', + 'API_TEST_SUCCESS': '连接成功!API密钥有效', + 'API_TEST_FAILED': 'API密钥测试失败', + 'MISSING_CREDENTIALS': '请先填写论坛地址、API密钥和用户名', // 发布页面 'PUBLISH_TO_DISCOURSE': '发布到 Discourse', diff --git a/src/main.ts b/src/main.ts index bc4b86b..6c83544 100644 --- a/src/main.ts +++ b/src/main.ts @@ -445,6 +445,60 @@ export default class DiscourseSyncPlugin extends Plugin { } } + /** + * 测试API密钥是否有效 + * @returns 返回测试结果,包含成功状态和消息 + */ + async testApiKey(): Promise<{ success: boolean; message: string }> { + if (!this.settings.baseUrl || !this.settings.apiKey || !this.settings.disUser) { + return { + success: false, + message: t('MISSING_CREDENTIALS') + }; + } + + const url = `${this.settings.baseUrl}/users/${this.settings.disUser}.json`; + const headers = { + "Content-Type": "application/json", + "Api-Key": this.settings.apiKey, + "Api-Username": this.settings.disUser, + }; + + try { + const response = await requestUrl({ + url: url, + method: "GET", + contentType: "application/json", + headers, + throw: false + }); + + if (response.status === 200) { + return { + success: true, + message: t('API_TEST_SUCCESS') + }; + } else { + let errorMessage; + try { + const errorData = await response.json; + errorMessage = errorData?.errors || errorData?.error || `${t('API_TEST_FAILED')} (${response.status})`; + } catch (e) { + errorMessage = `${t('API_TEST_FAILED')} (${response.status})`; + } + return { + success: false, + message: errorMessage + }; + } + } catch (error) { + return { + success: false, + message: error.message || t('UNKNOWN_ERROR') + }; + } + } + registerDirMenu(menu: Menu, file: TFile) { const syncDiscourse = (item: MenuItem) => { item.setTitle(t('PUBLISH_TO_DISCOURSE'));