fenghelin/turtle
0
1const { Client, GatewayIntentBits } = require('discord.js');2const axios = require('axios');3 4 5const express = require('express');6const app = express();7app.get('/', (req, res) => res.send('🐢 烏龜機器人在 Hugging Face 正常工作中!'));8const port = 7860; // 👈 這裡強制改成 78609app.listen(port, () => console.log(`🌍 偽裝網頁已啟動 (Port: ${port})`));10// ==========================================11 12// ==========================================13// 🔑 雲端環境變數抓取區14// ==========================================15const TOKEN = process.env.DISCORD_TOKEN;16const GITHUB_API_KEY = process.env.GITHUB_API_KEY;17const GAS_URL = process.env.GAS_URL;18const MODEL_NAME = "gpt-4o-mini"; // 🌟 補上這行:指定 AI 模型19 20// 初始化 Discord 機器人21const client = new Client({22 intents: [23 GatewayIntentBits.Guilds,24 GatewayIntentBits.GuildMessages,25 GatewayIntentBits.MessageContent26 ]27});28// 開啟上帝視角,印出所有底層連線細節29client.on('debug', console.log);30 31 32 33// 當頻道有新訊息時34client.on('messageCreate', async (message) => {35 if (message.author.bot) return;36 37 // ==========================================38 // 功能 1:萃取單字並存入試算表 (!jp)39 // ==========================================40 if (message.content.startsWith('!jp')) {41 const loadingMessage = await message.reply('⏳ 收到!烏龜正在努力閱讀中,請稍候...');42 let chatText = message.content.replace('!jp', '').trim();43 44 if (message.attachments.size > 0) {45 const attachment = message.attachments.first();46 try {47 const fileResponse = await axios.get(attachment.url);48 chatText = chatText + "\n\n" + fileResponse.data;49 } catch (err) {50 return loadingMessage.edit('❌ 讀取檔案失敗,請確定上傳的是純文字檔 (.txt) 喔!');51 }52 }53 54 if (!chatText.trim()) return loadingMessage.edit('⚠️ 請在 !jp 後面貼上文字,或上傳 .txt 檔案喔!');55 56 try {57 const prompt = `你是一個專業的資料萃取助理。請從以下的對話紀錄中,找出所有學習到的「日文單字/句子」及對應的「中文講解」。請嚴格且只輸出 JSON 陣列格式:[{"jp": "單字", "zh": "講解"}]。對話:\n` + chatText;58 59 const response = await axios.post('https://models.inference.ai.azure.com/chat/completions', {60 model: MODEL_NAME,61 messages: [{ role: 'user', content: prompt }],62 temperature: 0.2,63 max_tokens: 102464 }, { headers: { 'Authorization': `Bearer ${GITHUB_API_KEY}`, 'Content-Type': 'application/json' } });65 66 let aiResult = response.data.choices[0].message.content.trim().replace(/```json/g, "").replace(/```/g, "").trim();67 const wordsArray = JSON.parse(aiResult);68 69 let replyText = '🎉 **萃取成功!以下是幫你整理好的單字卡:**\n\n';70 wordsArray.forEach(word => { replyText += `🇯🇵 **${word.jp}**\n📝 ${word.zh}\n──────────\n`; });71 72 try {73 await axios.post(GAS_URL, wordsArray);74 replyText += '✅ **已同步自動儲存至你的日文大本營!**';75 } catch (gasError) {76 replyText += '⚠️ **儲存至試算表失敗,但單字已為您整理如上。**';77 }78 79 if (replyText.length > 2000) replyText = replyText.substring(0, 1900) + '\n\n... (字數超過限制省略)';80 await loadingMessage.edit(replyText);81 82 } catch (error) {83 await loadingMessage.edit('❌ 分析失敗,請檢查內容格式!');84 }85 }86 87 // ==========================================88 // 功能 2:AI 日文老師專屬解題 (!ask)89 // ==========================================90 else if (message.content.startsWith('!ask')) {91 const question = message.content.replace('!ask', '').trim();92 93 if (!question) {94 return message.reply('⚠️ 請在 !ask 後面輸入你想問的問題喔!例如:`!ask は和が的差別是什麼?`');95 }96 97 const loadingMessage = await message.reply('🤔 老師思考中,請稍候...');98 99 try {100 const prompt = `你現在是一位專業、有耐心的日文老師。請用繁體中文為學生的以下問題提供詳細、清楚的解答。如果可以,請提供簡單的日文例句來輔助說明。\n學生的問題:\n` + question;101 102 const response = await axios.post('https://models.inference.ai.azure.com/chat/completions', {103 model: MODEL_NAME,104 messages: [{ role: 'user', content: prompt }],105 temperature: 0.6,106 max_tokens: 1500107 }, {108 headers: {109 'Authorization': `Bearer ${GITHUB_API_KEY}`,110 'Content-Type': 'application/json'111 }112 });113 114 const aiResult = response.data.choices[0].message.content.trim();115 116 if (aiResult.length > 2000) {117 await loadingMessage.edit(aiResult.substring(0, 1950) + '\n\n... (字數超過限制,已省略部分內容)');118 } else {119 await loadingMessage.edit(aiResult);120 }121 122 } catch (error) {123 console.error("AI 老師連線錯誤:", error);124 await loadingMessage.edit('❌ 老師的腦袋稍微卡住了,請稍後再試!');125 }126 }127});128 129// ====== 把這段取代掉原本的 client.once 和 client.login ======130 131// 1. 修正開機暗號 (把 clientReady 改成標準的 ready)132client.once('ready', () => {133 console.log(`✅ 大成功!機器人 ${client.user.tag} 已經順利登入 Discord 並連線!`);134});135 136console.log("準備登入 Discord... 檢查 Token 狀態:", TOKEN ? "🔑 有抓到鑰匙!" : "❌ 鑰匙是空的!");137 138client.login(TOKEN.trim()).catch(err => {139 console.error("🚨 致命錯誤:機器人登入失敗!");140 console.error("錯誤原因請看這裡 👉", err);141});142 