From 964389cf1ac1ab8866b401fede6bda8991f8c4e4 Mon Sep 17 00:00:00 2001 From: JianMiau Date: Thu, 24 Apr 2025 16:26:27 +0800 Subject: [PATCH] [add] /everyone --- app.js | 45 ++++++++++++++++++++++++--------------------- db.js | 47 ++++++++++++++++++++++++++++++++++++++--------- models/User.js | 9 --------- userModel.js | 15 +++++++++++++++ 4 files changed, 77 insertions(+), 39 deletions(-) delete mode 100644 models/User.js create mode 100644 userModel.js diff --git a/app.js b/app.js index c2eb2c6..6ecd48d 100644 --- a/app.js +++ b/app.js @@ -1,11 +1,14 @@ +// app.js // 關掉 webhook,專心用 polling 模式 // 執行以下指令取消 webhook(只需要做一次): // curl -F "url=" https://api.telegram.org/bot7916405163:AAGllDyNHNRTPDJ4gjwFPDi-TFDyFwD4foA/setWebhook require('dotenv').config(); // 加這行載入 .env 檔案 -const User = require('./models/User'); const TelegramBot = require('node-telegram-bot-api'); +const { connectDB, saveUser, getGroupUsers } = require('./db'); + +connectDB(); // 建立資料庫連線 const token = process.env.BOT_TOKEN; // 從環境變數讀取 token //括號裡面的內容需要改為在第5步獲得的Token @@ -45,32 +48,32 @@ bot.onText(/\/roll(?:@[\w_]+)?(?:\s+(\d*)d(\d+))?/i, function (msg, match) { }); bot.onText(/\/everyone/, async (msg) => { - const chatId = msg.chat.id; - - const users = await User.find({}); - if (users.length === 0) { - return bot.sendMessage(chatId, '尚未記錄任何使用者。'); + if (msg.chat.type !== 'group' && msg.chat.type !== 'supergroup') { + return bot.sendMessage(msg.chat.id, '⚠️ 此指令僅限群組使用'); } - const tags = users - .map((u) => u.username ? `@${u.username}` : u.firstName || '') - .filter(Boolean) + const groupId = msg.chat.id; + const users = await getGroupUsers(groupId); + + if (users.length === 0) { + return bot.sendMessage(groupId, '😅 沒有人講過話,無法標記'); + } + + const mentions = users + .filter(u => !!u.username) + .map(u => `@${u.username}`) .join(' '); - bot.sendMessage(chatId, `📣 呼叫所有人:\n${tags}`); + if (!mentions) { + return bot.sendMessage(groupId, '⚠️ 沒有人有公開 username,無法標記'); + } + + bot.sendMessage(groupId, `📣 呼叫所有人:\n${mentions}`); }); bot.on('message', async (msg) => { - const { chat } = msg; - if (chat.type !== 'private') return; + if (!msg.from || !msg.chat || !msg.chat.id || !msg.from.id) return; + if (msg.chat.type !== 'group' && msg.chat.type !== 'supergroup') return; - await User.findOneAndUpdate( - { chatId: chat.id }, - { - chatId: chat.id, - username: chat.username || '', - firstName: chat.first_name || '', - }, - { upsert: true, new: true } - ); + await saveUser(msg.from, msg.chat.id); }); \ No newline at end of file diff --git a/db.js b/db.js index 35eac7d..e842e96 100644 --- a/db.js +++ b/db.js @@ -1,13 +1,42 @@ +// db.js +// 資料庫模組,提供連線與常用操作函式 + const mongoose = require('mongoose'); -require('dotenv').config(); +const User = require('./userModel'); -mongoose.connect(process.env.MONGODB_URI, { - useNewUrlParser: true, - useUnifiedTopology: true, -}); +// 初始化 MongoDB 連線 +function connectDB() { + mongoose.connect(process.env.MONGODB_URI, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); -const db = mongoose.connection; -db.on('error', console.error.bind(console, 'MongoDB 連線錯誤:')); -db.once('open', () => console.log('✅ 已連線到 MongoDB')); + const db = mongoose.connection; + db.on('error', console.error.bind(console, '❌ MongoDB 連線錯誤:')); + db.once('open', () => console.log('✅ 已連線到 MongoDB')); +} -module.exports = mongoose; +// 儲存或更新使用者資訊 +async function saveUser(from, groupId) { + await User.findOneAndUpdate( + { userId: from.id, groupId }, + { + userId: from.id, + username: from.username, + groupId, + lastActive: new Date(), + }, + { upsert: true } + ); +} + +// 取得某群組中有講過話的使用者(依照 username 過濾) +async function getGroupUsers(groupId) { + return await User.find({ groupId }); +} + +module.exports = { + connectDB, + saveUser, + getGroupUsers, +}; diff --git a/models/User.js b/models/User.js deleted file mode 100644 index aced22f..0000000 --- a/models/User.js +++ /dev/null @@ -1,9 +0,0 @@ -const mongoose = require('../db'); - -const userSchema = new mongoose.Schema({ - chatId: { type: Number, required: true, unique: true }, - username: { type: String }, - firstName: { type: String }, -}); - -module.exports = mongoose.model('User', userSchema); diff --git a/userModel.js b/userModel.js new file mode 100644 index 0000000..154fa49 --- /dev/null +++ b/userModel.js @@ -0,0 +1,15 @@ +// userModel.js +// 使用者的資料結構定義 + +const mongoose = require('mongoose'); + +const userSchema = new mongoose.Schema({ + userId: { type: Number, required: true }, // Telegram 使用者 ID + username: String, // 使用者名稱(可選) + groupId: { type: Number, required: true }, // 所在群組 ID + lastActive: Date, // 最後發言時間 +}); + +userSchema.index({ userId: 1, groupId: 1 }, { unique: true }); // 避免重複記錄 + +module.exports = mongoose.model('User', userSchema);