From eb7bfb4fbceeef24de53f8ac8c92b5f9b0fec1fa Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 03:11:34 +0000 Subject: [PATCH 1/2] fix: stabilize bot logic and improve dashboard UI - Updated Gemini model name to `gemini-1.5-flash` in `src/config/discord.js`. - Improved AI response parsing in `statusService`, `levelingService`, and `welcomeService` to handle markdown JSON blocks and extra text. - Enhanced `interactionCreate.js` to enforce blacklist and maintenance mode checks on all interaction types, including buttons. - Refined Tom Select dropdown positioning logic in `public/client.js` to prevent overflow and ensure visibility near viewport edges. - Performed syntax checks and frontend verification. Co-authored-by: systemcmd0122 <155505304+systemcmd0122@users.noreply.github.com> --- events/interactionCreate.js | 16 ++++++++++------ public/client.js | 17 +++++++++++------ src/config/discord.js | 2 +- src/services/levelingService.js | 6 ++++-- src/services/statusService.js | 9 ++++++++- src/services/welcomeService.js | 4 +++- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/events/interactionCreate.js b/events/interactionCreate.js index 5b94e14..91a15ec 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -29,10 +29,6 @@ async function getCachedDoc(db, collection, id, cacheObj) { module.exports = { name: 'interactionCreate', async execute(interaction, client) { - if (interaction.isButton()) return; - - if (!interaction.isChatInputCommand() && !interaction.isAutocomplete() && !interaction.isModalSubmit()) return; - // 1. Global Checks (Maintenance & Blacklist) const maintenanceData = await getCachedDoc(client.db, 'bot_settings', 'maintenance', globalCache.maintenance); const blacklistData = await getCachedDoc(client.db, 'bot_settings', 'blacklist', globalCache.blacklist); @@ -40,7 +36,9 @@ module.exports = { // Blacklist check if (blacklistData && blacklistData.users?.includes(interaction.user.id)) { const message = { content: '[ERR] あなたはボットの使用を制限されています。', ephemeral: true }; - return interaction.isAutocomplete() ? null : interaction.reply(message); + if (interaction.isAutocomplete()) return null; + if (interaction.isRepliable()) return interaction.reply(message); + return; } // Maintenance mode check (Bypass for Bot Owners) @@ -54,10 +52,16 @@ module.exports = { if (!owners.includes(interaction.user.id)) { const reason = maintenanceData.reason || '現在メンテナンス中です。'; const message = { content: `[INFO] ${reason}`, ephemeral: true }; - return interaction.isAutocomplete() ? null : interaction.reply(message); + if (interaction.isAutocomplete()) return null; + if (interaction.isRepliable()) return interaction.reply(message); + return; } } + if (interaction.isButton()) return; + + if (!interaction.isChatInputCommand() && !interaction.isAutocomplete() && !interaction.isModalSubmit()) return; + if (interaction.isChatInputCommand()) { // 2. Guild-specific Command Check if (interaction.guildId) { diff --git a/public/client.js b/public/client.js index 62695df..c460c6a 100644 --- a/public/client.js +++ b/public/client.js @@ -113,10 +113,9 @@ document.addEventListener('DOMContentLoaded', async () => { $dropdown.style.zIndex = '9999'; // コントロールの幅に合わせる(最小幅は200px) - const width = controlRect.width; + let width = Math.max(controlRect.width, 200); $dropdown.style.width = width + 'px'; $dropdown.style.minWidth = '200px'; - $dropdown.style.maxWidth = width + 'px'; // 縦位置の計算 const dropdownHeight = Math.min($dropdown.scrollHeight, 300); @@ -141,13 +140,19 @@ document.addEventListener('DOMContentLoaded', async () => { } // 横位置の調整(左端に合わせる) - $dropdown.style.left = controlRect.left + 'px'; + let left = controlRect.left; // 右端がはみ出す場合の調整 - const rightEdge = controlRect.left + width; - if (rightEdge > window.innerWidth - 8) { - $dropdown.style.left = (window.innerWidth - width - 8) + 'px'; + if (left + width > window.innerWidth - 8) { + left = window.innerWidth - width - 8; } + + // 左端がはみ出す場合の調整 + if (left < 8) { + left = 8; + } + + $dropdown.style.left = left + 'px'; }, ...options }); diff --git a/src/config/discord.js b/src/config/discord.js index 8d8a71d..556b9b2 100644 --- a/src/config/discord.js +++ b/src/config/discord.js @@ -6,7 +6,7 @@ const path = require('node:path'); const chalk = require('chalk'); const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY); -const geminiModel = genAI.getGenerativeModel({ model: "gemini-2.5-flash" }); +const geminiModel = genAI.getGenerativeModel({ model: "gemini-1.5-flash" }); const client = new Client({ intents: [ diff --git a/src/services/levelingService.js b/src/services/levelingService.js index 44d6f81..69d18b9 100644 --- a/src/services/levelingService.js +++ b/src/services/levelingService.js @@ -23,8 +23,10 @@ async function generateLevelUpComment(client, user, newLevel, serverName) { * **絶対に絵文字を使用しないでください。**`; const result = await client.geminiModel.generateContent(prompt); - const text = result.response.text().trim().replace(/[\n*「」]/g, '').split('。')[0]; - return text; + const rawText = result.response.text().trim(); + // 改行、アスタリスク、カギカッコを除去し、最初の文章のみを取得 + const text = rawText.replace(/[\n*「」]/g, '').split(/[。!?!?. \n]/)[0]; + return text || `**${user.displayName} が新たな境地へ到達しました!**`; } catch (error) { console.error(chalk.red('[ERROR] Gemini APIでのコメント生成に失敗:'), error.message); return `**${user.displayName} が新たな境地へ到達しました!**`; diff --git a/src/services/statusService.js b/src/services/statusService.js index 2406e1b..04a9885 100644 --- a/src/services/statusService.js +++ b/src/services/statusService.js @@ -15,7 +15,14 @@ async function generateAIStatus(client) { - ステータスメッセージは30文字以内にしてください。`; const result = await client.geminiModel.generateContent(prompt); - const text = result.response.text().replace(/```json|```/g, '').trim(); + let text = result.response.text().trim(); + + // JSONを抽出するためのロバストな処理 + const jsonMatch = text.match(/\{[\s\S]*\}/); + if (jsonMatch) { + text = jsonMatch[0]; + } + return JSON.parse(text); } catch (error) { console.error(chalk.red('[ERROR] Geminiによるステータス生成に失敗:'), error); diff --git a/src/services/welcomeService.js b/src/services/welcomeService.js index 642dc9d..76926f7 100644 --- a/src/services/welcomeService.js +++ b/src/services/welcomeService.js @@ -18,7 +18,9 @@ async function generateWelcomeWithGemini(client, member) { - 必ずJSON形式で、{"title": "生成したタイトル", "description": "生成した説明文"} の形式で出力してください。`; const result = await client.geminiModel.generateContent(prompt); - const text = result.response.text().replace(/```json|```/g, '').trim(); + let text = result.response.text().trim(); + const jsonMatch = text.match(/\{[\s\S]*\}/); + if (jsonMatch) text = jsonMatch[0]; return JSON.parse(text); } catch (error) { console.error('[ERROR] Geminiでのウェルカムメッセージ生成エラー:', error); From bff2e1315e408d0913f4a1cfc3c8656f5c9cc6c1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 03:29:39 +0000 Subject: [PATCH 2/2] fix: stabilize bot logic, improve UI, and add admin shortcut - Corrected Gemini model name and improved AI response parsing. - Refined Tom Select dropdown positioning in the dashboard. - Reordered interaction checks for better security. - Added "admin" shortcut to the login page for easier admin access. Co-authored-by: systemcmd0122 <155505304+systemcmd0122@users.noreply.github.com> --- public/login.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/public/login.html b/public/login.html index 5d60eb7..bdffd45 100644 --- a/public/login.html +++ b/public/login.html @@ -51,6 +51,14 @@

[O] OrderlyCore

const form = document.getElementById('login-form'); const tokenInput = document.getElementById('token'); + + // Admin shortcut + tokenInput.addEventListener('input', () => { + if (tokenInput.value.trim().toLowerCase() === 'admin') { + window.location.href = '/admin-login.html'; + } + }); + const messageEl = document.getElementById('message'); const msgWrap = document.getElementById('message-container'); const submitBtn = document.getElementById('submit-btn');