├── fbstate.json ├── .gitignore ├── database ├── threadsData.json ├── usersData.json └── dataProcessing │ ├── models │ └── dataModels.js │ └── handlerData.js ├── scripts ├── events │ ├── src │ │ ├── mediaLeave │ │ │ └── .gitkeep │ │ └── mediaWelcome │ │ │ └── .gitkeep │ ├── checkwarn.js │ ├── leave.js │ ├── logsbot.js │ ├── autoUpdateInfoThread.js │ └── welcome.js ├── cmds │ ├── cache │ │ └── hexcolor.png │ ├── database │ │ ├── rules.png │ │ └── custom.json │ ├── src │ │ ├── image │ │ │ ├── bgweather.jpg │ │ │ └── helpcustomrankcard.jpg │ │ └── font │ │ │ ├── BeVietnamPro-Regular.ttf │ │ │ ├── BeVietnamPro-SemiBold.ttf │ │ │ └── Kanit-SemiBoldItalic.ttf │ ├── money.js │ ├── run.js │ ├── uid.js │ ├── unsend.js │ ├── uptime.js │ ├── adminonly.js │ ├── logsbot.js │ ├── all.js │ ├── reload.js │ ├── sorthelp.js │ ├── leavemsg.js │ ├── welcome.js │ ├── bannedlist.js │ ├── onlyadminbox.js │ ├── refresh.js │ ├── kick.js │ ├── qrcode.js │ ├── backupmongo.js │ ├── setname.js │ ├── prefix.js │ ├── jail.js │ ├── busy.js │ ├── github.js │ ├── batslap.js │ ├── dhbcemoji.js │ ├── voice.js │ ├── configcmd.js │ ├── dhbc.js │ ├── banner2.js │ ├── bannerbw.js │ ├── wakeup.js │ ├── sleep.js │ ├── banner.js │ ├── daily.js │ ├── setbox.js │ ├── setleave.js │ ├── setwelcome.js │ ├── adduser.js │ ├── pairing.js │ ├── notification.js │ ├── count.js │ ├── avatar.js │ ├── rank.js │ ├── callad.js │ ├── wordlink.js │ ├── customrankcard.js │ ├── weather.js │ ├── user.js │ ├── thread.js │ ├── rules.js │ ├── cmd.js │ ├── help.js │ ├── warn.js │ └── ytb.js └── README.txt ├── custom.js ├── configCommands.json ├── bot ├── createFuncMessage.js ├── handlerAction.js ├── handler │ ├── handlerCreateDB.js │ └── handlerEvents.js └── loadAllScript.js ├── .eslintrc.json ├── config.json ├── logger ├── print.js └── loading.js ├── package.json ├── update.js ├── index.js ├── README.md └── versions.json /fbstate.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /database/threadsData.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /database/usersData.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /scripts/events/src/mediaLeave/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/events/src/mediaWelcome/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /custom.js: -------------------------------------------------------------------------------- 1 | module.exports = async ({ globalGoat, client, api }) => { 2 | //custom tại đây (auto restart,..) 3 | }; -------------------------------------------------------------------------------- /scripts/cmds/cache/hexcolor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntkhang03/Goat-Bot/HEAD/scripts/cmds/cache/hexcolor.png -------------------------------------------------------------------------------- /scripts/cmds/database/rules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntkhang03/Goat-Bot/HEAD/scripts/cmds/database/rules.png -------------------------------------------------------------------------------- /scripts/cmds/src/image/bgweather.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntkhang03/Goat-Bot/HEAD/scripts/cmds/src/image/bgweather.jpg -------------------------------------------------------------------------------- /scripts/cmds/src/font/BeVietnamPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntkhang03/Goat-Bot/HEAD/scripts/cmds/src/font/BeVietnamPro-Regular.ttf -------------------------------------------------------------------------------- /scripts/cmds/src/font/BeVietnamPro-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntkhang03/Goat-Bot/HEAD/scripts/cmds/src/font/BeVietnamPro-SemiBold.ttf -------------------------------------------------------------------------------- /scripts/cmds/src/font/Kanit-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntkhang03/Goat-Bot/HEAD/scripts/cmds/src/font/Kanit-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /scripts/cmds/src/image/helpcustomrankcard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntkhang03/Goat-Bot/HEAD/scripts/cmds/src/image/helpcustomrankcard.jpg -------------------------------------------------------------------------------- /database/dataProcessing/models/dataModels.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { Schema } = mongoose; 3 | 4 | const dataModel = new Schema({ 5 | type: String, 6 | data: Object, 7 | prefix: String 8 | }, { 9 | timestamps: true 10 | }); 11 | 12 | module.exports = mongoose.model("database", dataModel); -------------------------------------------------------------------------------- /scripts/cmds/database/custom.json: -------------------------------------------------------------------------------- 1 | { 2 | "wordlink": { 3 | "hightPoint": [ 4 | { 5 | "id": "100010382497517", 6 | "point": 5 7 | }, 8 | { 9 | "id": "100015308170955", 10 | "point": 3 11 | }, 12 | { 13 | "id": "100056335523144", 14 | "point": 0 15 | } 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /scripts/README.txt: -------------------------------------------------------------------------------- 1 | - Không sửa đổi tên tệp, tên lệnh, version của bất kỳ tệp lệnh có sẵn nào nếu không muốn xảy ra lỗi. 2 | - Tắt chế độ tự động cập nhật commands ở file config.json, phần autoUpdateScript sửa thành false. 3 | - Không sửa đổi tên tác giả của bất kỳ tệp lệnh nào. 4 | - Không hỏi admin cách sửa lỗi của bất kỳ tệp lệnh nào bên ngoài. 5 | 6 | >>Thanks for using<< -------------------------------------------------------------------------------- /configCommands.json: -------------------------------------------------------------------------------- 1 | { 2 | "commandBanned": {}, 3 | "envGlobal": { 4 | "tokenFacebook": "6628568379%7Cc1e620fa708a1d5696fb991c1bde5662", 5 | "tts-zalo": "nWaXzdlpZzdMKdcjz1DCQ2xXH5tGxm6r", 6 | "weatherApiKey": "d7e795ae6a0d44aaa8abb1a0a7ac19e4", 7 | "youtube": "AIzaSyBZjYk2QtAvsZjAzUJ5o4qGl8eRl6gr2SA" 8 | }, 9 | "envCommands": { 10 | "daily": { 11 | "rewardDay1": { 12 | "coin": 100, 13 | "exp": 10 14 | } 15 | } 16 | }, 17 | "envEvents": { 18 | "logsbot": { 19 | "logsbot": true 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /scripts/cmds/money.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "money", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "xem số tiền của bạn", 11 | longDescription: "xem số tiền hiện có của bạn", 12 | category: "economy", 13 | guide: "{p}{n}" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ message, usersData, event }) { 19 | const userData = await usersData.getData(event.senderID); 20 | message.reply(`Bạn đang có ${userData.money} coin`); 21 | } 22 | 23 | }; -------------------------------------------------------------------------------- /bot/createFuncMessage.js: -------------------------------------------------------------------------------- 1 | module.exports = (event, api) => { 2 | return { 3 | send: async (form, callback) => await api.sendMessage(form, event.threadID, callback), 4 | reply: async (form, callback) => await api.sendMessage(form, event.threadID, callback, event.messageID), 5 | unsend: async (messageID, callback) => await api.unsendMessage(messageID, callback), 6 | reaction: async (emoji, messageID, callback) => await api.setMessageReaction(emoji, messageID, callback, true) 7 | }; 8 | // Có thể phát sinh những giá trị khác trong handleEvents.js 9 | // Can generate other values in handleEvents.js 10 | }; -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "ecmaVersion": 13 10 | }, 11 | "rules": { 12 | "no-prototype-builtins": 0, 13 | "no-unused-vars": 1, 14 | "comma-dangle": 1, 15 | "no-redeclare": 0, 16 | "prefer-const": 1, 17 | "no-useless-escape": 0, 18 | "no-mixed-spaces-and-tabs": 0, 19 | "semi": 1, 20 | "no-useless-catch": 0, 21 | "no-empty": 0, 22 | "use-isnan": 0, 23 | "no-extra-semi": 1, 24 | "no-async-promise-executor": 0, 25 | "no-unreachable": 1 26 | } 27 | } -------------------------------------------------------------------------------- /scripts/cmds/run.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "run", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "Test code nhanh", 11 | longDescription: "Test code nhanh", 12 | category: "owner", 13 | guide: "{prefix}run <đoạn code cần test>" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ api, globalGoat, args, download, message, client, event, threadsData, usersData, usersModel, threadsModel, configCommands }) { 19 | try { 20 | eval("(async () => {" + args.join(" ") + "})();"); 21 | } 22 | catch (e) { 23 | message.send(`Đã có lỗi xảy ra: ${e.message}`); 24 | } 25 | } 26 | }; -------------------------------------------------------------------------------- /scripts/cmds/uid.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "uid", 3 | version: "1.0.0", 4 | author: { name: "NTKhang", contacts: "" }, 5 | cooldowns: 5, 6 | role: 0, 7 | shortDescription: "Xem id", 8 | longDescription: "Xem id facebook của người dùng", 9 | category: "info", 10 | guide: "{prefix}uid: dùng để xem id facebook của bạn\n{prefix}uid @tag: xem id facebook của những người được tag" 11 | }; 12 | 13 | module.exports = { 14 | config: this.config, 15 | start: function ({ message, event }) { 16 | const { mentions } = event; 17 | if (Object.keys(mentions) != 0) { 18 | let msg = ""; 19 | for (let id in mentions) msg += `${mentions[id].replace("@", "")}: ${id}\n`; 20 | message.reply(msg); 21 | } 22 | else message.reply(event.senderID); 23 | } 24 | }; -------------------------------------------------------------------------------- /scripts/cmds/unsend.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "unsend", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Gỡ tin nhắn của bot", 11 | longDescription: "Gỡ tin nhắn của bot", 12 | category: "info", 13 | guide: "Reply tin nhắn của bot với nội dung {p}{n}" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ message, api, event, args, globalGoat }) { 19 | if (event.type != "message_reply") return message.reply('Vui lòng reply tin nhắn của bot cần gỡ'); 20 | if (event.messageReply.senderID != globalGoat.botID) return message.reply('Không thể gỡ tin nhắn của người khác!!'); 21 | return api.unsendMessage(event.messageReply.messageID); 22 | } 23 | }; -------------------------------------------------------------------------------- /scripts/cmds/uptime.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "uptime", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "xem thời gian bot đã online", 11 | longDescription: "xem thời gian bot đã online", 12 | category: "info", 13 | guide: "{p}{n}" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ message }) { 19 | const timeRun = process.uptime(); 20 | const hours = Math.floor(timeRun / 3600000); 21 | const minutes = Math.floor((timeRun % 3600) / 60); 22 | const seconds = Math.floor(timeRun % 60); 23 | message.reply(`Bot đã hoạt động được ${hours ? hours + "h" : ""}${minutes ? minutes + "p" : ""}${seconds}s\n[ 🐐 | Project Goat Bot ]`); 24 | } 25 | }; -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "email": "", 3 | "password": "", 4 | "adminOnly": false, 5 | "adminBot": [], 6 | "nickNameBot": "", 7 | "prefix": "#", 8 | "database": { 9 | "type": "local", 10 | "uriMongodb": "", 11 | "notes": "type chọn *local* hoặc *mongodb*, nếu chọn mongodb thì điền uri connect mongodb vào phần uriMongodb, còn local sẽ tự lưu file json tại thư mục database" 12 | }, 13 | "SERVER_UPTIME": true, 14 | "autoRefreshFbstate": true, 15 | "restartListenMqtt": { 16 | "allow": true, 17 | "timeRestart": 3600000, 18 | "logNoti": true 19 | }, 20 | "logEvents": { 21 | "eventAndMessage": true, 22 | "read_receipt": false, 23 | "typ": false, 24 | "presence": false 25 | }, 26 | "logsbot": true, 27 | "OptionsApi": { 28 | "forceLogin": true, 29 | "listenEvents": true, 30 | "updatePresence": true, 31 | "listenTyping": true, 32 | "logLevel": "error", 33 | "selfListen": false 34 | } 35 | } -------------------------------------------------------------------------------- /bot/handlerAction.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ api, handlerEvents, handlerCreateDB }) => { 2 | return async (event) => { 3 | const message = require("./createFuncMessage.js")(event, api); 4 | await handlerCreateDB({ event }); 5 | const handlerChat = await handlerEvents({ event, message }); 6 | switch (event.type) { 7 | case "message": 8 | case "message_reply": 9 | case "message_unsend": 10 | await handlerChat.whenChat(); 11 | await handlerChat.whenStart(); 12 | await handlerChat.whenReply(); 13 | break; 14 | case "event": 15 | await handlerChat.handlerEvent(); 16 | break; 17 | case "message_reaction": 18 | await handlerChat.whenReaction(); 19 | break; 20 | case "typ": 21 | await handlerChat.typ(); 22 | break; 23 | case "presence": 24 | await handlerChat.presence(); 25 | break; 26 | case "read_receipt": 27 | await handlerChat.read_receipt(); 28 | break; 29 | default: 30 | break; 31 | } 32 | }; 33 | }; -------------------------------------------------------------------------------- /scripts/cmds/adminonly.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs-extra"); 2 | 3 | this.config = { 4 | name: "adminonly", 5 | version: "1.0.1", 6 | author: { 7 | name: "NTKhang", 8 | contacts: "" 9 | }, 10 | cooldowns: 5, 11 | role: 2, 12 | shortDescription: "bật/tắt chỉ admin sử dụng bot", 13 | longDescription: "bật/tắt chế độ chỉ admin mới có thể sử dụng bot", 14 | category: "owner", 15 | guide: "{prefix}{name} [on|off]" 16 | }; 17 | 18 | module.exports = { 19 | config: this.config, 20 | start: function ({ globalGoat, args, message, client }) { 21 | const { config } = globalGoat; 22 | if (args[0] == "on") { 23 | config.adminOnly = true; 24 | message.reply("Đã bật chế độ chỉ admin mới có thể sử dụng bot"); 25 | fs.writeFileSync(client.dirConfig, JSON.stringify(config, null, 2)); 26 | } 27 | else if (args[0] == "off") { 28 | config.adminOnly = false; 29 | message.reply("Đã tắt chế độ chỉ admin mới có thể sử dụng bot"); 30 | fs.writeFileSync(client.dirConfig, JSON.stringify(config, null, 2)); 31 | } 32 | else return message.reply("Vui lòng chọn chế độ on hoặc off"); 33 | } 34 | }; -------------------------------------------------------------------------------- /scripts/cmds/logsbot.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "logsbot", 3 | version: "1.0.3", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "bật/tắt ghi nhật ký bot", 11 | longDescription: "bật hoặc tắt gửi tin nhắn khi bot được thêm vào nhóm mới hoặc bị kick về admin", 12 | category: "owner", 13 | guide: "{p}{n} on: bật" 14 | + "\n{p}{n} off: tắt" 15 | }; 16 | 17 | module.exports = { 18 | config: this.config, 19 | start: async function ({ args, client, globalGoat, message }) { 20 | const fs = require("fs-extra"); 21 | if (args[0] == "on") globalGoat.configCommands.envEvents.logsbot.logsbot = true; 22 | else if (args[0] == "off") globalGoat.configCommands.envEvents.logsbot.logsbot = false; 23 | else return message.reply("Vui lòng chọn on hoặc off"); 24 | fs.writeFileSync(client.dirConfigCommands, JSON.stringify(globalGoat.configCommands, null, 2)); 25 | message.reply(`Đã ${globalGoat.configCommands.envEvents.logsbot.logsbot ? "bật" : "tắt"} gửi tin nhắn khi bot được thêm vào nhóm mới hoặc bị kick về admin`); 26 | } 27 | }; -------------------------------------------------------------------------------- /scripts/cmds/all.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "all", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 1, 10 | shortDescription: "tag all", 11 | longDescription: "tag tất cả thành viên trong nhóm", 12 | category: "box chat", 13 | guide: "{prefix}{name} [để trống|nội dung]" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ args, threadsData, message, event }) { 19 | const alluser = Object.keys((await threadsData.getData(event.threadID)).members); 20 | const lengthAllUser = alluser.length; 21 | const mentions = []; 22 | let body = args.join(" ") || "@all"; 23 | let lengthbody = body.length; 24 | let i = 0; 25 | for (const uid of alluser) { 26 | let fromIndex = 0; 27 | if (lengthbody < lengthAllUser) { 28 | body += body[lengthbody - 1]; 29 | lengthbody++; 30 | } 31 | if (body.slice(0, i).lastIndexOf(body[i]) != -1) fromIndex = i; 32 | mentions.push({ tag: body[i], id: uid, fromIndex }); 33 | i++; 34 | } 35 | message.reply({ body, mentions }); 36 | } 37 | }; -------------------------------------------------------------------------------- /scripts/cmds/reload.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "reload", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "reload file config", 11 | longDescription: "load lại file config.json hoặc configComands.json vào biến globalGoat", 12 | guide: "{p}{n} [config | cmds]", 13 | category: "owner" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ globalGoat, args, threadsData, message, event }) { 19 | const content = (args[0] || "").toLowerCasee(); 20 | if (["config"].includes(content)) { 21 | delete require.cache[require.resolve(client.dirConfig)]; 22 | globalGoat.config = require(client.dirConfig); 23 | return message.reply("Đã tải lại config.json"); 24 | } 25 | else if (["cmds", "cmd", "command", "commands"].includes(content)) { 26 | delete require.cache[require.resolve(client.dirConfigCommands)]; 27 | globalGoat.configComands = require(client.dirConfig); 28 | return message.reply("Đã tải lại configComands.json"); 29 | } 30 | else return message.SyntaxError(); 31 | } 32 | }; -------------------------------------------------------------------------------- /logger/print.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | 3 | module.exports = (text, type) => { 4 | console.log(chalk.cyan(`» ${type} «`), text); 5 | }; 6 | 7 | module.exports.error = (text, type) => { 8 | console.log(chalk.bold.hex("#ff0000").bold(`» ${type} «`), text); 9 | }; 10 | 11 | module.exports.err = (text, type) => { 12 | console.log(chalk.bold.hex("#ff0000").bold(`» ${type} «`), text); 13 | }; 14 | 15 | module.exports.warn = (text, type) => { 16 | console.log(chalk.bgYellow.hex("#000000").bold(`» ${type} «`), text); 17 | }; 18 | 19 | module.exports.master = (text, type) => { 20 | console.log(chalk.hex("#ff5208")(`» ${type} «`), text); 21 | }; 22 | 23 | module.exports.blue = (text, type) => { 24 | console.log(chalk.hex("#0568f2").bold(`» ${type} «`), text); 25 | }; 26 | 27 | module.exports.green = (text, type) => { 28 | console.log(chalk.green.bold(`» ${type} «`), text); 29 | }; 30 | 31 | module.exports.pink = (text, type) => { 32 | console.log(chalk.hex("#f205c3").bold(`» ${type} «`), text); 33 | }; 34 | module.exports.purple = (text, type) => { 35 | console.log(chalk.hex("#a700ffff").bold(`» ${type} «`), text); 36 | }; 37 | -------------------------------------------------------------------------------- /scripts/cmds/sorthelp.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "sorthelp", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Tạo ảnh bìa", 11 | longDescription: "Tạo ảnh bìa đẹp", 12 | category: "image", 13 | guide: "{prefix}{n} [name|category]\nVí dụ: {p}{n} name" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ message, event, args, threadsData }) { 19 | if (args[0] == "name") { 20 | threadsData.setData(event.threadID, { sortHelp: "name" }, (err) => { 21 | if (err) return message.reply("Đã xảy ra lỗi vui lòng thử lại sau" + err.stack); 22 | else message.reply("Đã lưu cài đặt sắp xếp danh sách help theo thứ tự chữ cái"); 23 | }); 24 | } 25 | else if (args[0] == "category") { 26 | threadsData.setData(event.threadID, { sortHelp: "category" }, (err) => { 27 | if (err) return message.reply("Đã xảy ra lỗi vui lòng thử lại sau" + err.stack); 28 | else message.reply("Đã lưu cài đặt sắp xếp danh sách help theo thứ tự nhóm"); 29 | }); 30 | } 31 | else message.SyntaxError(); 32 | } 33 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "goat-bot", 3 | "version": "1.4.39", 4 | "description": "A simple Bot chat messenger made by NTKhang", 5 | "main": "index.js", 6 | "author": "NTKhang", 7 | "scripts": { 8 | "start": "node index.js", 9 | "update": "node update.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/ntkhang03/Goat-Bot.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/ntkhang03/Goat-Bot/issues" 17 | }, 18 | "keywords": [ 19 | "bot-chat-messenger", 20 | "bot-messenger", 21 | "bot-chat-goat", 22 | "GoatBot Chat Bot" 23 | ], 24 | "dependencies": { 25 | "axios": "^0.21.1", 26 | "body-parser": "^1.19.0", 27 | "canvas": "", 28 | "chalk": "^4.1.1", 29 | "child_process": "^1.0.2", 30 | "crypto": "", 31 | "express": "^4.17.1", 32 | "fb-chat-api": "latest", 33 | "fb-tools": "", 34 | "fs-extra": "^10.0.0", 35 | "moment-timezone": "^0.5.33", 36 | "mongoose": "^5.13.7", 37 | "path": "^0.12.7", 38 | "querystring": "^0.2.1", 39 | "readline": "^1.3.0", 40 | "request": "^2.88.2", 41 | "uuid": "3.3.2", 42 | "ytdl-core": "^4.11.1" 43 | }, 44 | "homepage": "https://github.com/ntkhang03/Goat-Bot#readme" 45 | } -------------------------------------------------------------------------------- /scripts/cmds/leavemsg.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "leavemsg", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "bật/tắt gửi tin nhắn tạm biệt", 11 | longDescription: "bật hoặc tắt gửi nhắn tạm biệt khi có thành viên out hoặc bị kick khỏi nhóm bạn", 12 | category: "custom", 13 | guide: "{p}{n} on: bật" 14 | + "\n{p}{n} off: tắt" 15 | }; 16 | 17 | module.exports = { 18 | config: this.config, 19 | start: async function ({ args, threadsData, globalGoat, message, event }) { 20 | const { threadID } = event; 21 | const data = (await threadsData.getData(threadID)).data; 22 | 23 | if (args[0] == "on") data.sendLeaveMessage = true; 24 | else if (args[0] == "off") data.sendLeaveMessage = false; 25 | else message.reply("Vui lòng chọn on hoặc off"); 26 | 27 | await threadsData.setData(threadID, { 28 | data 29 | }, (err, info) => { 30 | if (err) return message.reply(`Đã xảy ra lỗi, vui lòng thử lại sau: ${err.name}: ${err.message}`); 31 | message.reply(`Đã ${data.sendLeaveMessage ? "bật" : "tắt"} gửi tin nhắn tạm biệt khi có thành viên out hoặc bị kick khỏi nhóm bạn`); 32 | }); 33 | } 34 | }; -------------------------------------------------------------------------------- /scripts/cmds/welcome.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "welcome", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "bật/tắt gửi tin nhắn chào mừng", 11 | longDescription: "bật hoặc tắt gửi nhắn chào mừng khi có thành viên mới tham gia nhóm chat của bạn", 12 | category: "custom", 13 | guide: "{p}{n} on: bật" 14 | + "\n{p}{n} off: tắt" 15 | }; 16 | 17 | module.exports = { 18 | config: this.config, 19 | start: async function ({ args, threadsData, globalGoat, message, event, role }) { 20 | const { threadID } = event; 21 | const data = (await threadsData.getData(threadID)).data; 22 | 23 | if (args[0] == "on") data.sendWelcomeMessage = true; 24 | else if (args[0] == "off") data.sendWelcomeMessage = false; 25 | else message.reply("Vui lòng chọn on hoặc off"); 26 | 27 | await threadsData.setData(threadID, { 28 | data 29 | }, (err, info) => { 30 | if (err) return message.reply(`Đã xảy ra lỗi, vui lòng thử lại sau: ${err.name}: ${err.message}`); 31 | message.reply(`Đã ${data.sendWelcomeMessage ? "bật" : "tắt"} gửi tin nhắn chào mừng khi có thành viên mới tham gia nhóm chat của bạn`); 32 | }); 33 | } 34 | }; -------------------------------------------------------------------------------- /scripts/events/checkwarn.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | config: { 3 | name: "checkwarn", 4 | version: "1.0.0", 5 | type: ["log:subscribe"], 6 | author: { 7 | name: "NTKhang", 8 | contacts: "" 9 | }, 10 | }, 11 | start: async ({ threadsData, message, event, globalGoat, api, client }) => { 12 | const { threadID } = event; 13 | const { data, adminIDs } = await threadsData.getData(event.threadID); 14 | if (!data.warn) return; 15 | const { banned } = data.warn; 16 | const { addedParticipants } = event.logMessageData; 17 | for (const user of addedParticipants) { 18 | if (banned.includes(user.userFbId)) { 19 | message.send({ 20 | body: `Thành viên này đã bị cảnh cáo đủ 3 lần trước đó và bị ban khỏi box\nName: ${user.fullName}\nUid: ${user.userFbId}\nĐể gỡ ban vui lòng sử dụng lệnh "${client.getPrefix(threadID)}warn unban " (với uid là uid của người muốn gỡ ban)`, 21 | mentions: [{ 22 | tag: user.fullName, 23 | id: user.userFbId 24 | }] 25 | }, function () { 26 | api.removeUserFromGroup(user.userFbId, threadID, (err) => { 27 | if (err) return message.send(`Bot cần quyền quản trị viên để kick thành viên bị ban`); 28 | }); 29 | }); 30 | } 31 | } 32 | } 33 | }; -------------------------------------------------------------------------------- /logger/loading.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | 3 | module.exports = (text, type) => { 4 | process.stderr.write(chalk.cyan(`\r» ${type} « `) + text); 5 | }; 6 | 7 | module.exports.error = (text, type) => { 8 | process.stderr.write(chalk.bold.hex("#ff0000").bold(`\r» ${type} « `) + text); 9 | }; 10 | 11 | module.exports.err = (text, type) => { 12 | process.stderr.write(chalk.bold.hex("#ff0000").bold(`\r» ${type} « `) + text); 13 | }; 14 | 15 | module.exports.warn = (text, type) => { 16 | process.stderr.write(chalk.bgYellow.hex("#000000").bold(`\r» ${type} « `) + text); 17 | }; 18 | 19 | module.exports.master = (text, type) => { 20 | process.stderr.write(chalk.hex("#ff5208")(`\r» ${type} « `) + text); 21 | }; 22 | 23 | module.exports.blue = (text, type) => { 24 | process.stderr.write(chalk.hex("#0568f2").bold(`\r» ${type} « `) + text); 25 | }; 26 | 27 | module.exports.green = (text, type) => { 28 | process.stderr.write(chalk.green.bold(`\r» ${type} « `) + text); 29 | }; 30 | 31 | module.exports.pink = (text, type) => { 32 | process.stderr.write(chalk.hex("#f205c3").bold(`\r» ${type} « `) + text); 33 | }; 34 | 35 | module.exports.purple = (text, type) => { 36 | process.stderr.write(chalk.hex("#a700ffff").bold(`\r» ${type} « `) + text); 37 | }; 38 | -------------------------------------------------------------------------------- /scripts/cmds/bannedlist.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "bannedlist", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "xem danh sách nhóm/người dùng bị cấm", 11 | longDescription: "xem danh sách nhóm/người dùng bị cấm", 12 | category: "owner", 13 | guide: "{p}{n} [thread|user]", 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ message, args, usersData, threadsData }) { 19 | let target, type; 20 | if (["thread", "-t"].includes(args[0])) { 21 | target = await threadsData.getAll(); 22 | type = "nhóm"; 23 | } 24 | else if (["user", "-u"].includes(args[0])) { 25 | target = await usersData.getAll(); 26 | type = "người dùng"; 27 | } 28 | else return message.SyntaxError(); 29 | 30 | const bannedList = target.filter(item => item.banned.status); 31 | const msg = bannedList.reduce((i, item) => i += `Name: ${item.name}` 32 | + `\nID: ${item.id}` 33 | + `\nReason: ${item.banned.reason}` 34 | + `\nTime: ${item.banned.date}\n\n`, ""); 35 | 36 | message.reply(msg ? `Hiện tại có ${bannedList.length} ${type} đã bị cấm sử dụng bot:\n\n${msg}` : `Hiện tại chưa có ${type} nào bị cấm sử dụng bot`); 37 | } 38 | }; -------------------------------------------------------------------------------- /scripts/cmds/onlyadminbox.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs-extra"); 2 | this.config = { 3 | name: "onlyadminbox", 4 | version: "1.0.0", 5 | author: { 6 | name: "NTKhang", 7 | contacts: "" 8 | }, 9 | cooldowns: 5, 10 | role: 1, 11 | shortDescription: "bật/tắt chỉ admin box sử dụng bot", 12 | longDescription: "bật/tắt chế độ chỉ quản trị viên nhóm mới có thể sử dụng bot", 13 | category: "box chat", 14 | guide: "{prefix}{name} [on|off]" 15 | }; 16 | 17 | module.exports = { 18 | config: this.config, 19 | start: async function ({ globalGoat, args, message, event, client, threadsData }) { 20 | const threadData = await threadsData.getData(event.threadID); 21 | if (args[0] == "on") { 22 | threadsData.setData(event.threadID, { 23 | onlyAdminBox: true 24 | }, (e) => { 25 | if (e) return message.reply(`Đã xảy ra lỗi ${e.name}: ${e.message}`); 26 | message.reply("Đã bật chế độ chỉ quản trị viên nhóm mới có thể sử dụng bot"); 27 | }); 28 | } 29 | else if (args[0] == "off") { 30 | threadsData.setData(event.threadID, { 31 | onlyAdminBox: false 32 | }, (e) => { 33 | if (e) return message.reply(`Đã xảy ra lỗi ${e.name}: ${e.message}`); 34 | message.reply("Đã tắt chế độ chỉ quản trị viên nhóm mới có thể sử dụng bot"); 35 | }); 36 | } 37 | else return message.reply("Vui lòng chọn chế độ on hoặc off"); 38 | } 39 | }; -------------------------------------------------------------------------------- /scripts/cmds/refresh.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "refresh", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "Cập nhật dữ liệu của bot", 11 | longDescription: "Cập nhật dữ liệu của tất cả người dùng hoặc thread", 12 | category: "owner", 13 | guide: "{p}{n} [user | thread | all]" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ args, usersData, threadsData, message, api }) { 19 | 20 | async function refreshUsers() { 21 | const allUser = await usersData.getAll(); 22 | for (const user of allUser) await usersData.refreshInfo(user.id); 23 | return message.reply(`Đã cập nhật dữ liệu của ${allUser.length} người dùng`); 24 | } 25 | async function refreshThreads() { 26 | const allThread = (await api.getThreadList(999, null, ["INBOX"])).filter(item => item.isGroup); 27 | for (const thread of allThread) await threadsData.refreshInfo(thread.threadID); 28 | return message.reply(`Đã cập nhật dữ liệu của ${allThread.length} nhóm`); 29 | } 30 | 31 | if (args[0] == "user") await refreshUsers(); 32 | else if (args[0] == "thread") await refreshThreads(); 33 | else if (args[0] == "all") { 34 | await refreshUsers(); 35 | await refreshThreads(); 36 | } 37 | else return message.SyntaxError(); 38 | } 39 | }; -------------------------------------------------------------------------------- /scripts/cmds/kick.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | config: { 3 | name: "kick", 4 | version: "1.0", 5 | author: "NTKhang", 6 | countDown: 5, 7 | role: 1, 8 | shortDescription: "Kick thành viên", 9 | longDescription: "Kick thành viên khỏi box chat", 10 | category: "box chat", 11 | guide: "{p}{n} @tags: dùng để kick những người được tag" 12 | }, 13 | 14 | start: async function ({ message, event, args, threadsData, api }) { 15 | const { adminIDs } = await threadsData.getData(event.threadID); 16 | if (!adminIDs.includes(api.getCurrentUserID())) 17 | return message.reply("Vui lòng thêm quản trị viên cho bot trước khi sử dụng tính năng này"); 18 | async function kickAndCheckError(uid) { 19 | try { 20 | await api.removeUserFromGroup(uid, event.threadID); 21 | } 22 | catch (e) { 23 | message.reply("Đã có lỗi xảy ra, hãy thêm bot làm quản trị viên và thử lại sau"); 24 | return "ERROR"; 25 | } 26 | } 27 | if (!args[0]) { 28 | if (!event.messageReply) 29 | return message.SyntaxError(); 30 | await kickAndCheckError(event.messageReply.senderID); 31 | } 32 | else { 33 | const uids = Object.keys(event.mentions); 34 | if (uids.length === 0) 35 | return message.SyntaxError(); 36 | if (await kickAndCheckError(uids.shift()) === "ERROR") 37 | return; 38 | for (const uid of uids) 39 | api.removeUserFromGroup(uid, event.threadID); 40 | } 41 | } 42 | }; -------------------------------------------------------------------------------- /scripts/cmds/qrcode.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "qrcode", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Tạo mã qr code", 11 | longDescription: "Tạo mã qr code với nội dung bạn nhập vào", 12 | category: "image", 13 | guide: "{p}{n} " 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: function ({ message, args }) { 19 | const axios = require("axios"); 20 | const fs = require("fs-extra"); 21 | 22 | if (!args[0]) return message.reply("Vui lòng nhập vào nội dung bạn muốn tạp qr code"); 23 | axios.get("https://api.qrcode-monkey.com//qr/custom?", { 24 | params: { 25 | "data": args.join(" "), 26 | "config": { 27 | "body": "square", 28 | "eye": "frame3", 29 | "eyeBall": "ball0", 30 | "erf1": ["fv"], 31 | "erf2": ["fv", "fh"] 32 | }, 33 | "size": 1000, 34 | "file": "png" 35 | }, 36 | responseType: "arraybuffer" 37 | }) 38 | .then(result => { 39 | const pathSave = __dirname + "/cache/qrcode.png"; 40 | fs.writeFileSync(pathSave, Buffer.from(result.data)); 41 | message.reply({ 42 | attachment: fs.createReadStream(pathSave) 43 | }, () => fs.unlinkSync(pathSave)); 44 | }) 45 | .catch(() => { 46 | return message.reply("Rất tiếc. Đã xảy ra lỗi vui lòng thử lại sau"); 47 | }); 48 | 49 | } 50 | }; -------------------------------------------------------------------------------- /scripts/cmds/backupmongo.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "backupmongo", 3 | version: "2.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "Convert mongodb to json", 11 | longDescription: "Sao lưu lại dữ liệu trên mongodb về json", 12 | category: "owner", 13 | guide: "{prefix}backupmongo" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ message, event, globalGoat }) { 19 | const fs = require("fs-extra"); 20 | if (globalGoat.config.database.type != "mongodb") return message.send("Bạn phải sử dụng cơ sở dữ liệu mongdb mới có thể dùng lệnh này"); 21 | const pathThreads = __dirname + "/cache/dataThreads.json"; 22 | const pathUsers = __dirname + "/cache/dataUsers.json"; 23 | const dataModels = require("../../database/dataProcessing/models/dataModels.js"); 24 | 25 | const dataAllThreads = (await dataModels.find({ type: "thread" }))[0].data || {}; 26 | const dataAllUsers = (await dataModels.find({ type: "user" }))[0].data || {}; 27 | 28 | fs.writeFileSync(pathThreads, JSON.stringify(dataAllThreads, null, 2)); 29 | fs.writeFileSync(pathUsers, JSON.stringify(dataAllUsers, null, 2)); 30 | 31 | const sendFile = []; 32 | sendFile.push(fs.createReadStream(pathThreads)); 33 | sendFile.push(fs.createReadStream(pathUsers)); 34 | message.reply({ 35 | attachment: sendFile 36 | }, () => { 37 | fs.unlinkSync(pathThreads); 38 | fs.unlinkSync(pathUsers); 39 | }); 40 | } 41 | 42 | }; -------------------------------------------------------------------------------- /scripts/cmds/setname.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "setname", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "đổi biệt danh của bạn/người tag", 11 | longDescription: "đổi biệt danh của bạn hoặc người được tag", 12 | category: "box chat", 13 | guide: "{prefix}{name} [|để trống]" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ args, threadsData, message, event, api }) { 19 | let uid, nickname; 20 | if (event.type == "message_reply") { 21 | uid = event.messageReply.senderID; 22 | nickname = args.join(" "); 23 | } 24 | else if (Object.keys(event.mentions)[0]) { 25 | uid = Object.keys(event.mentions)[0]; 26 | nickname = args.join(" ").replace(event.mentions[uid], ""); 27 | } 28 | else { 29 | uid = event.senderID; 30 | nickname = args.join(" "); 31 | } 32 | 33 | api.changeNickname(nickname || "", event.threadID, uid, async (err) => { 34 | if (err) return; 35 | const data = await threadsData.getData(event.threadID); 36 | const members = data.members; 37 | if (!members[uid]) { 38 | members[uid] = { 39 | id: uid, 40 | name: (await api.getUserInfo(uid))[uid].name, 41 | nickname: nickname || null, 42 | inGroup: true, 43 | count: 0 44 | }; 45 | } 46 | else { 47 | members[uid].nickname = nickname; 48 | } 49 | await threadsData.setData(event.threadID, { members }); 50 | }); 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /scripts/cmds/prefix.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "prefix", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Xem hoặc đổi prefix", 11 | longDescription: "Xem hoặc đổi prefix của nhóm bạn", 12 | category: "box chat", 13 | guide: "{prefix}prefix : đổi prefix của nhóm" 14 | + "\nprefix: xem prefix hiện tại" 15 | + "\n" 16 | + "\nVí dụ đổi prefix: {prefix}prefix !", 17 | priority: 1 18 | }; 19 | 20 | module.exports = { 21 | config: this.config, 22 | start: async function ({ globalGoat, threadsData, message, args, event }) { 23 | if (!args[0]) { 24 | const prefix = (await threadsData.getData(event.threadID)).prefix || globalGoat.config.data.prefix; 25 | return message.reply(`> Prefix của nhóm bạn: ${prefix}\n> Prefix của hệ thống: ${globalGoat.config.prefix}\n> Để thay đổi prefix hãy nhập ${prefix} `); 26 | } 27 | await threadsData.setData(event.threadID, { prefix: args[0] }, (err, info) => { 28 | if (err) return message.reply(err.stack); 29 | return message.reply(`Đã đổi prefix của nhóm bạn thành \`${info.prefix}\``); 30 | }); 31 | }, 32 | 33 | whenChat: async ({ threadsData, message, args, event, setup, globalGoat }) => { 34 | if (event.body && event.body.toLowerCase() == "prefix") { 35 | return message.reply(`Prefix của nhóm bạn: ${(await threadsData.getData(event.threadID)).prefix || globalGoat.config.prefix}\nPrefix của hệ thống: ${globalGoat.config.prefix}`); 36 | } 37 | } 38 | }; -------------------------------------------------------------------------------- /scripts/cmds/jail.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "jail", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "create image jail", 11 | longDescription: "create image jail", 12 | category: "image", 13 | envGlobal: { 14 | tokenFacebook: "6628568379%7Cc1e620fa708a1d5696fb991c1bde5662" 15 | }, 16 | guide: "{p}{n} [@tag|để trống]" 17 | }; 18 | 19 | module.exports = { 20 | config: this.config, 21 | start: async function ({ globalGoat, args, message, event }) { 22 | const axios = require("axios"); 23 | const fs = require("fs-extra"); 24 | const pathSave = __dirname + `/jail${Date.now()}.png`; 25 | const { tokenFacebook } = globalGoat.configCommands.envGlobal; 26 | const { senderID, mentions } = event; 27 | const uid = Object.keys(mentions).length > 0 ? Object.keys(mentions)[0] : senderID; 28 | const avatar = `https://graph.facebook.com/${uid}/picture?type=large&width=500&height=500&access_token=${tokenFacebook}`; 29 | axios.get(`https://goatbot.up.railway.app/taoanhdep/jail`, { 30 | params: { 31 | image: avatar, 32 | apikey: "ntkhang" 33 | }, 34 | responseType: "arraybuffer" 35 | }) 36 | .then(data => { 37 | fs.writeFileSync(pathSave, Buffer.from(data.data)); 38 | message.reply({ 39 | attachment: fs.createReadStream(pathSave) 40 | }, () => fs.unlinkSync(pathSave)); 41 | }) 42 | .catch(error => { 43 | const err = JSON.parse(error.response.data.toString()); 44 | message.reply(`Đã xảy ra lỗi ${err.error}: ${err.message}`); 45 | }); 46 | } 47 | }; -------------------------------------------------------------------------------- /scripts/cmds/busy.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "busy", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "bật chế độ không làm phiền", 11 | longDescription: "bật chế độ không làm phiền, khi bạn được tag bot sẽ thông báo", 12 | category: "box chat", 13 | guide: "{prefix}{name} [để trống|lý do]" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ args, client, message, event }) { 19 | const { senderID } = event; 20 | if (!client.busyList) client.busyList = {}; 21 | 22 | const reason = args.join(" ") || null; 23 | client.busyList[senderID] = reason; 24 | 25 | return message.reply(`Đã bật chế độ không làm phiền${reason ? ` với lý do: ${reason}` : ""}`); 26 | }, 27 | 28 | 29 | whenChat: async ({ event, client, message }) => { 30 | if (!client.busyList) return; 31 | const { senderID, mentions } = event; 32 | const { busyList } = client; 33 | 34 | if (busyList[senderID]) { 35 | delete busyList[senderID]; 36 | const text = "Chào mừng bạn đã quay trở lại =)"; 37 | message.reply({ 38 | body: text, 39 | mentions: [{ 40 | id: senderID, 41 | tag: text 42 | }] 43 | }); 44 | } 45 | 46 | if (!mentions || Object.keys(mentions).length == 0) return; 47 | const arrayMentions = Object.keys(mentions); 48 | 49 | for (const userID of arrayMentions) { 50 | if (Object.keys(client.busyList).includes(userID)) 51 | return message.reply(`Hiện tại người dùng ${mentions[userID].replace("@", "")} đang bận${busyList[userID] ? ` với lý do: ${busyList[userID]}` : ""}`); 52 | } 53 | } 54 | }; -------------------------------------------------------------------------------- /scripts/cmds/github.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "github", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Xem thông tin user github", 11 | longDescription: "Xem thông tin người dùng github công khai bằng id", 12 | category: "other" 13 | }; 14 | 15 | module.exports = { 16 | config: this.config, 17 | start: async function ({ api, globalGoat, args, message, event, download }) { 18 | if (!args[0]) return api.sendMessage(`username github không được để trống!`, event.threadID, event.messageID); 19 | const moment = require("moment"); 20 | const axios = require("axios"); 21 | const fs = require("fs-extra"); 22 | 23 | axios.get(`https://api.github.com/users/${encodeURI(args.join(' '))}`) 24 | .then(async body => { 25 | body = body.data; 26 | if (body.message) return sendandrep(`Không tìm thấy người dùng github mang id ${args.join(" ")}!`); 27 | let { login, avatar_url, name, id, html_url, public_repos, followers, following, location, created_at, bio } = body; 28 | const info = `>> ${login} Information! <<\n\nUsername: ${login}\nID: ${id}\nBio: ${bio || "No Bio"}\nPublic Repositories: ${public_repos || "None"}\nFollowers: ${followers}\nFollowing: ${following}\nLocation: ${location || "No Location"}\nAccount Created: ${moment(created_at).tz("Asia/Ho_Chi_minh").format("DD/MM/YYYY HH:mm:ss")} (UTC +7)\nAvatar:`; 29 | await download(avatar_url, __dirname + "/cache/avatargithub.png"); 30 | 31 | message.reply({ attachment: fs.createReadStream(__dirname + "/cache/avatargithub.png"), body: info }, () => fs.unlinkSync(__dirname + "/cache/avatargithub.png")); 32 | }); 33 | } 34 | }; -------------------------------------------------------------------------------- /scripts/cmds/batslap.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "batslap", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "batman slap", 11 | longDescription: "batman slap user mention or you", 12 | category: "image", 13 | envGlobal: { 14 | tokenFacebook: "6628568379%7Cc1e620fa708a1d5696fb991c1bde5662" 15 | } 16 | }; 17 | 18 | module.exports = { 19 | config: this.config, 20 | start: async function ({ api, globalGoat, args, message, event, download }) { 21 | const fs = require("fs-extra"); 22 | const axios = require("axios"); 23 | const { senderID, mentions } = event; 24 | const pathBatSlap = __dirname + `/cache/batslap${Date.now()}.jpg`; 25 | const { tokenFacebook } = globalGoat.configCommands.envGlobal; 26 | 27 | function linkAvatar(uid) { 28 | return encodeURIComponent(`https://graph.facebook.com/${uid}/picture?type=large&width=500&height=500&access_token=${tokenFacebook}`); 29 | } 30 | 31 | const targetId = Object.keys(mentions).length > 0 ? Object.keys(mentions)[0] : senderID; 32 | let imgBuffer; 33 | try { 34 | imgBuffer = (await axios.get(`https://goatbot.up.railway.app/taoanhdep/batslap?apikey=ntkhang&author=${linkAvatar(senderID)}&target=${linkAvatar(targetId)}`, { 35 | responseType: "arraybuffer" 36 | })).data; 37 | } 38 | catch (error) { 39 | let err; 40 | if (error.response) err = JSON.parse(error.response.data.toString()); 41 | else err = error; 42 | return message.reply(`Đã xảy ra lỗi ${err.error} ${err.message}`); 43 | } 44 | fs.writeFileSync(pathBatSlap, Buffer.from(imgBuffer)); 45 | message.reply({ attachment: fs.createReadStream(pathBatSlap) }, () => fs.unlinkSync(pathBatSlap)); 46 | } 47 | }; -------------------------------------------------------------------------------- /scripts/cmds/dhbcemoji.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "dhbcemoji", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "game đuổi hình bắt chữ emoji (demo)", 11 | longDescription: "chơi game đuổi hình bắt chữ phiên bản emoji (demo)", 12 | category: "game", 13 | guide: "{p}{n}" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ globalGoat, message, event, download }) { 19 | const axios = require("axios"); 20 | const fs = require("fs-extra"); 21 | const datagame = (await axios.get("https://goatbot.up.railway.app/api/duoihinhbatchuemoji")).data; 22 | const random = datagame.data; 23 | message.reply(`Hãy reply tin nhắn này với câu trả lời\n${random.emoji1}${random.emoji2}\n${random.wordcomplete.replace(/\S/g, "█ ")}`, 24 | (err, info) => globalGoat.whenReply[info.messageID] = { 25 | messageID: info.messageID, 26 | nameCmd: this.config.name, 27 | author: event.senderID, 28 | wordcomplete: random.wordcomplete 29 | }); 30 | }, 31 | 32 | whenReply: ({ message, Reply, event, globalGoat }) => { 33 | let { author, wordcomplete, messageID } = Reply; 34 | if (event.senderID != author) return message.reply("Bạn không phải là người chơi của câu hỏi này"); 35 | function formatText(text) { 36 | return text.normalize("NFD") 37 | .toLowerCase() 38 | .replace(/[\u0300-\u036f]/g, "") 39 | .replace(/đ/g, "d") 40 | .replace(/Đ/g, "D"); 41 | } 42 | 43 | (formatText(event.body) == formatText(wordcomplete)) ? message.reply("Chúc mừng bạn đã trả lời đúng") : message.reply(`Opps, Sai rồi`); 44 | //message.reply(`Sai rồi, đáp án đúng là: ${wordcomplete}`); 45 | delete globalGoat.whenReply[messageID]; 46 | } 47 | }; -------------------------------------------------------------------------------- /scripts/cmds/voice.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "voice", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "text to speech ", 11 | longDescription: "dịch văn bản sang giọng nói", 12 | category: "media", 13 | envGlobal: { 14 | "tts-zalo": "nWaXzdlpZzdMKdcjz1DCQ2xXH5tGxm6r" 15 | } 16 | }; 17 | 18 | module.exports = { 19 | config: this.config, 20 | start: async function ({ api, args, message, event, download, globalGoat }) { 21 | const fs = require("fs-extra"); 22 | const axios = require('axios'); 23 | const qs = require('querystring'); 24 | const apikey = globalGoat.configCommands.envGlobal["tts-zalo"]; 25 | 26 | let content = (event.type == "message_reply") ? event.messageReply.body : args.join(" "); 27 | if (!content) return api.sendMessage("Vui lòng nhập một đoạn văn bản hoặc reply một tin nhắn!", event.threadID, event.messageID); 28 | 29 | const url = "https://api.zalo.ai/v1/tts/synthesize"; 30 | const path = __dirname + "/cache/texttospeech.mp3"; 31 | const datapush = { 32 | input: content.replace(/\n/g, " "), 33 | encode_type: 1, 34 | speaker_id: 3// 0 | 1 | 2 | 3 35 | }; 36 | 37 | const result = await axios.post(url, qs.stringify(datapush), { 38 | headers: { 39 | apikey 40 | } 41 | }); 42 | const link = result.data.data.url; 43 | 44 | let getfile; 45 | let ERROR = true; 46 | while (ERROR == true) { 47 | try { 48 | getfile = (await axios.get(link, { responseType: "arraybuffer" })).data; 49 | ERROR = false; 50 | } 51 | catch (e) { 52 | continue; 53 | } 54 | } 55 | fs.writeFileSync(path, Buffer.from(getfile)); 56 | message.reply({ attachment: fs.createReadStream(path) }, () => fs.unlink(path)); 57 | } 58 | }; -------------------------------------------------------------------------------- /scripts/cmds/configcmd.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "configcmd", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "edit config bot", 11 | longDescription: "chỉnh sửa file configComands.json", 12 | category: "owner", 13 | guide: "{p}{n} api " 14 | + "\n{p}{n} [cmd | command] " 15 | + "\n{p}{n} event " 16 | }; 17 | 18 | module.exports = { 19 | config: this.config, 20 | start: async ({ globalGoat, args, message, client, event }) => { 21 | const fs = require("fs-extra"); 22 | try { 23 | const configCommands = globalGoat.configCommands; 24 | const content = args[0].toLowerCase(); 25 | if (content == "api") { 26 | const key = args[1]; 27 | const value = args[2]; 28 | configCommands.API[key] = value; 29 | } 30 | else if (["cmd", "command", "commands"].includes(content)) { 31 | const name = args[1]; 32 | const key = args[2]; 33 | const value = args[3]; 34 | !configCommands.configCmds[name] ? globalGoat.configCmd[name] = {} : ""; 35 | configCommands.configCmds[name][key] = value; 36 | } 37 | else if (["event", "evt"].includes(content)) { 38 | const name = args[1]; 39 | const key = args[2]; 40 | const value = args[3]; 41 | !configCommands.configEvent[name] ? configCommands.configCommands[name] = {} : ""; 42 | configCommands.configEvent[name][key] = value; 43 | } 44 | else return message.SyntaxError(); 45 | 46 | fs.writeFileSync(client.dirConfigCommands, JSON.stringify(configCommands, null, 2)); 47 | message.reply(`Đã cấu hình lại file configCommands`); 48 | } 49 | catch (err) { 50 | message.reply(`Đã xảy ra lỗi ${err.name}: ${err.message}`); 51 | } 52 | } 53 | }; -------------------------------------------------------------------------------- /bot/handler/handlerCreateDB.js: -------------------------------------------------------------------------------- 1 | module.exports = function ({ globalGoat, usersData, threadsData, client }) { 2 | const print = globalGoat.print; 3 | const CREATEDATA = async function ({ event }) { 4 | try { 5 | const { threadID, isGroup } = event; 6 | const senderID = event.senderID || event.author || event.userID; 7 | // —————————————— CREATE THREAD DATA —————————————— // 8 | if (!client.allThreadData[threadID] && isGroup && !isNaN(threadID) && threadID != 0) { 9 | if (client.database.threadBusy) return print.warn("DATABASE BUSY", "DATABASE"); 10 | client.database.threadBusy = true; 11 | try { 12 | await threadsData.createData(threadID); 13 | client.database.threadBusy = false; 14 | print(`New Thread: ${threadID} | ${client.allThreadData[threadID].name} | ${globalGoat.config.database.type}`, "DATABASE"); 15 | } 16 | catch (e) { 17 | client.database.threadBusy = false; 18 | print.err(`Không thể ghi nhóm có id '${threadID}' vào database! ${e.stack}`, "DATABASE"); 19 | } 20 | } 21 | // ——————————————— CREATE USER DATA ——————————————— // 22 | if (!client.allUserData[senderID] && !isNaN(senderID) && senderID != 0) { 23 | if (client.database.userBusy) return print.warn("DATABASE BUSY", "DATABASE"); 24 | client.database.userBusy = true; 25 | try { 26 | await usersData.createData(senderID); 27 | client.database.userBusy = false; 28 | print(`New User: ${senderID} | ${client.allUserData[senderID].name} | ${globalGoat.config.database.type}`, "DATABASE"); 29 | } 30 | catch (err) { 31 | client.database.userBusy = false; 32 | print.err(`Không thể ghi người dùng có id '${senderID}' vào database! ${err.stack}`, "DATABASE"); 33 | } 34 | } 35 | } 36 | catch (e) { 37 | print.err(e.stack, "HANDLE CREATE DATABASE"); 38 | } 39 | }; 40 | return CREATEDATA; 41 | }; -------------------------------------------------------------------------------- /scripts/events/leave.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs-extra"); 2 | const moment = require("moment-timezone"); 3 | 4 | module.exports = { 5 | config: { 6 | name: "leave", 7 | version: "1.0.1", 8 | type: ["log:unsubscribe"], 9 | author: { 10 | name: "NTKhang", 11 | contacts: "" 12 | }, 13 | }, 14 | start: async ({ threadsData, message, event, globalGoat, api, client, usersData }) => { 15 | const { leftParticipantFbId } = event.logMessageData; 16 | if (leftParticipantFbId == globalGoat.botID) return; 17 | const hours = moment.tz("Asia/Ho_Chi_Minh").format("HH"); 18 | const { threadID } = event; 19 | const threadData = client.allThreadData[threadID]; 20 | if (threadData.data.sendLeaveMessage == false) return; 21 | 22 | const messageLeaveDefault = "{userName} đã {type} khỏi nhóm"; 23 | let messageLeave = threadData ? threadData.data.leaveMessage || messageLeaveDefault : messageLeaveDefault; 24 | const boxName = messageLeave.includes("{boxName}") ? (await api.getThreadInfo(threadID)).threadName : ""; // hạn chế block acc 25 | const userName = (await usersData.getData(leftParticipantFbId)).name; 26 | // {userName}: tên của thành viên bị kick / tự out 27 | // {type}: tự rời/bị qtv kick 28 | // {boxName}: tên của nhóm chat 29 | // {session}: buổi trong ngày 30 | messageLeave = messageLeave 31 | .replace(/\{userName}/g, userName) 32 | .replace(/\{type}/g, leftParticipantFbId == event.author ? "tự rời" : "bị quản trị viên xóa") 33 | .replace(/\{boxName}/g, boxName) 34 | .replace(/\{session}/g, hours <= 10 ? "sáng" : 35 | hours > 10 && hours <= 12 ? "trưa" : 36 | hours > 12 && hours <= 18 ? "chiều" : 37 | "tối" 38 | ); 39 | 40 | const form = { 41 | body: messageLeave, 42 | mentions: [{ 43 | id: leftParticipantFbId, 44 | tag: userName 45 | }] 46 | }; 47 | threadData.data.leaveAttachment ? form.attachment = fs.createReadStream(__dirname + "/src/mediaLeave/" + threadData.data.leaveAttachment) : ""; 48 | message.send(form); 49 | } 50 | }; -------------------------------------------------------------------------------- /scripts/cmds/dhbc.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "dhbc", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "game đuổi hình bắt chữ (demo)", 11 | longDescription: "chơi game đuổi hình bắt chữ (demo)", 12 | category: "game", 13 | guide: "{p}{n}" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ globalGoat, message, event, download }) { 19 | const axios = require("axios"); 20 | const fs = require("fs-extra"); 21 | const datagame = (await axios.get("https://goatbot.up.railway.app/api/duoihinhbatchu")).data; 22 | const { wordcomplete, casi, image1, image2 } = datagame.data; 23 | const pathImage1 = __dirname + "/cache/dhbc1.jpg"; 24 | const pathImage2 = __dirname + "/cache/dhbc2.jpg"; 25 | await download(image1, pathImage1); 26 | await download(image2, pathImage2); 27 | message.reply({ 28 | body: `Hãy reply tin nhắn này với câu trả lời\n${wordcomplete.replace(/\S/g, "█ ")}${casi ? `\nĐây là tên bài hát của ca sĩ ${casi}` : ''}`, 29 | attachment: [fs.createReadStream(pathImage1), fs.createReadStream(pathImage2)] 30 | }, (err, info) => { 31 | fs.unlinkSync(pathImage1); 32 | fs.unlinkSync(pathImage2); 33 | globalGoat.whenReply[info.messageID] = { 34 | messageID: info.messageID, 35 | nameCmd: this.config.name, 36 | author: event.senderID, 37 | wordcomplete 38 | }; 39 | }); 40 | }, 41 | whenReply: ({ message, Reply, event, globalGoat }) => { 42 | let { author, wordcomplete, messageID } = Reply; 43 | if (event.senderID != author) return message.reply("Bạn không phải là người chơi của câu hỏi này"); 44 | function formatText(text) { 45 | return text.normalize("NFD") 46 | .toLowerCase() 47 | .replace(/[\u0300-\u036f]/g, "") 48 | .replace(/đ/g, "d") 49 | .replace(/Đ/g, "D"); 50 | } 51 | 52 | (formatText(event.body) == formatText(wordcomplete)) ? message.reply("Chúc mừng bạn đã trả lời đúng") : message.reply(`Opps, Sai rồi`); 53 | //message.reply(`Sai rồi, đáp án đúng là: ${wordcomplete}`); 54 | delete globalGoat.whenReply[messageID]; 55 | } 56 | }; -------------------------------------------------------------------------------- /update.js: -------------------------------------------------------------------------------- 1 | (async function () { 2 | const fs = require("fs-extra"); 3 | const axios = require("axios"); 4 | const print = require("./logger/print.js"); 5 | const chalk = require("chalk"); 6 | const allVersion = (await axios.get("https://github.com/ntkhang03/Goat-Bot/raw/main/versions.json")).data; 7 | const localVersion = require("./package.json").version; 8 | if (allVersion[allVersion.length - 1].version == localVersion) 9 | return print("Bạn đang sử dụng phiên bản mới nhất rồi", "LATEST VERSION"); 10 | 11 | fs.writeFileSync(__dirname + "/versions.json", JSON.stringify(allVersion, null, 2)); 12 | 13 | const indexCurrentVersion = allVersion.findIndex(item => item.version == localVersion); 14 | const versionsUpdate = allVersion.slice(indexCurrentVersion + 1); 15 | 16 | for (const data of versionsUpdate) { 17 | if (data.del) { 18 | for (const path in data.del) 19 | try { 20 | fs.unlinkSync(path); 21 | } 22 | catch (e) { 23 | } 24 | } 25 | const { info, version } = data; 26 | print.green(version, "VERSION"); 27 | 28 | for (const location in info) { 29 | let response = (await axios.get(`https://github.com/ntkhang03/Goat-Bot/raw/main/${location}`, { 30 | responseType: "arraybuffer" 31 | })).data.toString(); 32 | let description = data.info[location]; 33 | if (location == "config.json" && description.keysNeddUpdate) { 34 | const getNewConfig = JSON.parse(response); 35 | const oldConfig = require("./config.json"); 36 | description = description.description; 37 | const keysNeddUpdate = description.keysNeddUpdate; 38 | for (const key of keysNeddUpdate) oldConfig[key] = getNewConfig[key]; 39 | response = JSON.stringify(oldConfig, null, 2); 40 | } 41 | fs.writeFileSync(`${__dirname}/${location}`, response); 42 | print.green(`Update file ${chalk.hex("#ff5208")(location)} success, description: ${chalk.hex("#d6d6d6")(description || "No description")}`, "UPDATE"); 43 | } 44 | } 45 | 46 | const packageJson = (await axios.get("https://github.com/ntkhang03/Goat-Bot/raw/main/package.json")).data; 47 | fs.writeFileSync(__dirname + "/package.json", JSON.stringify(packageJson, null, 2)); 48 | })(); -------------------------------------------------------------------------------- /scripts/cmds/banner2.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "banner2", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Tạo ảnh bìa", 11 | longDescription: "Tạo ảnh bìa đẹp", 12 | category: "image", 13 | guide: "{prefix}{n} | | | | | | [ | hoặc reply hình ảnh]" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ api, message, event, args, help }) { 19 | const axios = require("axios"); 20 | const fs = require("fs-extra"); 21 | 22 | const content = args.join(" ").split("|").map(item => item = item.trim()); 23 | 24 | const apikey = "ntkhangGoatBot"; 25 | const name = content[0], 26 | description = content[1], 27 | facebook = content[2], 28 | instagram = content[3], 29 | phone = content[4], 30 | location = content[5], 31 | 32 | avatarurl = event.messageReply ? ((event.messageReply.attachments.length > 0) ? event.messageReply.attachments[0].url : content[6]) : content[6]; 33 | if (!avatarurl || !avatarurl.includes("http")) return message.reply(`Vui lòng nhập link hình ảnh hợp lệ, sử dụng help ${this.config.name} để xem chi tiết cách sử dụng lệnh`); 34 | const params = { apikey, name, description, facebook, instagram, phone, location, avatarurl }; 35 | for (const i in params) if (!params[i]) return message.SyntaxError(); 36 | message.reply(`Đang khởi tạo hình ảnh, vui lòng chờ đợi...`); 37 | const pathSave = __dirname + `/cache/banner2${Date.now()}.png`; 38 | 39 | axios.get("https://goatbot.up.railway.app/taoanhdep/banner2", { 40 | params, 41 | responseType: "arraybuffer" 42 | }) 43 | .then(data => { 44 | const imageBuffer = data.data; 45 | fs.writeFileSync(pathSave, Buffer.from(imageBuffer)); 46 | message.reply({ 47 | attachment: fs.createReadStream(pathSave) 48 | }, () => fs.unlinkSync(pathSave)); 49 | }) 50 | .catch(error => { 51 | const err = error.response ? JSON.parse(error.response.data.toString()) : error; 52 | return message.reply(`Đã xảy ra lỗi ${err.name} ${err.message}`); 53 | }); 54 | } 55 | }; -------------------------------------------------------------------------------- /scripts/cmds/bannerbw.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "bannerbw", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Tạo banner dịch vụ online", 11 | longDescription: "Tạo ảnh bìa hỗ trợ dịch vụ online phong cách trắng đen", 12 | category: "image", 13 | guide: "{prefix}bannerbw | | | | | | [ | hoặc reply hình ảnh]" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ api, message, event, args }) { 19 | const axios = require("axios"); 20 | const fs = require("fs-extra"); 21 | 22 | const content = args.join(" ").split("|").map(item => item = item.trim()); 23 | const name = content[0], 24 | titlefacebook = content[1], 25 | facebook = content[2], 26 | phone = content[3], 27 | mail = content[4], 28 | location = content[5], 29 | avatarurl = event.messageReply ? ((event.messageReply.attachments.length > 0) ? event.messageReply.attachments[0].url : content[6]) : content[6]; 30 | if (!avatarurl || !avatarurl.includes("http")) return message.reply(`Vui lòng nhập link hình ảnh hợp lệ, sử dụng help ${this.config.name} để xem chi tiết cách sử dụng lệnh`); 31 | let params = { name, titlefacebook, facebook, phone, mail, location, avatarurl, apikey: "ntkhangGoatBot" }; 32 | for (const i in params) if (!params[i]) return message.SyntaxError(); 33 | 34 | message.reply(`Đang khởi tạo hình ảnh, vui lòng chờ đợi...`); 35 | const pathSave = __dirname + `/cache/bannerbw${Date.now()}.jpg`; 36 | 37 | axios.get("https://goatbot.up.railway.app/taoanhdep/banner-black-white", { 38 | params, 39 | responseType: "arraybuffer" 40 | }) 41 | .then(data => { 42 | const imageBuffer = data.data; 43 | fs.writeFileSync(pathSave, Buffer.from(imageBuffer)); 44 | message.reply({ 45 | attachment: fs.createReadStream(pathSave) 46 | }, () => fs.unlinkSync(pathSave)); 47 | }) 48 | .catch(error => { 49 | const err = error.response ? JSON.parse(error.response.data.toString()) : error; 50 | return message.reply(`Đã xảy ra lỗi ${err.name} ${err.message}`); 51 | }); 52 | } 53 | }; -------------------------------------------------------------------------------- /scripts/cmds/wakeup.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "wakeup", 3 | shortName: "wake", 4 | version: "1.0.0", 5 | author: { 6 | name: "NTKhang", 7 | contacts: "" 8 | }, 9 | cooldowns: 5, 10 | role: 0, 11 | shortDescription: "tính giờ thức dậy 😪", 12 | longDescription: "tính giờ đi ngủ từ giờ thức dậy để bạn có một giấc ngủ ngon 😪😪", 13 | category: "healthy", 14 | guide: "{p}{n} \nVí dụ: {p}{n} 08:30", 15 | envGlobal: { 16 | sleepCycle: 110 17 | } 18 | }; 19 | 20 | module.exports = { 21 | config: this.config, 22 | start: async function ({ message, event, args, globalGoat }) { 23 | const Canvas = require("canvas"); 24 | const moment = require("moment-timezone"); 25 | const sleepCycle = globalGoat.configCommands.envGlobal.sleepCycle; 26 | function formatTwoNumber(t) { 27 | return t < 10 ? "0" + Number(t) : t; 28 | } 29 | 30 | let msg = ""; 31 | 32 | if ((args[0] || "").split(":").length != 2) return message.reply("Vui lòng nhập giờ bạn muốn thức dậy hợp lệ theo định dạng 24h hh:mm, ví dụ\n 08:30\n 22:02"); 33 | let hoursWakeup = formatTwoNumber(args[0].split(":")[0]); 34 | let minutesWakeup = formatTwoNumber(args[0].split(":")[1]); 35 | if (isNaN(hoursWakeup) || isNaN(minutesWakeup) || 36 | hoursWakeup > 23 || minutesWakeup > 59 || 37 | hoursWakeup < 0 || minutesWakeup < 0) return message.reply("Vui lòng nhập giờ bạn muốn thức dậy hợp lệ theo định dạng 24h hh:mm, ví dụ\n 08:30\n 22:02"); 38 | const getTime = moment().tz("Asia/Ho_Chi_Minh").format("YYYY-MM-DD") + "T"; 39 | const timeWakeup = getTime + hoursWakeup + ":" + minutesWakeup + ":00+07:00"; 40 | message.reply(timeWakeup); 41 | 42 | for (let i = 6; i > 0; i--) msg += moment(timeWakeup).tz("Asia/Ho_Chi_Minh").subtract(sleepCycle * i, "minutes").format("HH:mm") + " thời gian ngủ " + formatTwoNumber(Math.floor(sleepCycle * i / 60)) + ":" + formatTwoNumber(Math.floor(sleepCycle * i % 60)) + "\n"; 43 | 44 | message.reply(`Nếu bạn muốn thức dậy vào lúc ${moment(timeWakeup).tz("Asia/Ho_Chi_Minh").format("HH:mm:ss")}, hãy ngủ vào những khoảng thời gian này:\n\n${msg}\nChu kỳ ngủ ${sleepCycle}p (${Math.floor(sleepCycle / 60)}h${Math.floor(sleepCycle % 60)}p)`); 45 | } 46 | }; -------------------------------------------------------------------------------- /scripts/cmds/sleep.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "sleep", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "tính giờ thức dậy 😪", 11 | longDescription: "tính giờ thức dậy từ giờ đi ngủ để bạn có một giấc ngủ ngon 😪😪", 12 | category: "healthy", 13 | guide: "{p}{n} [để trống|]\nVí dụ:\n {p}{n}\n {p}{n} 08:30\n {p}{n} 22:02", 14 | envGlobal: { 15 | sleepCycle: 110 16 | } 17 | }; 18 | 19 | module.exports = { 20 | config: this.config, 21 | start: async function ({ message, event, args, globalGoat }) { 22 | const Canvas = require("canvas"); 23 | const moment = require("moment-timezone"); 24 | const sleepCycle = globalGoat.configCommands.envGlobal.sleepCycle; 25 | function formatTwoNumber(t) { 26 | return t < 10 ? "0" + Number(t) : t; 27 | } 28 | 29 | let msg = ""; 30 | let timeSleep; 31 | 32 | if (!args[0]) timeSleep = moment().tz("Asia/Ho_Chi_Minh").format(); 33 | else { 34 | if (args[0].split(":").length != 2) return message.reply("Vui lòng nhập giờ đi ngủ hợp lệ theo định dạng 24h hh:mm, ví dụ\n 08:30\n 22:02"); 35 | let hoursSleep = formatTwoNumber(args[0].split(":")[0]); 36 | let minutesSleep = formatTwoNumber(args[0].split(":")[1]); 37 | if (isNaN(hoursSleep) || isNaN(minutesSleep) || 38 | hoursSleep > 23 || minutesSleep > 59 || 39 | hoursSleep < 0 || minutesSleep < 0) return message.reply("Vui lòng nhập giờ đi ngủ hợp lệ theo định dạng 24h hh:mm, ví dụ\n 08:30\n 22:02"); 40 | const getTime = moment().tz("Asia/Ho_Chi_Minh").format("YYYY-MM-DD") + "T"; 41 | timeSleep = getTime + hoursSleep + ":" + minutesSleep + ":00+07:00"; 42 | } 43 | 44 | for (let i = 1; i < 6; i++) msg += moment(timeSleep).tz("Asia/Ho_Chi_Minh").add(sleepCycle * i, "minutes").format("HH:mm") + " thời gian ngủ " + formatTwoNumber(Math.floor(sleepCycle * i / 60)) + ":" + formatTwoNumber(Math.floor(sleepCycle * i % 60)) + "\n"; 45 | 46 | message.reply(`Nếu bạn ngủ vào lúc ${moment(timeSleep).tz("Asia/Ho_Chi_Minh").format("HH:mm:ss")}, đánh thức lúc:\n\n${msg}\nChu kỳ ngủ ${sleepCycle}p (${Math.floor(sleepCycle / 60)}h${Math.floor(sleepCycle % 60)}p)`); 47 | } 48 | }; -------------------------------------------------------------------------------- /scripts/cmds/banner.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "banner", 3 | version: "1.0.3", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Tạo banner dịch vụ online", 11 | longDescription: "Tạo ảnh bìa hỗ trợ dịch vụ online", 12 | category: "image", 13 | guide: "{prefix}banner | | | | | <subtitle> | <titlefacebook> | <info> | [<link ảnh> | hoặc reply hình ảnh]" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ message, event, args }) { 19 | const axios = require("axios"); 20 | const fs = require("fs-extra"); 21 | 22 | const content = args.join(" ").split("|").map(item => item = item.trim()); 23 | const apikey = "ntkhangGoatBot"; 24 | const facebook = content[0], 25 | zalo = content[1], 26 | phone = content[2], 27 | momo = content[3], 28 | title = content[4], 29 | subtitle = content[5], 30 | titlefacebook = content[6], 31 | info = content[7]; 32 | const avatarurl = event.messageReply ? ((event.messageReply.attachments.length > 0) ? event.messageReply.attachments[0].url : content[8]) : content[8]; 33 | if (!avatarurl || !avatarurl.includes("http")) return message.reply(`Vui lòng nhập link hình ảnh hợp lệ, sử dụng help ${this.config.name} để xem chi tiết cách sử dụng lệnh`); 34 | const params = { facebook, zalo, phone, momo, title, subtitle, titlefacebook, info, avatarurl, apikey }; 35 | for (const i in params) if (!params[i]) return message.SyntaxError(); 36 | message.reply(`Đang khởi tạo hình ảnh, vui lòng chờ đợi...`); 37 | 38 | axios.get("https://goatbot.up.railway.app/taoanhdep/banner1", { 39 | params, 40 | responseType: "arraybuffer" 41 | }) 42 | .then(data => { 43 | const imageBuffer = data.data; 44 | const pathSave = __dirname + "/cache/banner.jpg"; 45 | fs.writeFileSync(pathSave, Buffer.from(imageBuffer)); 46 | message.reply({ 47 | attachment: fs.createReadStream(pathSave) 48 | }, () => fs.unlinkSync(pathSave)); 49 | }) 50 | .catch(error => { 51 | const err = error.response ? JSON.parse(error.response.data.toString()) : error; 52 | return message.reply(`Đã xảy ra lỗi ${err.name} ${err.message}`); 53 | }); 54 | } 55 | }; -------------------------------------------------------------------------------- /scripts/cmds/daily.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "daily", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "báo danh hằng ngày", 11 | longDescription: "nhận quà báo danh hằng ngày", 12 | category: "gift", 13 | guide: "{p}{n} [để trống | info]", 14 | envConfig: { 15 | rewardDay1: { 16 | coin: 100, 17 | exp: 10 18 | } 19 | } 20 | }; 21 | 22 | 23 | module.exports = { 24 | config: this.config, 25 | start: async function ({ usersData, message, event, globalGoat, args }) { 26 | const moment = require("moment-timezone"); 27 | 28 | const reward = globalGoat.configCommands.envCommands[this.config.name].rewardDay1; 29 | if (args[0] == "info") { 30 | const rewardAll = globalGoat.configCommands.envCommands[this.config.name]; 31 | let msg = ""; 32 | let i = 1; 33 | for (let i = 1; i < 8; i++) { 34 | const getCoin = Math.floor(reward.coin * (1 + 20 / 100) ** ((i == 0 ? 7 : i) - 1)); 35 | const getExp = Math.floor(reward.exp * (1 + 20 / 100) ** ((i == 0 ? 7 : i) - 1)); 36 | msg += `${i == 7 ? "Chủ Nhật" : "Thứ " + (i + 1)}: ${getCoin} coin và ${getExp} exp\n`; 37 | } 38 | return message.reply(msg); 39 | } 40 | 41 | const dateTime = moment.tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY"); 42 | const date = new Date(); 43 | let current_day = date.getDay(); // Lấy số thứ tự của ngày hiện tại 44 | const { senderID } = event; 45 | 46 | const userData = await usersData.getData(senderID); 47 | if (userData.lastTimeGetReward === dateTime) return message.reply("Bạn đã nhận phần quà báo danh của ngày hôm nay rồi, vui lòng quay lại vào ngày mai"); 48 | 49 | const getCoin = Math.floor(reward.coin * (1 + 20 / 100) ** ((current_day == 0 ? 7 : current_day) - 1)); 50 | const getExp = Math.floor(reward.exp * (1 + 20 / 100) ** ((current_day == 0 ? 7 : current_day) - 1)); 51 | 52 | await usersData.setData(senderID, { 53 | money: userData.money + getCoin, 54 | exp: userData.exp + getExp, 55 | lastTimeGetReward: dateTime 56 | }, (err, data) => { 57 | if (err) return message.reply(`Đã xảy ra lỗi: ${err.name}: ${err.message}`); 58 | message.reply(`Bạn đã nhận được ${getCoin} coin và ${getExp} exp`); 59 | }); 60 | 61 | } 62 | }; -------------------------------------------------------------------------------- /scripts/events/logsbot.js: -------------------------------------------------------------------------------- 1 | const moment = require("moment-timezone"); 2 | 3 | module.exports = { 4 | config: { 5 | name: "logsbot", 6 | type: ["log:subscribe", "log:unsubscribe"], 7 | condition: `(event.logMessageType == "log:subscribe" && event.logMessageData.addedParticipants.some(item => item.userFbId == globalGoat.botID)) || (event.logMessageType == "log:unsubscribe" && event.logMessageData.leftParticipantFbId == globalGoat.botID)`, 8 | isBot: true, 9 | version: "1.0.2", 10 | author: { 11 | name: "NTKhang", 12 | contacts: "" 13 | }, 14 | cooldowns: 5, 15 | envConfig: { 16 | logsbot: true 17 | } 18 | }, 19 | start: async ({ globalGoat, args, allUserData, message, event, api, client }) => { 20 | 21 | if (!globalGoat.configCommands.envEvents.logsbot.logsbot) return; 22 | let msg = "====== Nhật ký bot ======"; 23 | const { author, threadID } = event; 24 | if (author == globalGoat.botID) return; 25 | let threadName; 26 | 27 | if (event.logMessageType == "log:subscribe") { 28 | if (!event.logMessageData.addedParticipants.some(item => item.userFbId == globalGoat.botID)) return; 29 | if (globalGoat.config.nickNameBot) api.changeNickname(globalGoat.config.nickNameBot, event.threadID, globalGoat.botID); 30 | threadName = (await api.getThreadInfo(threadID)).threadName; 31 | const authorName = client.allUserData[author] ? client.allUserData[author].name : await api.getUserInfo(author)[author].name; 32 | msg += `\n✅\nHoạt động: bot được thêm vào nhóm mới` + 33 | `\nNgười thêm: ${authorName}`; 34 | } 35 | else if (event.logMessageType == "log:unsubscribe") { 36 | if (event.logMessageData.leftParticipantFbId != globalGoat.botID) return; 37 | const authorName = client.allUserData[author] ? client.allUserData[author].name : await api.getUserInfo(author)[author].name; 38 | threadName = client.allThreadData[threadID].name; 39 | msg += `\n❎\nHoạt động: bot bị kick` + 40 | `\nNgười kick: ${authorName}`; 41 | } 42 | const time = moment.tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY HH:mm:ss"); 43 | msg += `\nUser ID: ${author}` + 44 | `\nThread Name: ${threadName}` + 45 | `\nThread ID: ${threadID}` + 46 | `\nThời gian: ${time}`; 47 | 48 | api.sendMessage(msg, globalGoat.config.adminBot[0]); 49 | } 50 | }; -------------------------------------------------------------------------------- /scripts/events/autoUpdateInfoThread.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs-extra"); 2 | const moment = require("moment-timezone"); 3 | 4 | module.exports = { 5 | config: { 6 | name: "autoUpdateInfoThread", 7 | version: "1.0.3", 8 | type: ["log:subscribe", "log:unsubscribe", "change_thread_admins", "log:thread-name", "change_thread_image", "log:thread-icon"], 9 | author: { 10 | name: "NTKhang", 11 | contacts: "" 12 | }, 13 | }, 14 | 15 | start: async ({ threadsData, message, event, globalGoat, api, client }) => { 16 | const { threadID, logMessageData, logMessageType } = event; 17 | const threadInfo = await threadsData.getData(event.threadID); 18 | const { members, adminIDs } = threadInfo; 19 | if (logMessageType == "log:subscribe") { 20 | const dataAddedParticipants = event.logMessageData.addedParticipants; 21 | for (const user of dataAddedParticipants) { 22 | const oldData = members[user.userFbId] || {}; 23 | const getThreadInfo_Fca = await api.getThreadInfo(threadID); 24 | const { userInfo, nicknames } = getThreadInfo_Fca; 25 | members[user.userFbId] = { 26 | id: user.userFbId, 27 | name: user.fullName, 28 | gender: userInfo.find(u => u.id == user.userFbId).gender, 29 | nickname: nicknames[user.userFbId] || null, 30 | inGroup: true, 31 | count: oldData.count || 0 32 | }; 33 | } 34 | await threadsData.setData(threadID, { members }); 35 | } 36 | else if (logMessageType == 'log:unsubscribe') { 37 | if (members[logMessageData.leftParticipantFbId]) { 38 | members[logMessageData.leftParticipantFbId].inGroup = false; 39 | await threadsData.setData(threadID, { members }); 40 | } 41 | } 42 | else if (logMessageType == 'change_thread_admins') { 43 | if (logMessageData.ADMIN_EVENT == "add_admin") adminIDs.push(logMessageData.TARGET_ID); 44 | else adminIDs.splice(adminIDs.findIndex(uid => uid == logMessageData.TARGET_ID), 1); 45 | await threadsData.setData(threadID, { adminIDs }); 46 | } 47 | else if (logMessageType == 'log:thread-name') { 48 | const threadName = logMessageData.name; 49 | await threadsData.setData(threadID, { name: threadName }); 50 | } 51 | else if (logMessageType == 'change_thread_image') { 52 | await threadsData.setData(threadID, { avatarbox: event.image.url }); 53 | } 54 | else if (logMessageType == 'log:thread-icon') { 55 | await threadsData.setData(threadID, { emoji: logMessageData.thread_icon }); 56 | } 57 | } 58 | }; -------------------------------------------------------------------------------- /scripts/events/welcome.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs-extra"); 2 | const moment = require("moment-timezone"); 3 | 4 | module.exports = { 5 | config: { 6 | name: "welcome", 7 | version: "1.0.3", 8 | type: ["log:subscribe"], 9 | author: { 10 | name: "NTKhang", 11 | contacts: "" 12 | }, 13 | }, 14 | start: async ({ threadsData, message, event, globalGoat, api, client }) => { 15 | const hours = moment.tz("Asia/Ho_Chi_Minh").format("HH"); 16 | const { threadID } = event; 17 | const { prefix, nickNameBot } = globalGoat.config; 18 | const dataAddedParticipants = event.logMessageData.addedParticipants; 19 | // Nếu là bot; 20 | if (dataAddedParticipants.some(item => item.userFbId == globalGoat.botID)) { 21 | if (nickNameBot) api.changeNickname(nickNameBot, threadID, globalGoat.botID); 22 | return message.send(`Thank you for inviting me!\nPrefix bot: ${globalGoat.config.prefix}\nĐể xem danh sách lệnh hãy nhập: ${prefix}help`); 23 | } 24 | 25 | // Nếu là thành viên mới: 26 | const threadData = client.allThreadData[threadID].data; 27 | if (threadData.sendWelcomeMessage == false) return; 28 | const boxName = client.allThreadData[threadID].name; 29 | const userName = [], mentions = []; 30 | let multiple = false; 31 | 32 | if (dataAddedParticipants.length > 1) multiple = true; 33 | for (let user of dataAddedParticipants) { 34 | userName.push(user.fullName); 35 | mentions.push({ 36 | tag: user.fullName, 37 | id: user.userFbId 38 | }); 39 | } 40 | // {userName}: tên của thành viên mới 41 | // {boxName}: tên của nhóm chat 42 | // {multiple}: bạn || các bạn 43 | // {session}: buổi trong ngày 44 | const messageWelcomeDefault = `Xin chào {userName}.\nChào mừng {multiple} đã đến với nhóm chat: {boxName}\nChúc {multiple} có một buổi {session} vui vẻ =)`; 45 | let messageWelcome = threadData.welcomeMessage || messageWelcomeDefault; 46 | messageWelcome = messageWelcome 47 | .replace(/\{userName}/g, userName.join(", ")) 48 | .replace(/\{boxName}/g, boxName) 49 | .replace(/\{multiple}/g, multiple ? "các bạn" : "bạn") 50 | .replace(/\{session}/g, hours <= 10 ? "sáng" : 51 | hours > 10 && hours <= 12 ? "trưa" : 52 | hours > 12 && hours <= 18 ? "chiều" : "tối"); 53 | 54 | const form = { 55 | body: messageWelcome, 56 | mentions 57 | }; 58 | threadData.welcomeAttachment ? form.attachment = fs.createReadStream(__dirname + "/src/mediaWelcome/" + threadData.welcomeAttachment) : ""; 59 | 60 | message.send(form); 61 | } 62 | }; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | 3 | process.on('unhandledRejection', error => console.error(error)); 4 | process.on('uncaughtException', error => console.error(error)); 5 | 6 | const chalk = require("chalk"); 7 | const login = require("fb-chat-api"); 8 | const { writeFileSync } = require("fs-extra"); 9 | 10 | const print = require("./logger/print.js"); 11 | const loading = require("./logger/loading.js"); 12 | 13 | const globalGoat = { 14 | print, 15 | loading, 16 | commands: new Map(), 17 | shortNameCommands: new Map(), 18 | events: new Map(), 19 | whenChat: [], 20 | whenReply: {}, 21 | whenReaction: {}, 22 | config: require("./config.json"), 23 | configCommands: require("./configCommands.json") 24 | }; 25 | // ————————————————— LOAD CONFIG ————————————————— // 26 | print("Đã cài đặt thiết lặp cho bot", "CONFIG"); 27 | const { configCommands, config } = globalGoat; 28 | 29 | const client = { 30 | dirConfig: __dirname + "/config.json", 31 | dirConfigCommands: __dirname + "/configCommands.json", 32 | allThreadData: {}, 33 | allUserData: {}, 34 | cooldowns: {}, 35 | cache: {}, 36 | database: { 37 | threadBusy: false, 38 | userBusy: false 39 | }, 40 | allThread: [], 41 | allUser: [], 42 | commandBanned: configCommands.commandBanned, 43 | getPrefix: function (threadID) { 44 | let prefix = globalGoat.config.prefix; 45 | client.allThreadData[threadID] ? prefix = client.allThreadData[threadID].prefix || prefix : ""; 46 | return prefix; 47 | } 48 | }; 49 | 50 | // ———————————— LOAD TẤT CẢ TỆP LỆNH ———————————— // 51 | print("Tiến hành tải các tệp lệnh, vui lòng chờ", "LOAD COMMANDS"); 52 | await require("./bot/loadAllScript.js")(globalGoat); 53 | // ———————— // ———————— // ———————— // ———————— // 54 | console.log(chalk.blue(`===========================================`)); 55 | print(`Đã load thành công: ${globalGoat.commands.size} Script commands`, "LOADED"); 56 | print(`Đã load thành công: ${globalGoat.events.size} Script events`, "LOADED"); 57 | console.log(chalk.blue(`===========================================`)); 58 | // —————————————————— LOGIN ————————————————— // 59 | require("./bot/login.js")(login, print, loading, config, client, globalGoat, configCommands, writeFileSync); 60 | })(); 61 | 62 | /* 63 | * 64 | *Mã nguồn được viết bởi NTKhang, vui lòng không thay đổi tên tác giả ở bất kỳ tệp nào. Cảm ơn bạn đã sử dụng 65 | *The source code is written by NTKhang, please don't change the author's name everywhere. Thank you for using 66 | * 67 | */ -------------------------------------------------------------------------------- /scripts/cmds/setbox.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "setbox", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Chỉnh sửa nhóm của bạn", 11 | longDescription: "Chỉnh sửa nhóm của bạn", 12 | category: "box chat", 13 | guide: "{p}{n} [name|emoji|avatar] <nội dung chỉnh sửa>" 14 | + "\nChi tiết:" 15 | + "\n {p}{n} name <tên mới>: đổi tên nhóm chat" 16 | + "\n {p}{n} emoji <emoji mới>: đổi emoji nhóm" 17 | + "\n {p}{n} avatar <link ảnh hoặc reply một ảnh hoặc gửi kèm 1 ảnh>: đổi avatar nhóm chat" 18 | }; 19 | 20 | module.exports = { 21 | config: this.config, 22 | start: async function ({ message, api, event, args, threadsData, download }) { 23 | const fs = require("fs-extra"); 24 | const axios = require("axios"); 25 | 26 | if (args[0] == "name") { 27 | const newName = args.slice(1).join(" "); 28 | api.setTitle(newName, event.threadID, async function (err) { 29 | if (err) return message.reply("Rất tiếc, đã xảy ra lỗi"); 30 | message.reply("Đã đổi tên nhóm thành: " + newName); 31 | await threadsData.setData(event.threadID, { 32 | name: newName 33 | }); 34 | }); 35 | } 36 | else if (args[0] == "emoji") { 37 | const newEmoji = args[1]; 38 | api.changeThreadEmoji(newEmoji, event.threadID, async function (err) { 39 | if (err) return message.reply("Rất tiếc, đã xảy ra lỗi"); 40 | message.reply("Đã đổi emoji nhóm thành: " + newEmoji); 41 | await threadsData.setData(event.threadID, { 42 | emoji: newEmoji 43 | }); 44 | }); 45 | } 46 | else if (["avatar", "avt", "img"].includes(args[0])) { 47 | const urlImage = (event.messageReply && event.messageReply.attachments[0] && event.messageReply.attachments[0].type != "share") ? event.messageReply.attachments[0].url : (event.attachments[0] && event.attachments[0].type != "share") ? event.attachments[0].url : args[1]; 48 | 49 | if (!urlImage) return message.reply("Vui lòng gửi kèm hoặc reply một hình ảnh hoặc nhập vào link"); 50 | const pathSave = __dirname + `/avatar${event.threadID}.png`; 51 | await download(urlImage, pathSave); 52 | api.changeGroupImage(fs.createReadStream(pathSave), event.threadID, async function (err) { 53 | if (err) return message.reply("Rất tiếc, đã xảy ra lỗi"); 54 | message.reply("Đã thay đổi ảnh nhóm"); 55 | fs.unlinkSync(pathSave); 56 | await threadsData.setData(event.threadID, { 57 | avatarbox: urlImage 58 | }); 59 | }); 60 | } 61 | else message.SyntaxError(); 62 | } 63 | }; -------------------------------------------------------------------------------- /scripts/cmds/setleave.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "setleave", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "chỉnh sửa nội dung tin nhắn tạm biệt", 11 | longDescription: "chỉnh sửa nội dung tin nhắn tạm biệt thành viên rời khỏi nhóm chat của bạn", 12 | category: "custom", 13 | guide: "{p}{n} text [<nội dung>|reset]: chỉnh sửa nội dung văn bản hoặc reset về mặc định, những shortcut có sẵn:" 14 | + "\n+ {userName}: tên của thành viên mới" 15 | + "\n+ {boxName}: tên của nhóm chat" 16 | + "\n+ {type}: tự rời/bị qtv xóa khỏi nhóm" 17 | + "\n+ {session}: buổi trong ngày" 18 | + "\n* Ví dụ: {p}{n} text {userName} đã {type} khỏi nhóm, see you again 🤧" 19 | + "\n" 20 | + "\nReply (phản hồi) một tin nhắn có file với nội dung {p}{n} file: để gửi file đó khi có thành viên rời khỏi nhóm (ảnh, video, audio)" 21 | + "\n{p}{n} file reset: xóa gửi file" 22 | }; 23 | 24 | module.exports = { 25 | config: this.config, 26 | start: async function ({ args, threadsData, globalGoat, message, event, download }) { 27 | const fs = require("fs-extra"); 28 | const { threadID } = event; 29 | const data = (await threadsData.getData(threadID)).data; 30 | 31 | if (args[0] == "text") { 32 | if (!args[1]) return message.reply("Vui lùng nhập nội dung tin nhắn"); 33 | else if (args[1] == "reset") data.leaveMessage = null; 34 | else data.leaveMessage = args.slice(1).join(" "); 35 | } 36 | else if (args[0] == "file") { 37 | if (args[1] == "reset") { 38 | try { 39 | fs.unlinkSync(__dirname + "/../events/src/mediaLeave/" + data.leaveAttachment); 40 | } 41 | catch (e) { } 42 | data.leaveAttachment = null; 43 | } 44 | else if (!event.messageReply || event.messageReply.attachments.length == 0) return message.reply("Vui lòng reply (phản hồi) một tin nhắn có chứa file ảnh/video/audio"); 45 | else { 46 | const attachments = event.messageReply.attachments; 47 | const typeFile = attachments[0].type; 48 | const ext = typeFile == "audio" ? ".mp3" : 49 | typeFile == "video" ? ".mp4" : 50 | typeFile == "photo" ? ".png" : 51 | typeFile == "animated_image" ? ".gif" : ""; 52 | const fileName = "leave" + threadID + ext; 53 | await download(attachments[0].url, __dirname + "/../events/src/mediaLeave/" + fileName); 54 | data.leaveAttachment = fileName; 55 | } 56 | } 57 | else return message.SyntaxError(); 58 | 59 | await threadsData.setData(threadID, { 60 | data 61 | }, (err, info) => { 62 | if (err) return message.reply(`Đã xảy ra lỗi, vui lòng thử lại sau: ${err.name}: ${err.message}`); 63 | message.reply(`Đã lưu thay đổi của bạn`); 64 | }); 65 | 66 | } 67 | }; -------------------------------------------------------------------------------- /scripts/cmds/setwelcome.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "setwelcome", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "chỉnh sửa nội dung tin nhắn chào mừng", 11 | longDescription: "chỉnh sửa nội dung tin nhắn chào mừng thành viên mới tham gia vào nhóm chat của bạn", 12 | category: "custom", 13 | guide: "{p}{n} text [<nội dung>|reset]: chỉnh sửa nội dung văn bản hoặc reset về mặc định, những shortcut có sẵn:" 14 | + "\n+ {userName}: tên của thành viên mới" 15 | + "\n+ {boxName}: tên của nhóm chat" 16 | + "\n+ {multiple}: bạn || các bạn" 17 | + "\n+ {session}: buổi trong ngày" 18 | + "\n* Ví dụ: {p}{n} text Hello {userName}, welcome to {boxName}, chúc {multiple} một ngày mới vui vẻ" 19 | + "\n" 20 | + "\nReply (phản hồi) một tin nhắn có file với nội dung {p}{n} file: để gửi file đó khi có thành viên mới (ảnh, video, audio)" 21 | + "\n{p}{n} file reset: xóa gửi file" 22 | }; 23 | 24 | module.exports = { 25 | config: this.config, 26 | start: async function ({ args, threadsData, globalGoat, message, event, download }) { 27 | const fs = require("fs-extra"); 28 | const { threadID } = event; 29 | const data = (await threadsData.getData(threadID)).data; 30 | 31 | if (args[0] == "text") { 32 | if (!args[1]) return message.reply("Vui lùng nhập nội dung tin nhắn"); 33 | else if (args[1] == "reset") data.welcomeMessage = null; 34 | else data.welcomeMessage = args.slice(1).join(" "); 35 | } 36 | else if (args[0] == "file") { 37 | if (args[1] == "reset") { 38 | try { 39 | fs.unlinkSync(__dirname + "/../events/src/mediaWelcome/" + data.welcomeAttachment); 40 | } 41 | catch (e) { } 42 | data.welcomeAttachment = null; 43 | } 44 | else if (!event.messageReply || event.messageReply.attachments.length == 0) return message.reply("Vui lòng reply (phản hồi) một tin nhắn có chứa file ảnh/video/audio"); 45 | else { 46 | const attachments = event.messageReply.attachments; 47 | const typeFile = attachments[0].type; 48 | const ext = typeFile == "audio" ? ".mp3" : 49 | typeFile == "video" ? ".mp4" : 50 | typeFile == "photo" ? ".png" : 51 | typeFile == "animated_image" ? ".gif" : ""; 52 | const fileName = "welcome" + threadID + ext; 53 | await download(attachments[0].url, __dirname + "/../events/src/mediaWelcome/" + fileName); 54 | data.welcomeAttachment = fileName; 55 | } 56 | } 57 | else return message.SyntaxError(); 58 | 59 | await threadsData.setData(threadID, { 60 | data 61 | }, (err, info) => { 62 | if (err) return message.reply(`Đã xảy ra lỗi, vui lòng thử lại sau: ${err.name}: ${err.message}`); 63 | message.reply(`Đã lưu thay đổi của bạn`); 64 | }); 65 | 66 | } 67 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | <p align="center"> 2 | <img alt="size" src="https://img.shields.io/github/repo-size/ntkhang03/Goat-Bot.svg?style=flat-square&label=size"> 3 | <img alt="code-version" src="https://img.shields.io/badge/dynamic/json?color=red&label=code%20version&prefix=v&query=%24.version&url=https://github.com/ntkhang03/Goat-Bot/raw/main/package.json&style=flat-square"> 4 | <img alt="visitors" src="https://visitor-badge.laobi.icu/badge?page_id=ntkhang3.Goat-Bot"> 5 | </p> 6 | 7 | ## **NOTE**: ***There is now version 2 with improved performance and stability: [here](https://github.com/ntkhang03/Goat-Bot-V2)*** 8 | <hr> 9 | 10 | ## HOW TO INSTALL 11 | ### Video 12 | * Installation Instructions in hosting replit: [click here](https://youtu.be/PIjtrHXLakE) 13 | * Installation Instructions in VPS: [click here](https://youtu.be/wo8Pz_5N-ug) 14 | [![IMAGE_ALT](https://i.imgur.com/n4svD1I.png)](https://youtu.be/PIjtrHXLakE) 15 | 16 | ### Bên dưới là tóm tắt cách cái đặt và sử dụng bot: 17 | * Bước 1: cài đặt nodejs 18 | * Bước 2: clone project về máy 19 | * Bước 3: tải và cài đặt [tiện ích này](https://github.com/ntkhang03/resources-goat-bot/blob/master/c3c-fbstate-extractor.crx?raw=true) (nếu sử dụng kiwi browser trên điện thoại) hoặc [tiện ích này](https://github.com/ntkhang03/resources-goat-bot/blob/master/c3c-fbstate-master.zip?raw=true) (nếu sử dụng trên Windows) vào trình duyệt 20 | * Bước 4: mở trình duyệt, đăng nhập vào tài khoản facebook dùng để treo bot (acc phụ). Sau đó mở tiện ích vừa cài ở bước trên, nhấp vào nút Export FBstate. lúc này sẽ tải 1 file fbstate.json về máy, copy file đó vào project 21 | * Bước 5: mở cmd di chuyển đến thư mục chứa project. Gõ npm install && npm start 22 | ## Lưu Ý: 23 | * Đây là một project sử dụng api chat bot không chính thức nên có thể sẽ bị facebook quét acc và dính checkpoint (block acc). Vì vậy nên cân nhắc trước khi sử dụng hoặc sử dụng một tài khoản clone (tài khoản phụ) để treo. 24 | * Nghiêm cấm mọi hình thức rao bán source code. Vì đây là một project hoàn toàn miễn phí 25 | 26 | ## HOW TO UPDATE WHEN HAVE NEW VERSION 27 | * Type in cmd 28 | 29 | > node update.js 30 | 31 | or 32 | 33 | > npm update 34 | 35 | ## DEMO 36 | ![image](https://i.ibb.co/NZpRk31/Screenshot-2021-12-12-16-01-59-14.png) 37 | ![image](https://i.ibb.co/d4ccbJd/Screenshot-2021-12-12-15-55-32-66.png) 38 | ![image](https://i.ibb.co/jZ7F74c/IMG-20211212-160006.jpg) 39 | ![image](https://i.ibb.co/bJ1Hckw/IMG-20220110-163630.jpg) 40 | 41 | ## FEEDBACK & REPORT BUGS 42 | * https://github.com/ntkhang03/Goat-Bot/issues 43 | * https://www.facebook.com/groups/399521505099456/?ref=share 44 | ## CONTACT 45 | [NTKhang](https://facebook.com/100010382497517) 46 | 47 | ## DONATE ME 48 | * MB Bank: 0789629831 (Nguyễn Thành Khang) 49 | * Momo: 0789629831 (Nguyễn Thành Khang) 50 | 51 | ## THANKS FOR USING MY PROJECT 52 | ![failed image](https://www.english-learning.net/wp-content/uploads/2018/03/Thank-you.jpg) -------------------------------------------------------------------------------- /scripts/cmds/adduser.js: -------------------------------------------------------------------------------- 1 | const qs = require('querystring'); 2 | const axios = require('axios'); 3 | 4 | this.config = { 5 | name: "adduser", 6 | version: "1.0.9", 7 | author: { 8 | name: "NTKhang", 9 | contacts: "" 10 | }, 11 | cooldowns: 5, 12 | role: 0, 13 | shortDescription: "Thêm thành viên vào box chat", 14 | longDescription: "Thêm thành viên vào box chat của bạn", 15 | category: "box chat", 16 | guide: "{p}{n} [link profile|uid]", 17 | packages: "querystring" 18 | }; 19 | 20 | async function findUid(link) { 21 | const response = await axios.post("https://id.traodoisub.com/api.php", qs.stringify({ link })); 22 | const uid = response.data.id; 23 | if (!uid) { 24 | const err = new Error(response.data.error); 25 | for (const key in response.data) 26 | err[key] = response.data[key]; 27 | throw err; 28 | } 29 | return uid; 30 | } 31 | 32 | module.exports = { 33 | config: this.config, 34 | start: async function ({ message, api, event, args }) { 35 | const threadInfo = await api.getThreadInfo(event.threadID); 36 | const success = [{ 37 | type: "success", 38 | uids: [] 39 | }, 40 | { 41 | type: "waitApproval", 42 | uids: [] 43 | }]; 44 | const failed = []; 45 | 46 | function checkAndPushError(messageError, item) { 47 | const findType = failed.find(error => error.type == messageError); 48 | if (findType) findType.uids.push(item); 49 | else failed.push({ 50 | type: messageError, 51 | uids: [item] 52 | }); 53 | } 54 | 55 | for (const item of args) { 56 | let uid; 57 | if (isNaN(item)) { 58 | try { 59 | uid = await findUid(item); 60 | } 61 | catch (err) { 62 | checkAndPushError(err.message, item); 63 | continue; 64 | } 65 | } 66 | else uid = item; 67 | 68 | if (threadInfo.participantIDs.includes(uid)) { 69 | checkAndPushError("Đã có trong nhóm", item); 70 | } 71 | else { 72 | try { 73 | await api.addUserToGroup(uid, event.threadID); 74 | const botID = api.getCurrentUserID(); 75 | if (threadInfo.approvalMode && !threadInfo.adminIDs.some(admin => admin.id == botID)) success[1].uids.push(uid); 76 | else success[0].uids.push(uid); 77 | } 78 | catch (err) { 79 | checkAndPushError(err.errorDescription, item); 80 | } 81 | } 82 | } 83 | const lengthUserSuccess = success[0].uids.length; 84 | const lengthUserWaitApproval = success[1].uids.length; 85 | const lengthUserError = failed.length; 86 | 87 | let msg = ""; 88 | if (lengthUserSuccess) msg += `- Đã thêm thành công ${lengthUserSuccess} thành viên vào nhóm`; 89 | if (lengthUserWaitApproval) msg += `\n- Đã thêm ${lengthUserWaitApproval} thành viên vào danh sách phê duyệt`; 90 | if (lengthUserError) msg += `\n- Đã xảy ra lỗi khi thêm ${lengthUserError} thành viên vào nhóm:${failed.reduce((a, b) => a += `\n + ${b.uids.join('; ')}: ${b.type}`, "")}`; 91 | message.reply(msg); 92 | } 93 | }; -------------------------------------------------------------------------------- /scripts/cmds/pairing.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "pairing", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Ghép đôi random với một người", 11 | longDescription: "Ghép đôi random với một người trong box chat", 12 | category: "image", 13 | guide: "{p}{n}", 14 | packages: ["jimp"], 15 | envGlobal: { 16 | tokenFacebook: "2712477385668128%7Cb429aeb53369951d411e1cae8e810640" 17 | }, 18 | }; 19 | 20 | module.exports = { 21 | config: this.config, 22 | start: async function ({ api, args, threadsData, message, client, event, globalGoat, download }) { 23 | const axios = require("axios"); 24 | const fs = require("fs-extra"); 25 | const Canvas = require("canvas"); 26 | const jimp = require("jimp"); 27 | 28 | async function circleImage(buffer) { 29 | const imageBuffer = await jimp.read(buffer); 30 | imageBuffer.circle(); 31 | return await imageBuffer.getBufferAsync("image/png"); 32 | } 33 | 34 | const { tokenFacebook } = globalGoat.configCommands.envGlobal; 35 | const { threadID, senderID, messageID } = event; 36 | const threadData = await threadsData.getData(threadID); 37 | const { members } = threadData; 38 | const listUid = Object.keys(members); 39 | const random = listUid[Math.floor(Math.random() * listUid.length)]; 40 | 41 | const frame = await Canvas.loadImage("https://i.pinimg.com/736x/15/fa/9d/15fa9d71cdd07486bb6f728dae2fb264.jpg"); 42 | const avatarAuthor = await Canvas.loadImage(await circleImage(`https://graph.facebook.com/${senderID}/picture?width=512&height=512&access_token=${tokenFacebook}`)); 43 | const avatarRandom = await Canvas.loadImage(await circleImage(`https://graph.facebook.com/${random}/picture?width=512&height=512&access_token=${tokenFacebook}`)); 44 | 45 | const canvas = Canvas.createCanvas(frame.width, frame.height); 46 | const ctx = canvas.getContext("2d"); 47 | 48 | const infoFrame = [ 49 | { 50 | gender: "MALE", 51 | x: 355, 52 | y: 120, 53 | size: 80 54 | }, 55 | { 56 | gender: "FEMALE", 57 | x: 250, 58 | y: 155, 59 | size: 75 60 | } 61 | ]; 62 | const drawAuthor = infoFrame.find(item => item.gender == members[senderID].gender); 63 | const drawRandom = infoFrame.find(item => item.gender != members[senderID].gender); 64 | 65 | ctx.drawImage(frame, 0, 0, frame.width, frame.height); 66 | ctx.drawImage(avatarAuthor, drawAuthor.x, drawAuthor.y, drawAuthor.size, drawAuthor.size); 67 | ctx.drawImage(avatarRandom, drawRandom.x, drawRandom.y, drawRandom.size, drawRandom.size); 68 | 69 | const pathSave = __dirname + "/cache/pairing.png"; 70 | fs.writeFileSync(pathSave, canvas.toBuffer()); 71 | 72 | return message.reply({ 73 | body: `Chúc mừng bạn đã được ghép đôi với ${members[random].name}`, 74 | attachment: fs.createReadStream(pathSave) 75 | }, () => { 76 | fs.unlinkSync(pathSave); 77 | }); 78 | 79 | } 80 | }; -------------------------------------------------------------------------------- /scripts/cmds/notification.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "notification", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "Gửi thông báo từ admin đến all box", 11 | longDescription: "Gửi thông báo từ admin đến all box", 12 | category: "owner", 13 | guide: "{p}{n} <tin nhắn>", 14 | envConfig: { 15 | delayPerGroup: 250 16 | } 17 | }; 18 | 19 | module.exports = { 20 | config: this.config, 21 | start: async function ({ message, api, client, event, args, download, globalGoat }) { 22 | const fs = require("fs-extra"); 23 | const axios = require("axios"); 24 | const { delayPerGroup } = globalGoat.configCommands.envCommands["notification"]; 25 | if (!args[0]) return message.reply("Vui lòng nhập tin nhắn bạn muốn gửi đến tất cả các nhóm"); 26 | const formSend = { 27 | body: "Thông báo từ admin bot\n────────────────\n" + args.join(" ") 28 | }; 29 | const attachmentSend = []; 30 | const arrPathSave = []; 31 | 32 | async function getAttachments(attachments) { 33 | let startFile = 0; 34 | for (const data of attachments) { 35 | const ext = data.type == "photo" ? "jpg" : 36 | data.type == "video" ? "mp4" : 37 | data.type == "animated_image" ? "gif" : 38 | data.type == "audio" ? "mp3" : 39 | "txt"; 40 | const pathSave = __dirname + `/cache/notification${startFile}.${ext}`; 41 | ++startFile; 42 | const url = data.url; 43 | const res = await axios.get(url, { 44 | responseType: "arraybuffer" 45 | }); 46 | fs.writeFileSync(pathSave, Buffer.from(res.data)); 47 | attachmentSend.push(fs.createReadStream(pathSave)); 48 | arrPathSave.push(pathSave); 49 | } 50 | } 51 | 52 | if (event.messageReply) { 53 | if (event.messageReply.attachments.length > 0) { 54 | await getAttachments(event.messageReply.attachments); 55 | } 56 | } 57 | else if (event.attachments.length > 0) { 58 | await getAttachments(event.attachments); 59 | } 60 | 61 | if (attachmentSend.length > 0) formSend.attachment = attachmentSend; 62 | const allThreadID = (await api.getThreadList(500, null, ["INBOX"])).filter(item => item.isGroup === true && item.threadID != event.threadID).map(item => item = item.threadID); 63 | 64 | let sendSucces = 0; 65 | let sendError = []; 66 | 67 | for (let tid of allThreadID) { 68 | let errorWhenSend = false; 69 | api.sendMessage(formSend, tid, async function (err) { 70 | if (err) { 71 | sendError.push(tid); 72 | errorWhenSend = true; 73 | } 74 | await new Promise(resolve => setTimeout(resolve, delayPerGroup)); 75 | }); 76 | if (errorWhenSend === true) continue; 77 | ++sendSucces; 78 | } 79 | 80 | message.reply(`Đã gửi thông báo đến ${sendSucces} nhóm thành công\n${sendError.length > 0 ? `Có lỗi xảy ra khi gửi đến ${sendError.length} nhóm` : ""}`); 81 | for (const pathSave of arrPathSave) fs.unlinkSync(pathSave); 82 | } 83 | }; -------------------------------------------------------------------------------- /scripts/cmds/count.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "count", 3 | version: "1.0.3", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Đếm tin nhắn nhóm", 11 | longDescription: "Xem số lượng tin nhắn của tất cả thành viên hoặc bản thân (tính từ lúc bot vào nhóm)", 12 | category: "box chat", 13 | guide: "{prefix}count: dùng để xem số lượng tin nhắn của bạn" 14 | + "\n{prefix}count @tag: dùng để xem số lượng tin nhắn của những người được tag" 15 | + "\n{prefix}count all: dùng để xem số lượng tin nhắn của tất cả thành viên" 16 | }; 17 | 18 | module.exports = { 19 | config: this.config, 20 | start: async function ({ args, threadsData, message, event, globalGoat, api }) { 21 | const { threadID, senderID, messageID } = event; 22 | const threadData = await threadsData.getData(threadID); 23 | const { members } = threadData; 24 | const arraySort = []; 25 | const usersInGroup = (await api.getThreadInfo(threadID)).participantIDs; 26 | for (let id in members) { 27 | if (!usersInGroup.includes(id)) continue; 28 | const count = members[id].count; 29 | const name = members[id].name; 30 | arraySort.push({ name, count, uid: id }); 31 | } 32 | let stt = 1; 33 | arraySort.sort((a, b) => b.count - a.count); 34 | arraySort.map(item => item.stt = stt++); 35 | 36 | if (args[0]) { 37 | if (args[0].toLowerCase() == "all") { 38 | let msg = "Số tin nhắn của các thành viên:\n"; 39 | for (const item of arraySort) { 40 | if (item.count > 0) msg += `\n${item.stt}/ ${item.name}: ${item.count}`; 41 | } 42 | message.reply(msg + "\n\nNhững người không có tên trong danh sách là chưa gửi tin nhắn nào"); 43 | } 44 | else if (event.mentions) { 45 | let msg = ""; 46 | for (const id in event.mentions) { 47 | const findUser = arraySort.find(item => item.uid == id); 48 | msg += `${findUser.name} hạng ${findUser.stt} với ${findUser.count} tin nhắn\n`; 49 | } 50 | message.reply(msg); 51 | } 52 | } 53 | else { 54 | return message.reply(`Bạn đứng hạng ${arraySort.find(item => item.uid == senderID).stt} và đã gửi ${members[senderID].count} tin nhắn trong nhóm này`); 55 | } 56 | }, 57 | 58 | whenChat: async ({ args, threadsData, message, client, event, api }) => { 59 | try { 60 | let { senderID, threadID, messageID, isGroup } = event; 61 | if (!client.allThreadData[threadID]) await threadsData.createData(threadID); 62 | const members = (await threadsData.getData(threadID)).members; 63 | 64 | if (!members[senderID]) { 65 | members[senderID] = { 66 | id: senderID, 67 | name: (await api.getUserInfo(senderID))[senderID].name, 68 | nickname: null, 69 | inGroup: true, 70 | count: 1 71 | }; 72 | await threadsData.setData(threadID, { members }); 73 | } 74 | else members[senderID].count += 1; 75 | await threadsData.setData(threadID, { members }); 76 | } 77 | catch (err) { } 78 | } 79 | 80 | }; -------------------------------------------------------------------------------- /scripts/cmds/avatar.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "avatar", 3 | version: "1.0.5", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "tạo avatar anime", 11 | longDescription: "tạo avatar anime với chữ ký", 12 | category: "image", 13 | guide: { 14 | body: "{p}{n} <mã số nhân vật hoặc tên nhân vật> | <chữ nền> | <chữ ký> | <tên màu tiếng anh hoặc mã màu nền (hex color)>\n{p}{n} help: xem cách dùng lệnh", 15 | attachment: { 16 | [__dirname + "/cache/hexcolor.png"]: "https://seotct.com/wp-content/uploads/2020/03/code-backgroud.png" 17 | } 18 | } 19 | }; 20 | 21 | module.exports = { 22 | config: this.config, 23 | start: async function ({ args, message }) { 24 | const axios = require("axios"); 25 | if (!args[0] || args[0] == "help") message.guideCmd(); 26 | else { 27 | message.reply(`Đang khởi tạo hình ảnh, vui lòng chờ đợi...`); 28 | const content = args.join(" ").split("|").map(item => item = item.trim()); 29 | let idNhanVat, tenNhanvat; 30 | const chu_Nen = content[1]; 31 | const chu_Ky = content[2]; 32 | const colorBg = content[3]; 33 | try { 34 | const dataChracter = (await axios.get("https://goatbot.up.railway.app/taoanhdep/listavataranime?apikey=ntkhang")).data.data; 35 | if (!isNaN(content[0])) { 36 | idNhanVat = parseInt(content[0]); 37 | const totalCharacter = dataChracter.length - 1; 38 | if (idNhanVat > totalCharacter) return message.reply(`Hiện tại chỉ có ${totalCharacter} nhân vật trên hệ thống, vui lòng nhập id nhân vật nhỏ hơn`); 39 | tenNhanvat = dataChracter[idNhanVat].name; 40 | } 41 | else { 42 | const findChracter = dataChracter.find(item => item.name.toLowerCase() == content[0].toLowerCase()); 43 | if (findChracter) { 44 | idNhanVat = findChracter.stt; 45 | tenNhanvat = content[0]; 46 | } 47 | else return message.reply("Không tìm thấy nhân vật mang tên " + content[0] + " trong danh sách nhân vật"); 48 | } 49 | } 50 | catch (error) { 51 | const err = error.response.data; 52 | return message.reply(`Đã xảy ra lỗi lấy dữ liệu nhân vật:\n${err.name}: ${err.message}`); 53 | } 54 | 55 | const endpoint = `https://goatbot.up.railway.app/taoanhdep/avataranime`; 56 | const params = { 57 | id: idNhanVat, 58 | chu_Nen, 59 | chu_Ky, 60 | apikey: "ntkhangGoatBot" 61 | }; 62 | if (colorBg) params.colorBg = colorBg; 63 | 64 | try { 65 | const response = await axios.get(endpoint, { 66 | params, 67 | responseType: "stream" 68 | }); 69 | response.data.path = "avatar.png"; 70 | message.reply({ 71 | body: `✅ Avatar của bạn\nNhân vật: ${tenNhanvat}\nMã số: ${idNhanVat}\nChữ nền: ${chu_Nen}\nChữ ký: ${chu_Ky}\nMàu: ${colorBg || "mặc định"}`, 72 | attachment: response.data 73 | }); 74 | } 75 | catch (error) { 76 | error.response.data.on("data", function (e) { 77 | const err = JSON.parse(e); 78 | message.reply(`Đã xảy ra lỗi ${err.name}: ${err.message}`); 79 | }); 80 | } 81 | } 82 | } 83 | }; -------------------------------------------------------------------------------- /scripts/cmds/rank.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "rank", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Xem level của người dùng", 11 | longDescription: "Xem level của bạn hoặc người được tag. Có thể tag nhiều người", 12 | category: "rank", 13 | guide: "{p}{n} [để trống | @tag]", 14 | envGlobal: { 15 | tokenFacebook: "6628568379%7Cc1e620fa708a1d5696fb991c1bde5662" 16 | }, 17 | }; 18 | 19 | module.exports = { 20 | config: this.config, 21 | start: async function ({ message, event, usersData, threadsData, globalGoat }) { 22 | const axios = require("axios"); 23 | const qs = require("querystring"); 24 | const { writeFileSync, unlinkSync, createReadStream } = require("fs-extra"); 25 | 26 | const TOKEN = globalGoat.configCommands.envGlobal.tokenFacebook; 27 | 28 | let targetUsers; 29 | const arrayMentions = Object.keys(event.mentions); 30 | 31 | if (arrayMentions.length == 0) targetUsers = [event.senderID]; 32 | else targetUsers = arrayMentions; 33 | 34 | function expToLevel(exp) { 35 | const deltaNext = 5; 36 | return Math.floor((1 + Math.sqrt(1 + 8 * exp / deltaNext)) / 2); 37 | } 38 | 39 | function levelToExp(level) { 40 | const deltaNext = 5; 41 | return Math.floor(((Math.pow(level, 2) - level) * deltaNext) / 2); 42 | } 43 | 44 | for (let userID of targetUsers) { 45 | const totalExpUser = (await usersData.getData(userID)).exp; 46 | 47 | const levelUser = expToLevel(totalExpUser); 48 | 49 | const expNextLevel = levelToExp(levelUser + 1) - levelToExp(levelUser); 50 | const currentExp = expNextLevel - (levelToExp(levelUser + 1) - totalExpUser); 51 | 52 | const expAllUser = await usersData.getAll(["exp", "name"]); 53 | expAllUser.sort((a, b) => b.exp - a.exp); 54 | const rank = expAllUser.findIndex(user => user.id == userID) + 1; 55 | 56 | const defaultDesignCard = { 57 | widthCard: 2000, 58 | heightCard: 500, 59 | main_color: "#474747", 60 | sub_color: "rgba(255, 255, 255, 0.5)", 61 | alpha_subcard: 0.9, 62 | exp_color: "#e1e1e1", 63 | expNextLevel_color: "#3f3f3f", 64 | text_color: "#000000" 65 | }; 66 | 67 | const threadInfo = await threadsData.getData(event.threadID); 68 | let { customRankCard } = threadInfo.data; 69 | if (!customRankCard) customRankCard = {}; 70 | const dataLevel = { 71 | exp: currentExp, 72 | expNextLevel, 73 | name: expAllUser[rank - 1].name, 74 | rank: `#${rank}/${expAllUser.length}`, 75 | level: levelUser, 76 | avatar: `https://graph.facebook.com/${userID}/picture?width=512&height=512&access_token=${TOKEN}` 77 | }; 78 | 79 | const stringBody = qs.stringify({ 80 | ...defaultDesignCard, 81 | ...customRankCard, 82 | ...dataLevel 83 | }); 84 | 85 | axios.get("https://goatbot.up.railway.app/taoanhdep/makerankcard?" + stringBody, { 86 | responseType: "arraybuffer" 87 | }) 88 | .then(data => { 89 | writeFileSync("./rank.png", Buffer.from(data.data)); 90 | message.reply({ 91 | attachment: createReadStream("./rank.png") 92 | }, (e, i) => unlinkSync("./rank.png")); 93 | }) 94 | .catch(err => { 95 | console.log(err.response.data.toString()); 96 | }); 97 | } 98 | 99 | }, 100 | 101 | whenChat: async function ({ usersData, client, event }) { 102 | if (!client.allUserData[event.senderID]) await usersData.createData(event.senderID); 103 | let exp = (await usersData.getData(event.senderID)).exp; 104 | if (isNaN(exp)) exp = 0; 105 | try { 106 | await usersData.setData(event.senderID, { 107 | exp: exp + 1 108 | }); 109 | } 110 | catch (e) { } 111 | } 112 | }; -------------------------------------------------------------------------------- /scripts/cmds/callad.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "callad", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "gửi báo cáo về admin bot", 11 | longDescription: "gửi báo cáo, góp ý, báo lỗi,... của bạn về admin bot", 12 | category: "contacts admin", 13 | guide: "{prefix}{name} <tin nhắn>" 14 | }; 15 | 16 | module.exports = { 17 | config: this.config, 18 | start: async function ({ globalGoat, args, message, api, event, usersData, threadsData }) { 19 | if (!args[0]) return message.reply("Vui lòng nhập tin nhắn bạn muốn gửi về admin"); 20 | const { senderID, threadID, isGroup } = event; 21 | 22 | const userData = await usersData.getData(senderID); 23 | const nameSender = userData.name; 24 | let msg = "==📨️ Báo cáo 📨️==" 25 | + `\n${userData.gender == 2 ? "🚹" : "🚺"} Name: ${nameSender}` 26 | + `\n🆔 User ID: ${senderID}`; 27 | 28 | msg += `\n👨‍👩‍👧‍👦 Từ ` + (isGroup ? `nhóm: ${(await threadsData.getData(threadID)).name}` 29 | + `\n🆔 Thread ID: ${threadID}` : "cá nhân"); 30 | 31 | api.sendMessage({ 32 | body: msg + `\n🆎 Nội dung: ${args.join(" ")}\n─────────────────\nPhản hồi tin nhắn này để gửi tin nhắn về người dùng`, 33 | mentions: [{ 34 | id: senderID, 35 | tag: nameSender 36 | }] 37 | }, globalGoat.config.adminBot[0], (err, info) => { 38 | if (err) return message.reply(`Đã xảy ra lỗi: ${err.name ? err.name + " " + err.message : err.errorSummary + "\n" + err.errorDescription}`); 39 | message.reply("Đã gửi báo cáo của bạn về admin thành công"); 40 | globalGoat.whenReply[info.messageID] = { 41 | nameCmd: this.config.name, 42 | messageID: info.messageID, 43 | messageIDSender: event.messageID, 44 | threadIDSender: threadID, 45 | type: "userCallAdmin" 46 | }; 47 | }); 48 | }, 49 | 50 | whenReply: async ({ globalGoat, args, event, api, message, Reply, usersData }) => { 51 | const { messageIDSender, threadIDSender, type } = Reply; 52 | const nameSender = (await usersData.getData(event.senderID)).name; 53 | 54 | switch (type) { 55 | case "userCallAdmin": 56 | api.sendMessage({ 57 | body: `📍 Phản hồi từ admin ${nameSender}\n${args.join(" ")}` 58 | + `\n─────────────────\nPhản hồi tin nhắn này để tiếp tục gửi tin nhắn về admin`, 59 | mentions: [{ 60 | id: event.senderID, 61 | tag: nameSender 62 | }] 63 | }, threadIDSender, (err, info) => { 64 | if (err) return message.reply(`Đã xảy ra lỗi: ${err.name ? err.name + " " + err.message : err.errorSummary + "\n" + err.errorDescription}`); 65 | globalGoat.whenReply[info.messageID] = { 66 | nameCmd: this.config.name, 67 | messageID: info.messageID, 68 | messageIDSender: event.messageID, 69 | threadIDSender: event.threadID, 70 | type: "adminReply" 71 | }; 72 | }, messageIDSender); 73 | break; 74 | case "adminReply": 75 | api.sendMessage({ 76 | body: `📝 Phản hồi từ người dùng ${nameSender}:` 77 | + `\n🆔: ${event.senderID}` 78 | + `\n🗣️: ${nameSender}` 79 | + `\nNội dung:\n${args.join(" ")}` 80 | + `\n─────────────────\nPhản hồi tin nhắn này để gửi tin nhắn về người dùng`, 81 | mentions: [{ 82 | id: event.senderID, 83 | tag: nameSender 84 | }] 85 | }, threadIDSender, (err, info) => { 86 | if (err) return message.reply(`Đã xảy ra lỗi: ${err.name ? err.name + " " + err.message : err.errorSummary + "\n" + err.errorDescription}`); 87 | globalGoat.whenReply[info.messageID] = { 88 | nameCmd: this.config.name, 89 | messageID: info.messageID, 90 | messageIDSender: event.messageID, 91 | threadIDSender: event.threadID, 92 | type: "userCallAdmin" 93 | }; 94 | }, messageIDSender); 95 | break; 96 | default: 97 | break; 98 | } 99 | 100 | } 101 | }; -------------------------------------------------------------------------------- /scripts/cmds/wordlink.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "wordlink", 3 | version: "1.0.0", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "game nối chữ", 11 | longDescription: "chơi game nối chữ cùng bot", 12 | category: "game", 13 | guide: "{prefix}wordlink: dùng để bật game nối chữ" 14 | + "\n{prefix}wordlink rank: xem bảng xếp hạng" 15 | }; 16 | 17 | module.exports = { 18 | config: this.config, 19 | start: async function ({ globalGoat, args, message, event, usersData }) { 20 | const { writeFileSync, existsSync } = require("fs-extra"); 21 | const { threadID, messageID, senderID } = event; 22 | 23 | const database = require(__dirname + "/database/custom.json"); 24 | if (!database.wordlink) database.wordlink = { 25 | point: [], 26 | }; 27 | writeFileSync(__dirname + "/database/custom.json", JSON.stringify(database, null, 2)); 28 | 29 | if (args[0] && args[0].toLowerCase() == "rank") { 30 | var top = database.wordlink.hightPoint.sort((a, b) => b.point - a.point); 31 | var msg = "", i = 1; 32 | for (let item of top) { 33 | msg += `\nTop ${i}: ${(await usersData.getData(item.id)).name} với ${item.point} điểm`; 34 | i++; 35 | } 36 | return message.reply(msg); 37 | } 38 | message.reply(`Đã bật game nối chữ\nHãy reply tin nhắn này với 2 từ để bắt đầu trò chơi`, (err, info) => { 39 | globalGoat.whenReply[info.messageID] = { 40 | nameCmd: require(__filename).config.name, 41 | messageID: info.messageID, 42 | senderID 43 | }; 44 | }); 45 | }, 46 | 47 | whenReply: async ({ Reply, globalGoat, client, message, event }) => { 48 | const { threadID, messageID, senderID, body } = event; 49 | if (!body || senderID != Reply.senderID) return; 50 | const axios = require("axios"); 51 | const fs = require("fs-extra"); 52 | const args = body.split(" "); 53 | 54 | const database = require(__dirname + "/database/custom.json"); 55 | const Data = database.wordlink; 56 | if (!Data || args.length != 2) return; 57 | if (!Data.hightPoint.some(item => item.id == senderID)) Data.hightPoint.push({ id: senderID, point: 0 }); 58 | const { cache } = client; 59 | if (!cache.wordlink) cache.wordlink = []; 60 | const cacheWordlink = cache.wordlink; 61 | if (!cacheWordlink.some(item => item.id == senderID)) { 62 | cacheWordlink.push({ 63 | id: senderID, 64 | wordConnect: null, 65 | currentPoint: 0 66 | }); 67 | } 68 | const dataWLuser = cacheWordlink.find(item => item.id == senderID); 69 | if (dataWLuser.wordConnect != args[0].toLowerCase() && dataWLuser.wordConnect != null) return; 70 | 71 | const word = (await axios.get("http://goatbot.tk/api/wordlink?text=" + encodeURI(args.join(" ")))).data.data; 72 | 73 | var currentPoint = dataWLuser.currentPoint; 74 | var hightPoint = Data.hightPoint.find(item => item.id == senderID).point || 0; 75 | 76 | if (currentPoint > hightPoint) { 77 | hightPoint = currentPoint; 78 | Data.hightPoint.find(item => item.id == senderID).point = hightPoint; 79 | fs.writeFileSync(__dirname + "/database/custom.json", JSON.stringify(database, null, 2)); 80 | } 81 | 82 | var top = Data.hightPoint.sort((a, b) => b.point - a.point); 83 | if (word == "You Lose!!") { 84 | message.reply(`Bạn đã thua\n• Điểm lần này là: ${currentPoint}\n• Điểm cao nhất là: ${hightPoint}\n• Top #${top.findIndex(item => item.id == senderID) + 1} trong bảng xếp hạng`); 85 | dataWLuser.currentPoint = 0; 86 | dataWLuser.wordConnect = null; 87 | return; 88 | } 89 | const wordConnect = word.split(" ")[1]; 90 | message.reply(`${word}\nTừ liên kết là "${wordConnect}", reply tin nhắn này với từ tiếp theo để tiếp tục chơi`, (err, info) => { 91 | globalGoat.whenReply[info.messageID] = { 92 | nameCmd: require(__filename).config.name, 93 | messageID: info.messageID, 94 | senderID 95 | }; 96 | }); 97 | dataWLuser.currentPoint = currentPoint + 1; 98 | dataWLuser.wordConnect = wordConnect; 99 | } 100 | }; -------------------------------------------------------------------------------- /scripts/cmds/customrankcard.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "customrankcard", 3 | version: "1.0.1", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Thiết kế thẻ rank", 11 | longDescription: "Thiết kế thẻ rank theo ý bạn", 12 | category: "rank", 13 | guide: { 14 | body: "{p}{n} [maincolor | subcolor | expcolor | expnextlevelcolor | alphasubcolor | textcolor | reset] <value>\nTrong đó: " 15 | + "\n+ Maincolor: background chính của thẻ rank (hex color or rgba or url image)" 16 | + "\n+ Subcolor: background phụ (hex color or rgba or url image)" 17 | + "\n+ Expcolor: màu của thanh exp hiện tại" 18 | + "\n+ Expnextlevelcolor: màu của thanh exp full" 19 | + "\n+ Alphasubcolor: độ mờ của background phụ (từ 0 -> 1)" 20 | + "\n Textcolor: màu của chữ (hex color or rgba)" 21 | + "\n Reset: reset về mặc định" 22 | + "\n\nVí dụ:" 23 | + "\n {p}{n} maincolor #fff000" 24 | + "\n {p}{n} subcolor rgba(255,136,86,0.4)" 25 | + "\n {p}{n} reset", 26 | attachment: { 27 | [__dirname + "/src/image/helpcustomrankcard.jpg"]: "https://github.com/ntkhang03/resources-goat-bot/raw/master/image/helpcustomrankcard.jpg" 28 | } 29 | } 30 | }; 31 | 32 | module.exports = { 33 | config: this.config, 34 | start: async function ({ message, threadsData, event, args }) { 35 | const axios = require("axios"); 36 | 37 | const threadInfo = await threadsData.getData(event.threadID); 38 | 39 | const dataThread = threadInfo.data; 40 | if (!dataThread.customRankCard) dataThread.customRankCard = {}; 41 | let oldDesign = dataThread.customRankCard; 42 | if (!args[0]) return message.SyntaxError(); 43 | const key = args[0].toLowerCase(); 44 | const value = args.slice(1).join(" "); 45 | 46 | const rgbRegex = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/; 47 | const checkUrlRegex = /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/; 48 | const hexColorRegex = /^#([0-9a-f]{6})$/i; 49 | 50 | if (["subcolor", "maincolor", "expcolor", "expnextlevelcolor"].includes(key)) { 51 | // if image url 52 | if (value.match(checkUrlRegex)) { 53 | const response = await axios.get("https://goatbot.up.railway.app/taoanhdep/checkurlimage?url=" + encodeURIComponent(value)); 54 | if (response.data == false) return message.reply("Url hình ảnh không hợp lệ, vui lòng chọn 1 url với trang đích là hình ảnh"); 55 | key == "maincolor" ? oldDesign.main_color = value 56 | : key == "subcolor" ? oldDesign.sub_color = value 57 | : key == "expcolor" ? oldDesign.exp_color = value 58 | : key == "textcolor" ? oldDesign.text_color = value 59 | : oldDesign.expNextLevel_color = value; 60 | } 61 | else { 62 | // if color 63 | if (!value.match(rgbRegex) && !value.match(hexColorRegex)) return message.reply("Mã màu không hợp lệ, vui lòng nhập mã hex color (6 chữ số) hoặc mã màu rgba"); 64 | key == "maincolor" ? oldDesign.main_color = value 65 | : key == "subcolor" ? oldDesign.sub_color = value 66 | : key == "expcolor" ? oldDesign.exp_color = value 67 | : key == "textcolor" ? oldDesign.text_color = value 68 | : oldDesign.expNextLevel_color = value; 69 | } 70 | await threadsData.setData(event.threadID, { 71 | data: dataThread 72 | }, (e, i) => { 73 | if (e) return message.reply("Đã xảy ra lỗi vui lòng thử lại sau\n" + e.name + ": " + e.message); 74 | message.reply("Đã lưu thay đổi của bạn"); 75 | }); 76 | } 77 | else if (key == "alphasubcolor" || key == "alphasubcard") { 78 | if (parseFloat(value) < 0 && parseFloat(value) > 1) return message.reply("Vui lòng chọn chỉ số trong khoảng từ 0 -> 1"); 79 | oldDesign.alpha_subcard = parseFloat(value); 80 | await threadsData.setData(event.threadID, { 81 | data: dataThread 82 | }, (e, i) => { 83 | if (e) return message.reply("Đã xảy ra lỗi vui lòng thử lại sau\n" + e.name + ": " + e.message); 84 | message.reply("Đã lưu thay đổi của bạn"); 85 | }); 86 | } 87 | else if (key == "reset") { 88 | dataThread.customRankCard = {}; 89 | await threadsData.setData(event.threadID, { 90 | data: dataThread 91 | }, (e, i) => { 92 | if (e) return message.reply("Đã xảy ra lỗi vui lòng thử lại sau\n" + e.name + ": " + e.message); 93 | message.reply("Đã lưu thay đổi của bạn (reset)"); 94 | }); 95 | } 96 | else message.SyntaxError(); 97 | 98 | } 99 | }; -------------------------------------------------------------------------------- /scripts/cmds/weather.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | config: { 3 | name: "weather", 4 | version: "1.0.0", 5 | author: { 6 | name: "NTKhang", 7 | contacts: "" 8 | }, 9 | cooldowns: 5, 10 | role: 0, 11 | shortDescription: "dự báo thời tiết", 12 | longDescription: "xem dự báo thời tiết trong 5 ngày", 13 | category: "other", 14 | guide: "{prefix}{name} <địa điểm>", 15 | envGlobal: { 16 | weatherApiKey: "d7e795ae6a0d44aaa8abb1a0a7ac19e4" 17 | } 18 | }, 19 | start: async function ({ globalGoat, args, message }) { 20 | const axios = require("axios"); 21 | const apikey = globalGoat.configCommands.envGlobal.weatherApiKey; 22 | const moment = require("moment-timezone"); 23 | const Canvas = require("canvas"); 24 | const fs = require("fs-extra"); 25 | 26 | const area = args.join(" "); 27 | if (!area) return message.reply("Vui lòng nhập địa điểm"); 28 | let areaKey, location = {}, dataWeather; 29 | 30 | try { 31 | const response = (await axios.get(`https://api.accuweather.com/locations/v1/cities/search.json?q=${encodeURIComponent(area)}&apikey=${apikey}&language=vi-vn`)).data; 32 | if (response.length == 0) return message.reply(`Không thể tìm thấy địa điểm: ${area}`); 33 | const data = response[0]; 34 | areaKey = data.Key; 35 | location = { 36 | latitude: data.GeoPosition.Latitude, 37 | longitude: data.GeoPosition.Longitude 38 | }; 39 | } 40 | catch (err) { 41 | return message.reply(`Đã xảy ra lỗi: ${err.response.data.Message}`); 42 | } 43 | 44 | try { 45 | dataWeather = (await axios.get(`http://api.accuweather.com/forecasts/v1/daily/10day/${areaKey}?apikey=${apikey}&details=true&language=vi`)).data; 46 | } 47 | catch (err) { 48 | return message.reply(`Đã xảy ra lỗi: ${err.response.data.Message}`); 49 | } 50 | function convertFtoC(F) { 51 | return Math.floor((F - 32) / 1.8); 52 | } 53 | function formatHours(hours) { 54 | return moment(hours).tz("Asia/Ho_Chi_Minh").format("HH[h]mm[p]"); 55 | } 56 | const dataWeatherDaily = dataWeather.DailyForecasts; 57 | const dataWeatherToday = dataWeatherDaily[0]; 58 | let msg = `Thời tiết hôm nay:\n${dataWeather.Headline.Text}` 59 | + `\n🌡 Nhiệt độ thấp nhất - cao nhất: ${convertFtoC(dataWeatherToday.Temperature.Minimum.Value)}°C - ${convertFtoC(dataWeatherToday.Temperature.Maximum.Value)}°C` 60 | + `\n🌡 Nhiệt độ cảm nhận được: ${convertFtoC(dataWeatherToday.RealFeelTemperature.Minimum.Value)}°C - ${convertFtoC(dataWeatherToday.RealFeelTemperature.Maximum.Value)}°C` 61 | + `\n🌅 Mặt trời mọc: ${formatHours(dataWeatherToday.Sun.Rise)}` 62 | + `\n🌄 Mặt trời lặn ${formatHours(dataWeatherToday.Sun.Set)}` 63 | + `\n🌃 Mặt trăng mọc: ${formatHours(dataWeatherToday.Moon.Rise)}` 64 | + `\n🏙️ Mặt trăng lặn: ${formatHours(dataWeatherToday.Moon.Set)}` 65 | + `\n🌞 Ban ngày: ${dataWeatherToday.Day.LongPhrase}` 66 | + `\n🌙 Ban đêm: ${dataWeatherToday.Night.LongPhrase}`; 67 | 68 | Canvas.registerFont( 69 | __dirname + "/src/font/BeVietnamPro-SemiBold.ttf", { 70 | family: "BeVietnamPro-SemiBold" 71 | }); 72 | Canvas.registerFont( 73 | __dirname + "/src/font/BeVietnamPro-Regular.ttf", { 74 | family: "BeVietnamPro-Regular" 75 | }); 76 | 77 | const bg = await Canvas.loadImage(__dirname + "/src/image/bgweather.jpg"); 78 | const { width, height } = bg; 79 | const canvas = Canvas.createCanvas(width, height); 80 | const ctx = canvas.getContext(`2d`); 81 | ctx.drawImage(bg, 0, 0, width, height); 82 | let X = 100; 83 | ctx.fillStyle = "#ffffff"; 84 | const data = dataWeather.DailyForecasts.slice(0, 7); 85 | for (let item of data) { 86 | const icon = await Canvas.loadImage("http://vortex.accuweather.com/adc2010/images/slate/icons/" + item.Day.Icon + ".svg"); 87 | ctx.drawImage(icon, X, 210, 80, 80); 88 | 89 | ctx.font = "30px BeVietnamPro-SemiBold"; 90 | const maxC = `${convertFtoC(item.Temperature.Maximum.Value)}°C `; 91 | ctx.fillText(maxC, X, 366); 92 | 93 | ctx.font = "30px BeVietnamPro-Regular"; 94 | const minC = String(`${convertFtoC(item.Temperature.Minimum.Value)}°C`); 95 | const day = moment(item.Date).format("DD"); 96 | ctx.fillText(minC, X, 445); 97 | ctx.fillText(day, X + 20, 140); 98 | 99 | X += 135; 100 | } 101 | const pathSaveImg = __dirname + "/cache/weather.jpg"; 102 | fs.writeFileSync(pathSaveImg, canvas.toBuffer()); 103 | 104 | return message.reply({ 105 | body: msg, 106 | attachment: fs.createReadStream(pathSaveImg) 107 | }, () => fs.unlinkSync(pathSaveImg)); 108 | 109 | } 110 | }; -------------------------------------------------------------------------------- /scripts/cmds/user.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "user", 3 | version: "1.0.4", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "Quản lý người dùng", 11 | longDescription: "Quản lý người dùng trong hệ thống bot", 12 | category: "owner", 13 | guide: "{prefix}user [find | -f | search | -s] <tên cần tìm>: tìm kiếm người dùng trong dữ liệu bot bằng tên" 14 | + "\n" 15 | + "\n{prefix}user [ban | -b] [<id> | @tag | reply tin nhắn] <reason>: để cấm người dùng mang id <id> hoặc người được tag hoặc người gửi của tin nhắn được reply sử dụng bot" 16 | + "\n" 17 | + "\n{prefix}user unban [<id> | @tag | reply tin nhắn]: để bỏ cấm người dùng sử dụng bot" 18 | }; 19 | 20 | module.exports = { 21 | config: this.config, 22 | start: async function ({ api, args, usersData, message, client, event, setup }) { 23 | const moment = require("moment-timezone"); 24 | const type = args[0]; 25 | // find user 26 | if (["find", "search", "-f", "-s"].includes(type)) { 27 | const allUser = await usersData.getAll(["name"]); 28 | const keyword = args.slice(1).join(" "); 29 | const result = allUser.filter(item => (item.name || "").toLowerCase().includes(keyword.toLowerCase())); 30 | const msg = result.reduce((i, user) => i += `\n╭Name: ${user.name}\n╰ID: ${user.id}`, ""); 31 | message.reply(result.length == 0 ? `❌ Không tìm thấy người dùng nào có tên khớp với từ khóa: ${keyword}` : `🔎Có ${result.length} kết quả phù hợp cho từ khóa "${keyword}":\n${msg}`); 32 | } 33 | // ban user 34 | else if (["ban", "-b"].includes(type)) { 35 | let id, reason; 36 | if (event.type == "message_reply") { 37 | id = event.messageReply.senderID; 38 | reason = args.slice(1).join(" "); 39 | } 40 | else if (Object.keys(event.mentions).length > 0) { 41 | const { mentions } = event; 42 | id = Object.keys(mentions)[0]; 43 | reason = args.slice(1).join(" ").replace(mentions[id], ""); 44 | } 45 | else if (args[1]) { 46 | id = args[1]; 47 | reason = args.slice(2).join(" "); 48 | } 49 | else return message.SyntaxError(); 50 | 51 | if (!id) return message.reply("Id của người cần ban không được để trống, vui lòng nhập id hoặc tag hoặc reply tin nhắn của 1 người theo cú pháp user ban <id> <lý do>"); 52 | if (!reason) return message.reply("Lý do cấm người dùng không được để trống, vui lòng soạn tin nhắn theo cú pháp user ban <id> <lý do>"); 53 | if (!client.allUserData[id]) return message.reply(`Người dùng mang id ${id} không tồn tại trong dữ liệu bot`); 54 | reason = reason.replace(/\s+/g, ' '); 55 | 56 | const userData = await usersData.getData(id); 57 | const name = userData.name; 58 | const status = userData.banned.status; 59 | 60 | if (status) return message.reply(`Người dùng mang id [${id} | ${name}] đã bị cấm từ trước:\n> Lý do: ${userData.banned.reason}\n> Thời gian: ${userData.banned.date}`); 61 | const time = moment.tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY HH:mm:ss"); 62 | await usersData.setData(id, { 63 | banned: { 64 | status: true, 65 | reason, 66 | date: time 67 | } 68 | }, (err) => { 69 | if (err) return message.reply(`Đã xảy ra lỗi ${err.name}: ${err.message}`); 70 | else return message.reply(`Đã cấm người dùng mang id [${id} | ${name}] sử dụng bot.\n> Lý do: ${reason}\n> Thời gian: ${time}`); 71 | }); 72 | } 73 | // unban user 74 | else if (["unban", "-u"].includes(type)) { 75 | let id; 76 | if (event.type == "message_reply") { 77 | id = event.messageReply.senderID; 78 | } 79 | else if (Object.keys(event.mentions).length > 0) { 80 | const { mentions } = event; 81 | id = Object.keys(mentions)[0]; 82 | } 83 | else if (args[1]) { 84 | id = args[1]; 85 | } 86 | else return message.SyntaxError(); 87 | if (!id) return message.reply("Id của người cần unban không được để trống, vui lòng nhập id hoặc tag hoặc reply tin nhắn của 1 người theo cú pháp user unban"); 88 | if (!client.allUserData[id]) return message.reply(`Người dùng mang id ${id} không tồn tại trong dữ liệu bot`); 89 | const userData = await usersData.getData(id); 90 | const name = userData.name; 91 | const status = userData.banned.status; 92 | if (!status) return message.reply(`Hiện tại người dùng mang id [${id} | ${name}] không bị cấm sử dụng bot`); 93 | await usersData.setData(id, { 94 | banned: { 95 | status: false, 96 | reason: null 97 | } 98 | }, (err) => { 99 | if (err) return message.reply(`Đã xảy ra lỗi ${err.name}: ${err.message}`); 100 | else message.reply(`Đã bỏ cấm người dùng mang id [${id} | ${name}], hiện tại người này có thể sử dụng bot`); 101 | }); 102 | } 103 | else return message.SyntaxError(); 104 | } 105 | }; -------------------------------------------------------------------------------- /scripts/cmds/thread.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "thread", 3 | version: "1.0.6", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "Quản lý các nhóm chat", 11 | longDescription: "Quản lý các nhóm chat trong hệ thống bot", 12 | category: "owner", 13 | guide: "{prefix}thread [find | -f | search | -s] <tên cần tìm>: tìm kiếm nhóm chat trong dữ liệu bot bằng tên" 14 | + "\n" 15 | + "\n{prefix}thread [ban | -b] [<id> | để trống] <reason>: dùng để cấm nhóm mang id <id> hoặc nhóm hiện tại sử dụng bot" 16 | + "\nVí dụ:" 17 | + "\n{prefix}thread ban 3950898668362484 spam bot" 18 | + "\n{prefix}thread ban spam quá nhiều" 19 | + "\n" 20 | + "\n{prefix}thread unban [<id> | để trống] để bỏ cấm nhóm mang id <id>" 21 | + "\nhoặc nhóm hiện tại" 22 | }; 23 | 24 | module.exports = { 25 | config: this.config, 26 | start: async function ({ api, args, threadsData, message, client, event }) { 27 | const moment = require("moment-timezone"); 28 | const type = args[0]; 29 | // find thread 30 | if (["find", "search", "-f", "-s"].includes(type)) { 31 | const allThread = await threadsData.getAll(["name"]); 32 | const keyword = args.slice(1).join(" "); 33 | const result = allThread.filter(item => (item.name || "").toLowerCase().includes(keyword.toLowerCase())); 34 | const msg = result.reduce((i, user) => i += `\n╭Name: ${user.name}\n╰ID: ${user.id}`, ""); 35 | message.reply(result.length == 0 ? `❌ Không tìm thấy nhóm nào có tên khớp với từ khoá: ${keyword}` : `🔎Có ${result.length} kết quả phù hợp cho từ khóa "${keyword}":\n${msg}`); 36 | } 37 | // ban thread 38 | else if (["ban", "-b"].includes(type)) { 39 | let id, reason; 40 | if (!isNaN(args[1])) { 41 | id = args[1]; 42 | reason = args.slice(2).join(" "); 43 | } 44 | else { 45 | id = event.threadID; 46 | reason = args.slice(1).join(" "); 47 | } 48 | if (!id || !reason) return message.SyntaxError(); 49 | reason = reason.replace(/\s+/g, ' '); 50 | if (!client.allThreadData[id]) return message.reply(`Nhóm mang id ${id} không tồn tại trong dữ liệu bot`); 51 | const threadData = await threadsData.getData(id); 52 | const name = threadData.name; 53 | const status = threadData.banned.status; 54 | 55 | if (status) return message.reply(`Nhóm mang id [${id} | ${name}] đã bị cấm từ trước:\n> Lý do: ${threadData.banned.reason}\n> Thời gian: ${threadData.banned.date}`); 56 | const time = moment.tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY HH:mm:ss"); 57 | 58 | await threadsData.setData(id, { 59 | banned: { 60 | status: true, 61 | reason, 62 | date: time 63 | } 64 | }, (err) => { 65 | if (err) return message.reply(`Đã xảy ra lỗi ${err.name}: ${err.message}`); 66 | else return message.reply(`Đã cấm nhóm mang id [${id} | ${name}] sử dụng bot.\n> Lý do: ${reason}\n> Thời gian: ${time}`); 67 | }); 68 | } 69 | // unban thread 70 | else if (["unban", "-u"].includes(type)) { 71 | let id; 72 | if (!isNaN(args[1])) id = args[1]; 73 | else id = event.threadID; 74 | if (!id) return message.SyntaxError(); 75 | if (!client.allThreadData[id]) return message.reply(`Nhóm mang id ${id} không tồn tại trong dữ liệu bot`); 76 | 77 | const threadData = await threadsData.getData(id); 78 | const name = threadData.name; 79 | const status = threadData.banned.status; 80 | 81 | if (!status) return message.reply(`Hiện tại nhóm mang id [${id} | ${name}] không bị cấm sử dụng bot`); 82 | await threadsData.setData(id, { 83 | banned: { 84 | status: false, 85 | reason: null 86 | } 87 | }, (err, data) => { 88 | if (err) return message.reply(`Đã xảy ra lỗi ${err.name}: ${err.message}`); 89 | else message.reply(`Đã bỏ cấm nhóm mang id [${id} | ${name}], hiện tại nhóm này có thể sử dụng bot`); 90 | }); 91 | } 92 | // info thread 93 | else if (["info", "-i"].includes(type)) { 94 | let id; 95 | if (!isNaN(args[1])) id = args[1]; 96 | else id = event.threadID; 97 | if (!id) return message.SyntaxError(); 98 | if (!client.allThreadData[id]) return message.reply(`Nhóm mang id ${id} không tồn tại trong dữ liệu bot`); 99 | const threadData = await threadsData.getData(id); 100 | const valuesMember = Object.values(threadData.members).filter(item => item.inGroup); 101 | const msg = `> Thread ID: ${threadData.id}` 102 | + `\n> Name: ${threadData.name}` 103 | + `\n> Create Date: ${moment(threadData.data.createDate).tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY HH:mm:ss")}` 104 | + `\n> Tổng thành viên: ${valuesMember.length}` 105 | + `\n> Nam: ${valuesMember.filter(item => item.gender == "MALE").length} thành viên` 106 | + `\n> Nữ: ${valuesMember.filter(item => item.gender == "FEMALE").length} thành viên` 107 | + `\n> Tổng tin nhắn: ${valuesMember.reduce((i, item) => i += item.count, 0)}` 108 | + `\n- Banned: ${threadData.banned.status}` 109 | + `\n- Reason: ${threadData.banned.reason}` 110 | + `\n- Time: ${threadData.banned.date}`; 111 | return message.reply(msg); 112 | } 113 | else return message.SyntaxError(); 114 | } 115 | }; -------------------------------------------------------------------------------- /bot/loadAllScript.js: -------------------------------------------------------------------------------- 1 | module.exports = async (globalGoat) => { 2 | const chalk = require("chalk"); 3 | const { print, loading, configCommands } = globalGoat; 4 | const { execSync } = require('child_process'); 5 | const { readdirSync, readFileSync, writeFileSync } = require("fs-extra"); 6 | 7 | const folder = ["cmds", "events"]; 8 | 9 | for (const folderModules of folder) { 10 | const makeColor = folderModules == "cmds" ? 11 | "============ LOADING COMMANDS ============" : 12 | "========= LOADING COMMANDS EVENTS ========="; 13 | console.log(chalk.blue(makeColor)); 14 | const commandError = []; 15 | let text = "", typeEnvCommand = "", setMap = ""; 16 | if (folderModules == "cmds") { 17 | text = "command"; 18 | typeEnvCommand = "envCommands"; 19 | setMap = "commands"; 20 | } 21 | else { 22 | text = "command event"; 23 | typeEnvCommand = "envEvents"; 24 | setMap = "events"; 25 | } 26 | const Files = readdirSync(__dirname + "/../scripts/" + folderModules).filter((item) => item.endsWith(".js")); 27 | 28 | for (const file of Files) { 29 | try { 30 | const pathCommand = __dirname + `/../scripts/${folderModules}/${file}`; 31 | const command = require(pathCommand); 32 | const configCommand = command.config; 33 | // ——————————————— CHECK SYNTAXERROR ——————————————— // 34 | if (!configCommand) throw new Error("Config of command undefined"); 35 | if (!command.start) throw new Error(`Command không được thiếu function start!`); 36 | if (!configCommand.name) throw new Error(`Tên Command không được để trống!`); 37 | const commandName = configCommand.name; 38 | if (globalGoat[setMap].has(commandName)) throw new Error("Tên Command bị trùng lặp với một Command khác"); 39 | // ——————————————— CHECK SHORT NAME ———————————————— // 40 | if (configCommand.shortName) { 41 | let { shortName } = configCommand; 42 | if (typeof shortName == "string") shortName = [shortName]; 43 | for (const aliases of shortName) { 44 | if (globalGoat.shortNameCommands.has(aliases)) throw new Error(`Short Name ${aliases} bị trùng lặp với short name của command ${chalk.hex("#ff5208")(globalGoat.shortNameCommands.get(aliases))}`); 45 | else globalGoat.shortNameCommands.set(aliases, configCommand.name); 46 | } 47 | } 48 | // ————————————————— CHECK PACKAGE ————————————————— // 49 | if (configCommand.packages) { 50 | const packages = (typeof configCommand.packages == "string") ? configCommand.packages.trim().replace(/\s/g, '').split(',') : configCommand.packages; 51 | if (!Array.isArray(packages)) throw new Error("Value packages needs to be array"); 52 | for (const i of packages) { 53 | try { 54 | require(i); 55 | } 56 | catch (err) { 57 | try { 58 | loading(`install package ${chalk.hex("#ff5208")(i)}, wating...`, "INSTALL PACKAGE"); 59 | execSync("npm install " + i + " -s"); 60 | loading(`Đã cài đặt package ${chalk.hex("#ff5208")(i)} cho ${text} ${chalk.hex("#FFFF00")(commandName)} thành công\n`, "PACKAGE"); 61 | } 62 | catch (e) { 63 | loading.err(`Không thể cài đặt package ${chalk.hex("#ff0000")(i)} cho ${text} ${chalk.hex("#ff0000")(commandName)}\n`, "INSTALL PACKAGE FAILED"); 64 | } 65 | } 66 | } 67 | } 68 | // ——————————————— CHECK ENV GLOBAL ——————————————— // 69 | if (configCommand.envGlobal) { 70 | const { envGlobal } = configCommand; 71 | if (typeof envGlobal != "object" && Array.isArray(envGlobal)) throw new Error("envGlobal need to be a object"); 72 | if (!configCommands.envGlobal) configCommands.envGlobal = {}; 73 | for (const i in envGlobal) { 74 | if (!configCommands.envGlobal[i]) configCommands.envGlobal[i] = envGlobal[i]; 75 | else { 76 | let readCommand = readFileSync(pathCommand).toString(); 77 | readCommand = readCommand.replace(envGlobal[i], configCommands.envGlobal[i]); 78 | writeFileSync(pathCommand, readCommand); 79 | } 80 | } 81 | } 82 | // ———————————————— CHECK CONFIG CMD ——————————————— // 83 | if (configCommand.envConfig && typeof configCommand.envConfig == "object") { 84 | if (!configCommands[typeEnvCommand]) configCommands[typeEnvCommand] = {}; 85 | if (!configCommands[typeEnvCommand][commandName]) configCommands[typeEnvCommand][commandName] = {}; 86 | 87 | for (const [key, value] of Object.entries(configCommand.envConfig)) { 88 | if (!configCommands[typeEnvCommand][commandName][key]) configCommands[typeEnvCommand][commandName][key] = value; 89 | else { 90 | let readCommand = readFileSync(pathCommand).toString(); 91 | readCommand = readCommand.replace(value, configCommands[typeEnvCommand][commandName][key]); 92 | writeFileSync(pathCommand, readCommand); 93 | } 94 | } 95 | } 96 | // ——————————————— CHECK RUN ANYTIME ——————————————— // 97 | if (command.whenChat) globalGoat.whenChat.push(commandName); 98 | // ————————————— IMPORT TO GLOBALGOAT ————————————— // 99 | globalGoat[setMap].set(commandName.toLowerCase(), command); 100 | const color = text == "command" ? "#ff7100" : "#00ff2f"; 101 | loading(`${chalk.hex(color)(`[ ${text.toUpperCase()} ]`)} ${chalk.hex("#FFFF00")(commandName)} succes\n`, "LOADED"); 102 | } 103 | catch (error) { 104 | const color = text == "command" ? "#ff7100" : "#00ff2f"; 105 | loading.error(`${chalk.hex(color)(`[ ${text.toUpperCase()} ]`)} ${chalk.hex("#FFFF00")(file)} failed: ${error.message}\n`, "FAILED"); 106 | commandError.push({ name: file, error }); 107 | } 108 | } 109 | if (commandError.length > 0) { 110 | print.err(`Những file ${chalk.yellow(text)} xảy ra lỗi trong quá trình load:`, "LOADED"); 111 | for (const item of commandError) print.err(`${chalk.hex("#ff4112")(item.name)}: ${item.error.stack}`, text.toUpperCase()); 112 | } 113 | } 114 | }; -------------------------------------------------------------------------------- /scripts/cmds/rules.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "rules", 3 | version: "1.0.5", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Quy tắc của nhóm", 11 | longDescription: "Tạo / xem / thêm / sửa / đổi vị trí / xóa nội quy nhóm của bạn", 12 | category: "Box chat", 13 | guide: "{p}{n} [add | -a] <nội quy muốn thêm>: thêm nội quy cho nhóm" 14 | + "\n{p}{n}: xem nội quy của nhóm" 15 | + "\n{p}{n} [edit | -e] <n> <nội dung sau khi sửa>: chỉnh sửa lại nội quy thứ n" 16 | + "\m{p}{n} [move | -m] <stt1> <stt2> hoán đổi vị trí của nội quy thứ <stt1> và <stt2> với nhau" 17 | + "\n{p}{n} [delete | -d] <n>: xóa nội quy theo số thứ tự thứ n" 18 | + "\n{p}{n} [remove | -r]: xóa tất cả nội quy của nhóm" 19 | + "\n" 20 | + "\n-Ví dụ:" 21 | + "\n + {p}{n} add không spam" 22 | + "\n + {p}{n} move 1 3" 23 | + "\n + {p}{n} -e 1 không spam tin nhắn trong nhóm" 24 | + "\n + {p}{n} -d 1" 25 | + "\n + {p}{n} -r" 26 | }; 27 | 28 | module.exports = { 29 | config: this.config, 30 | start: async function ({ api, role, globalGoat, args, message, event, threadsData }) { 31 | const { senderID, threadID, messageID } = event; 32 | 33 | const type = args[0]; 34 | const threadData = await threadsData.getData(threadID); 35 | const dataOfThread = threadData.data; 36 | 37 | if (!dataOfThread.rules) dataOfThread.rules = []; 38 | const rulesOfThread = dataOfThread.rules; 39 | const totalRules = rulesOfThread.length; 40 | 41 | if (!type) { 42 | let i = 1; 43 | const msg = rulesOfThread.reduce((text, rules) => text += `${i++}. ${rules}\n`, ""); 44 | message.reply(msg || "Hiện tại nhóm bạn chưa có bất kỳ nội quy nào, để thêm nội quy cho nhóm hãy sử dụng `rules add`"); 45 | } 46 | else if (["add", "-a"].includes(type)) { 47 | if (role < 1) return message.reply("Chỉ quản trị viên mới có thể thêm nội quy cho nhóm"); 48 | if (!args[1]) return message.reply("Vui lòng nhập nội dụng cho nội quy bạn muốn thêm"); 49 | rulesOfThread.push(args.slice(1).join(" ")); 50 | threadsData.setData(threadID, { 51 | data: dataOfThread 52 | }, (err) => { 53 | if (err) return message.reply("Đã xảy ra lỗi: " + err.name + "\n" + err.message); 54 | message.reply(`Đã thêm nội quy mới cho nhóm`); 55 | }); 56 | } 57 | else if (["edit", "-e"].includes(type)) { 58 | if (role < 1) return message.reply("Chỉ quản trị viên mới có thể chỉnh sửa nội quy nhóm"); 59 | const stt = parseInt(args[1]); 60 | if (isNaN(stt)) return message.reply(`Vui lòng nhập số thứ tự của quy định bạn muốn chỉnh sửa`); 61 | if (!rulesOfThread[stt - 1]) return message.reply(`Không tồn tại nội quy thứ ${stt}, hiện tại nhóm bạn ${totalRules == 0 ? `chưa có nội quy nào được đặt ra` : `chỉ có ${totalRules} nội quy`}`); 62 | if (!args[2]) return message.reply(`Vui lòng nhập nội dung bạn muốn thay đổi cho nội quy thứ ${stt}`); 63 | const newContent = args.slice(2).join(" "); 64 | rulesOfThread[stt - 1] = newContent; 65 | threadsData.setData(threadID, { 66 | data: dataOfThread 67 | }, (err) => { 68 | if (err) return message.reply("Đã xảy ra lỗi: " + err.name + "\n" + err.message); 69 | message.reply(`Đã chỉnh sửa nội quy thứ ${stt} của nhóm thành: ${newContent}`); 70 | }); 71 | } 72 | else if (["move", "-m"].includes(type)) { 73 | if (role < 1) return message.reply("Chỉ quản trị viên mới có thể đổi vị trí nội quy của nhóm"); 74 | const stt1 = parseInt(args[1]); 75 | const stt2 = parseInt(args[2]); 76 | if (isNaN(stt1) || isNaN(stt2)) return message.reply(`Vui lòng nhập số thứ tự của 2 nội quy nhóm bạn muốn chuyển đổi vị trí với nhau`); 77 | if (!rulesOfThread[stt1 - 1] || !rulesOfThread[stt2 - 1]) return message.reply(`Không tồn tại nội quy thứ ${!rulesOfThread[stt1 - 1] ? (stt1 + (!rulesOfThread[stt2 - 1] ? ` và ${stt2}` : '')) : stt2}, hiện tại nhóm bạn ${totalRules == 0 ? `chưa có nội quy nào được đặt ra` : `chỉ có ${totalRules} nội quy`}`); 78 | [rulesOfThread[stt1 - 1], rulesOfThread[stt2 - 1]] = [rulesOfThread[stt2 - 1], rulesOfThread[stt1 - 1]]; 79 | threadsData.setData(threadID, { 80 | data: dataOfThread 81 | }, (err) => { 82 | if (err) return message.reply("Đã xảy ra lỗi: " + err.name + "\n" + err.message); 83 | message.reply(`Đã chuyển đổi vị trí của 2 nội quy thứ ${stt1} và ${stt2}`); 84 | }); 85 | } 86 | else if (["delete", "del", "-d"].includes(type)) { 87 | if (role < 1) return message.reply("Chỉ quản trị viên mới có thể xóa nội quy của nhóm"); 88 | if (!args[1] || isNaN(args[1])) return message.reply("Vui lòng nhập số thứ tự của nội quy bạn muốn xóa"); 89 | const rulesDel = rulesOfThread[parseInt(args[1]) - 1]; 90 | if (!rulesDel) return message.reply(`Không tồn tại nội quy thứ ${args[1]}, hiện tại nhóm bạn có ${totalRules} nội quy`); 91 | rulesOfThread.splice(parseInt(args[1]) - 1, 1); 92 | threadsData.setData(threadID, { 93 | data: dataOfThread 94 | }, (err) => { 95 | if (err) return message.reply("Đã xảy ra lỗi: " + err.name + "\n" + err.message); 96 | message.reply(`Đã xóa nội quy thứ ${args[1]} của nhóm, nội dung: ${rulesDel}`); 97 | }); 98 | } 99 | else if (type == "remove" || type == "-r") { 100 | if (role < 1) return message.reply("Chỉ có quản trị viên nhóm mới có thể xoá bỏ tất cả nội quy của nhóm"); 101 | dataOfThread.rules = []; 102 | threadsData.setData(threadID, { 103 | data: dataOfThread 104 | }, (err) => { 105 | if (err) return message.reply("Đã xảy ra lỗi: " + err.name + "\n" + err.message); 106 | message.reply(`Đã xóa toàn bộ nội quy của nhóm`); 107 | }); 108 | } 109 | else if (!isNaN(type)) { 110 | let msg = ""; 111 | for (const stt of args) { 112 | const rules = rulesOfThread[parseInt(stt) - 1]; 113 | if (rules) msg += `${stt}. ${rules}\n`; 114 | } 115 | message.reply(msg || `Không tồn tại nội quy thứ ${type}, hiện tại nhóm bạn ${totalRules == 0 ? `chưa có nội quy nào được đặt ra` : `chỉ có ${totalRules} nội quy`}`); 116 | } 117 | } 118 | }; 119 | -------------------------------------------------------------------------------- /scripts/cmds/cmd.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "cmd", 3 | version: "1.0.7", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 2, 10 | shortDescription: "Quản lý command", 11 | longDescription: "Quản lý các tệp lệnh của bạn", 12 | category: "owner", 13 | guide: "{prefix}cmd load <tên file lệnh>", 14 | packages: "path" 15 | }; 16 | 17 | module.exports = { 18 | config: this.config, 19 | start: ({ envGlobal, globalGoat, args, download, message, event, client }) => { 20 | const { execSync } = require('child_process'); 21 | const { loading } = globalGoat; 22 | const { join } = require("path"); 23 | const chalk = require("chalk"); 24 | const fs = require("fs-extra"); 25 | const allWhenChat = globalGoat.whenChat; 26 | const { configCommands } = globalGoat; 27 | 28 | const loadCommand = function (filename) { 29 | try { 30 | const pathCommand = __dirname + `/${filename}.js`; 31 | if (!fs.existsSync(pathCommand)) throw new Error(`Không tìm thấy file ${filename}.js`); 32 | const oldCommand = require(join(__dirname, filename + ".js")); 33 | const oldNameCommand = oldCommand.config.name; 34 | const oldEnvConfig = oldCommand.config.envConfig || {}; 35 | const oldEnvGlobal = oldCommand.config.envGlobal || {}; 36 | 37 | if (oldCommand.config.shortName) { 38 | let oldShortName = oldCommand.config.shortName; 39 | if (typeof oldShortName == "string") oldShortName = [oldShortName]; 40 | for (let aliases of oldShortName) globalGoat.shortNameCommands.delete(aliases); 41 | } 42 | 43 | // delete old command 44 | delete require.cache[require.resolve(pathCommand)]; 45 | const command = require(join(__dirname, filename + ".js")); 46 | const configCommand = command.config; 47 | if (!configCommand) throw new Error("Config of command undefined"); 48 | 49 | const nameScript = configCommand.name; 50 | // Check whenChat function 51 | const indexWhenChat = allWhenChat.findIndex(item => item == oldNameCommand); 52 | if (indexWhenChat != -1) allWhenChat[indexWhenChat] = null; 53 | if (command.whenChat) allWhenChat.push(nameScript); 54 | // ------------- 55 | if (configCommand.shortName) { 56 | let { shortName } = configCommand; 57 | if (typeof shortName == "string") shortName = [shortName]; 58 | for (const aliases of shortName) { 59 | if (globalGoat.shortName.has(aliases)) throw new Error(`Short Name ${aliases} bị trùng lặp với short name của command ${chalk.hex("#ff5208")(globalGoat.shortName.get(aliases))}`); 60 | else globalGoat.shortName.set(aliases, configCommand.name); 61 | } 62 | } 63 | let { packages, envGlobal, envConfig } = configCommand; 64 | if (!command.start) throw new Error(`Command không được thiếu function start!`); 65 | if (!configCommand.name) throw new Error(`Tên Command không được để trống!`); 66 | 67 | if (packages) { 68 | typeof packages == "string" ? packages = packages.trim().replace(/\s+/g, '').split(',') : ""; 69 | if (!Array.isArray(packages)) throw new Error("Value packages needs to be array"); 70 | for (let i of packages) { 71 | try { 72 | require(i); 73 | } 74 | catch (err) { 75 | try { 76 | loading(`Install package ${chalk.hex("#ff5208")(i)}`, "PACKAGE"); 77 | execSync("npm install " + i + " -s"); 78 | loading(`Đã cài đặt package ${chalk.hex("#ff5208")(i)} cho Script ${chalk.hex("#FFFF00")(nameScript)} thành công\n`, "PACKAGE"); 79 | } 80 | catch (e) { 81 | loading.err(`Không thể cài đặt package ${chalk.hex("#ff0000")(i)} cho Script ${chalk.hex("#ff0000")(nameScript)} với lỗi: ${e.stack}\n`, "PACKAGE"); 82 | } 83 | } 84 | } 85 | } 86 | // env Global 87 | if (envGlobal && typeof envGlobal == "object") { 88 | if (!configCommands.envGlobal) configCommands.envGlobal = {}; 89 | if (JSON.stringify(envGlobal) != JSON.stringify(oldEnvGlobal)) configCommands.envGlobal = envGlobal; 90 | } 91 | // env Config 92 | if (envConfig && typeof envConfig == "object") { 93 | if (!configCommands.envCommands) configCommands.envCommands = {}; 94 | if (!configCommands.envCommands[nameScript]) configCommands.envCommands[nameScript] = {}; 95 | if (JSON.stringify(configCommands.envCommands[nameScript]) != JSON.stringify(oldEnvConfig)) configCommands.envCommands[nameScript] = envConfig; 96 | } 97 | globalGoat.commands.delete(oldNameCommand); 98 | globalGoat.commands.set(nameScript, command); 99 | fs.writeFileSync(client.dirConfigCommands, JSON.stringify(configCommands, null, 2)); 100 | globalGoat.print.master(`Đã load tệp lệnh ${filename}.js`, "LOADED"); 101 | return { 102 | status: "succes", 103 | name: filename 104 | }; 105 | } 106 | catch (err) { 107 | return { 108 | status: "failed", 109 | name: filename, 110 | error: err 111 | }; 112 | } 113 | }; 114 | 115 | if (args[0] == "load") { 116 | if (!args[1]) return message.reply("Vui lòng nhập vào tên lệnh bạn muốn reload"); 117 | const infoLoad = loadCommand(args[1]); 118 | if (infoLoad.status == "succes") message.reply(`Đã load command ${infoLoad.name} thành công`); 119 | else message.reply(`Load command ${infoLoad.name} thất bại với lỗi\n${infoLoad.error.stack.split("\n").filter(i => i.length > 0).slice(0, 3).join("\n")}`); 120 | globalGoat.whenChat = allWhenChat.filter(item => item != null); 121 | } 122 | else if (args[0].toLowerCase() == "loadall") { 123 | const allFile = fs.readdirSync(__dirname) 124 | .filter(item => item.endsWith(".js")) 125 | .map(item => item = item.split(".")[0]); 126 | const arraySucces = []; 127 | const arrayFail = []; 128 | for (let name of allFile) { 129 | const infoLoad = loadCommand(name); 130 | infoLoad.status == "succes" ? arraySucces.push(name) : 131 | arrayFail.push(`${name}: ${infoLoad.error.name}: ${infoLoad.error.message}`); 132 | } 133 | globalGoat.whenChat = allWhenChat.filter(item => item != null); 134 | message.reply(`Đã load thành công ${arraySucces.length} command` 135 | + `\n${arrayFail.length > 0 ? `\nLoad thất bại ${arrayFail.length} command\n${arrayFail.join("\n")})` : ""}`); 136 | } 137 | else message.SyntaxError(); 138 | } 139 | }; -------------------------------------------------------------------------------- /scripts/cmds/help.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "help", 3 | version: "1.0.11", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "Xem cách dùng lệnh", 11 | longDescription: "Xem cách sử dụng của các lệnh", 12 | category: "info", 13 | guide: "{p}{n} [để trống|<số trang>|<tên lệnh>]", 14 | priority: 1, 15 | packages: "moment-timezone" 16 | }; 17 | 18 | module.exports = { 19 | config: this.config, 20 | start: async function ({ globalGoat, message, args, event, threadsData, download }) { 21 | const moment = require("moment-timezone"); 22 | const { statSync, existsSync, createReadStream } = require("fs-extra"); 23 | const axios = require("axios"); 24 | const { threadID } = event; 25 | const dataThread = await threadsData.getData(threadID); 26 | const prefix = dataThread.prefix || globalGoat.config.prefix; 27 | let sortHelp = dataThread.sortHelp || "name"; 28 | if (!["category", "name"].includes(sortHelp)) sortHelp = "name"; 29 | const commandName = args[0] || ""; 30 | const command = globalGoat.commands.get(commandName.toLowerCase()) || globalGoat.commands.get(globalGoat.shortNameCommands.get(commandName)); 31 | 32 | // ———————————————— LIST ALL COMMAND ——————————————— // 33 | if (!command && !args[0] || !isNaN(args[0])) { 34 | const arrayInfo = []; 35 | let msg = ""; 36 | if (sortHelp == "name") { 37 | const page = parseInt(args[0]) || 1; 38 | const numberOfOnePage = 20; 39 | let i = 0; 40 | for (var [name, value] of (globalGoat.commands)) { 41 | value.config.shortDescription && value.config.shortDescription.length < 40 ? name += ` → ${value.config.shortDescription.charAt(0).toUpperCase() + value.config.shortDescription.slice(1)}` : ""; 42 | arrayInfo.push({ 43 | data: name, 44 | priority: value.priority || 0 45 | }); 46 | } 47 | arrayInfo.sort((a, b) => a.data - b.data); 48 | arrayInfo.sort((a, b) => (a.priority > b.priority ? -1 : 1)); 49 | const startSlice = numberOfOnePage * page - numberOfOnePage; 50 | i = startSlice; 51 | const returnArray = arrayInfo.slice(startSlice, startSlice + numberOfOnePage); 52 | const characters = "━━━━━━━━━━━━━"; 53 | 54 | msg += returnArray.reduce((text, item) => text += `【${++i}】 ${item.data}\n`, ''); 55 | 56 | const doNotDelete = "[ 🐐 | Project Goat Bot ]"; 57 | message.reply(`${characters}\n${msg}${characters}\nTrang [ ${page}/${Math.ceil(arrayInfo.length / numberOfOnePage)} ]\nHiện tại bot có ${globalGoat.commands.size} lệnh có thể sử dụng\n► Gõ ${prefix}help <số trang> để xem danh sách lệnh\n► Gõ ${prefix}help <tên lệnh> để xem chi tiết cách sử dụng lệnh đó\n${characters}\n${doNotDelete}`); 58 | } 59 | else if (sortHelp == "category") { 60 | for (const [name, value] of globalGoat.commands) { 61 | if (arrayInfo.some(item => item.category == value.config.category.toLowerCase())) arrayInfo[arrayInfo.findIndex(item => item.category == value.config.category.toLowerCase())].names.push(value.config.name); 62 | else arrayInfo.push({ 63 | category: value.config.category.toLowerCase(), 64 | names: [value.config.name] 65 | }); 66 | } 67 | arrayInfo.sort((a, b) => (a.category < b.category ? -1 : 1)); 68 | for (const data of arrayInfo) { 69 | let categoryUpcase = "- " + data.category.toUpperCase() + ":"; 70 | data.names.sort(); 71 | msg += `${categoryUpcase}\n${data.names.join(", ")}\n\n`; 72 | } 73 | const characters = "━━━━━━━━━━━━━"; 74 | const doNotDelete = "[ 🐐 | Project Goat Bot ]"; 75 | message.reply(`${msg}${characters}\n► Hiện tại bot có ${globalGoat.commands.size} lệnh có thể sử dụng, gõ ${prefix}help <tên lệnh> để xem chi tiết cách sử dụng lệnh đó\n${characters}\n${doNotDelete}`); 76 | } 77 | } 78 | // ———————————— COMMAND DOES NOT EXIST ———————————— // 79 | else if (!command && args[0]) { 80 | return message.reply(`Lệnh "${args[0]}" không tồn tại`); 81 | } 82 | // ————————————————— HELP COMMAND ————————————————— // 83 | else { 84 | const configCommand = command.config; 85 | let author = "", contacts = ""; 86 | if ( 87 | configCommand.author 88 | && typeof (configCommand.author) == "object" 89 | && !Array.isArray(configCommand.author) 90 | ) { 91 | author = configCommand.author.name || ""; 92 | contacts = configCommand.author.contacts || ""; 93 | } 94 | else if ( 95 | configCommand.author 96 | && typeof (configCommand.author) == "object" 97 | && Array.isArray(configCommand.author) 98 | ) { 99 | author = configCommand.author[0]; 100 | contacts = configCommand.author[1]; 101 | } 102 | else if (typeof (configCommand.author) == "string") author = configCommand.author; 103 | 104 | const nameUpperCase = configCommand.name.toUpperCase(); 105 | const title = "━━━━━━━━━━━━━" 106 | + "\n" + nameUpperCase 107 | + "\n" + "━━━━━━━━━━━━━"; 108 | 109 | let msg = `${title}\n► Mô tả: ${configCommand.longDescription || "Không có"}` 110 | + `\n► Version: ${configCommand.version}` 111 | + `${configCommand.shortName ? `\n\n► Tên gọi khác: ${typeof configCommand.shortName == "string" ? configCommand.shortName : configCommand.shortName.join(", ")}` : ""}` 112 | + `\n\n► Role: ${((configCommand.role == 0) ? "Tất cả người dùng" : (configCommand.role == 1) ? "Quản trị viên nhóm" : "Admin bot")}` 113 | + `\n► Thời gian mỗi lần dùng lệnh: ${configCommand.cooldowns || 1}s` 114 | + `\n► Phân loại: ${configCommand.category || "Không có phân loại"}` 115 | + (author ? `\n► Author: ${author}` : "") 116 | + (contacts ? `\n► Contacts: ${contacts}` : ""); 117 | let guide = configCommand.guide || { 118 | body: "" 119 | }; 120 | if (typeof (guide) == "string") guide = { 121 | body: guide 122 | }; 123 | msg += '\n━━━━━━━━━━━━━\n' 124 | + '► Hướng dẫn cách dùng:\n' 125 | + guide.body 126 | .replace(/\{prefix\}|\{p\}/g, prefix) 127 | .replace(/\{name\}|\{n\}/g, configCommand.name) 128 | + '\n━━━━━━━━━━━━━\n' 129 | + '► Chú thích:\n• Nội dung bên trong <XXXXX> là có thể thay đổi\n• Nội dung bên trong [a|b|c] là a hoặc b hoặc c'; 130 | 131 | const formSendMessage = { 132 | body: msg 133 | }; 134 | 135 | if (guide.attachment) { 136 | if (guide.attachment && typeof (guide.attachment) == 'object' && !Array.isArray(guide.attachment)) { 137 | formSendMessage.attachment = []; 138 | for (const pathFile in guide.attachment) { 139 | if (!existsSync(pathFile)) await download(guide.attachment[pathFile], pathFile); 140 | formSendMessage.attachment.push(createReadStream(pathFile)); 141 | } 142 | } 143 | } 144 | 145 | return message.reply(formSendMessage); 146 | } 147 | } 148 | }; -------------------------------------------------------------------------------- /scripts/cmds/warn.js: -------------------------------------------------------------------------------- 1 | const moment = require("moment-timezone"); 2 | this.config = { 3 | name: "warn", 4 | version: "1.0.1", 5 | author: { 6 | name: "NTKhang", 7 | contacts: "" 8 | }, 9 | cooldowns: 5, 10 | role: 0, 11 | shortDescription: "cảnh cáo thành viên", 12 | longDescription: "cảnh cáo thành viên trong nhóm, đủ 3 lần ban khỏi box", 13 | category: "box chat", 14 | guide: "{p}{n} @tag <lý do>: dùng cảnh cáo thành viên" 15 | + "\n{p}{n} list: xem danh sách những thành viên đã bị cảnh cáo" 16 | + "\n{p}{n} listban: xem danh sách những thành viên đã bị cảnh cáo đủ 3 lần và bị ban khỏi box" 17 | + "\n{p}{n} check [@tag | <uid> | để trống]: xem thông tin cảnh cáo của người được tag hoặc uid hoặc bản thân" 18 | + "\n{p}{n} unban <uid>: gỡ ban thành viên bằng uid" 19 | + "\n⚠️ Cần set quản trị viên cho bot để bot tự kick thành viên bị ban" 20 | }; 21 | 22 | module.exports = { 23 | config: this.config, 24 | start: async function ({ message, api, event, args, threadsData, usersData, client }) { 25 | if (!args[0]) return message.SyntaxError(); 26 | const { threadID, senderID } = event; 27 | const { data, adminIDs } = await threadsData.getData(threadID); 28 | if (!data.warn) data.warn = { 29 | banned: [], 30 | warnList: [] 31 | }; 32 | const { warnList, banned } = data.warn; 33 | 34 | 35 | if (args[0] == "list") { 36 | let msg = ""; 37 | for (const user of warnList) { 38 | msg += `\nName: ${user.name}` 39 | + `\nUid: ${user.uid}` 40 | + `\nSố lần bị cảnh cáo: ${user.data.length}` 41 | + '\n'; 42 | } 43 | message.reply(msg ? "Danh sách những thành viên bị cảnh cáo:\n" + msg + `\nĐể xem chi tiết những lần cảnh cáo hãy dùng lệnh "${client.getPrefix(threadID) + "warn check [@tag | <uid> | để trống]\": để xem thông tin cảnh cáo của người được tag hoặc uid hoặc bản thân"}` : "Nhóm bạn chưa có thành viên nào bị cảnh cáo"); 44 | } 45 | 46 | 47 | else if (args[0] == "listban") { 48 | let msg = ""; 49 | for (const uid of banned) { 50 | msg += `\nName: ${warnList.find(user => user.uid == uid).name}` 51 | + `\nUid: ${uid}` 52 | + '\n'; 53 | } 54 | message.reply(msg ? "Danh sách những thành viên bị cảnh cáo đủ 3 lần và ban khỏi box:\n" + msg : "Nhóm bạn chưa có thành viên nào bị ban khỏi box"); 55 | } 56 | 57 | 58 | else if (args[0] == "check" || args[0] == "info") { 59 | let uids, msg = ""; 60 | if (Object.keys(event.mentions).length > 0) uids = Object.keys(event.mentions); 61 | else if (args.slice(1).length > 0) uids = args.slice(1); 62 | else uids = [event.senderID]; 63 | if (!uids) return message.reply("Vui lòng nhập uid hợp lệ của người bạn muốn xem thông tin"); 64 | for (const uid of uids) { 65 | const dataWarnOfUser = warnList.find(user => user.uid == uid); 66 | msg += `\nUid: ${uid}`; 67 | if (!dataWarnOfUser || dataWarnOfUser.data.length == 0) msg += `\nKhông có dữ liệu nào\n`; 68 | else { 69 | msg += `\nName: ${dataWarnOfUser.name}` 70 | + `\nWarn list:`; 71 | for (const dataW of dataWarnOfUser.data) { 72 | msg += `\n Reason: ${dataW.reason}` 73 | + `\n Time: ${dataW.dateTime}\n`; 74 | } 75 | } 76 | } 77 | message.reply(msg); 78 | } 79 | 80 | 81 | else if (args[0] == "unban") { 82 | if (!adminIDs.includes(senderID)) return message.reply("Chỉ quản trị viên nhóm mới có thể unban thành viên bị ban khỏi box"); 83 | const uidUnban = args[1]; 84 | if (!uidUnban || isNaN(uidUnban)) return message.reply("Vui lòng nhập uid hợp lệ của người muốn gỡ ban"); 85 | if (!banned.includes(uidUnban)) return message.reply(`Người dùng mang id ${uidUnban} chưa bị ban khỏi box của bạn`); 86 | banned.splice(banned.findIndex(uid => uid == uidUnban), 1); 87 | warnList.splice(warnList.findIndex(user => user.uid == uidUnban), 1); 88 | const userName = warnList.find(user => user.uid == uidUnban).name; 89 | await threadsData.setData(threadID, { 90 | data 91 | }); 92 | return message.reply(`Đã gỡ ban thành viên [${uidUnban} | ${userName}], hiện tại người này có thể tham gia box chat của bạn`); 93 | } 94 | 95 | 96 | else { 97 | if (!adminIDs.includes(senderID)) return message.reply("Chỉ quản trị viên nhóm mới có thể cảnh cáo thành viên trong nhóm"); 98 | let reason, uid; 99 | if (event.messageReply) { 100 | uid = event.messageReply.senderID; 101 | reason = args.join(" ").trim(); 102 | } 103 | else if (Object.keys(event.mentions)[0]) { 104 | uid = Object.keys(event.mentions)[0]; 105 | reason = args.join(" ").replace(event.mentions[uid], "").trim(); 106 | } 107 | else { 108 | return message.reply("Bạn cần phải tag hoặc phản hồi tin nhắn của người muốn cảnh cáo"); 109 | } 110 | if (!reason) reason = "Không có lý do"; 111 | const dataWarnOfUser = warnList.find(item => item.uid == uid); 112 | const times = (dataWarnOfUser ? dataWarnOfUser.data.length : 0) + 1; 113 | const dateTime = moment.tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY hh:mm:ss"); 114 | if (times >= 3) banned.push(uid); 115 | const userName = (await usersData.getData(uid)).name; 116 | if (!dataWarnOfUser) { 117 | warnList.push({ 118 | uid, 119 | name: userName, 120 | data: [{ reason, dateTime }] 121 | }); 122 | } 123 | else { 124 | dataWarnOfUser.data.push({ reason, dateTime }); 125 | } 126 | await threadsData.setData(threadID, { 127 | data 128 | }); 129 | 130 | if (times >= 3) { 131 | message.reply(`⚠️ Đã cảnh cáo thành viên ${userName} lần ${times}` 132 | + `\n- Uid: ${uid}` 133 | + `\n- Lý do: ${reason}` 134 | + `\n- Date Time: ${dateTime}` 135 | + `\nThành viên này đã bị cảnh cáo đủ 3 lần và bị ban khỏi box, để gỡ ban vui lòng sử dụng lệnh "${client.getPrefix(threadID)}warn unban <uid>" (với uid là uid của người muốn gỡ ban)`, 136 | function () { 137 | api.removeUserFromGroup(uid, threadID, (err) => { 138 | if (err) return message.reply(`Bot cần quyền quản trị viên để kick thành viên bị ban`); 139 | }); 140 | }); 141 | } 142 | else return message.reply(`⚠️ Đã cảnh cáo thành viên ${userName} lần ${times}` 143 | + `\n- Uid: ${uid}` 144 | + `\n- Lý do: ${reason}` 145 | + `\n- Date Time: ${dateTime}` 146 | + `\nNếu vi phạm ${3 - (times)} lần nữa người này sẽ bị ban khỏi box` 147 | ); 148 | } 149 | }, 150 | 151 | whenReply: async function ({ message, api, event, args, threadsData, usersData }) { 152 | const { data, adminIDs } = await threadsData.getData(threadID); 153 | if (!data.warn) return; 154 | const { banned } = data.warn; 155 | 156 | if (banned.includes(event.senderID)) { 157 | const userName = (await usersData.getData(event.senderID)).name; 158 | message.send({ 159 | body: `Thành viên này đã bị cảnh cáo đủ 3 lần trước đó và bị ban khỏi box\nName: ${userName}\nUid: ${event.senderID}\n để gỡ ban vui lòng sử dụng lệnh "${client.getPrefix(threadID)}warn unban <uid>" (với uid là uid của người muốn gỡ ban)`, 160 | mentions: [{ 161 | tag: userName, 162 | id: event.senderID 163 | }] 164 | }, function () { 165 | api.removeUserFromGroup(event.senderID, event.threadID, (err) => { 166 | if (err) return message.send(`Bot cần quyền quản trị viên để kick thành viên bị ban`); 167 | }); 168 | }); 169 | } 170 | } 171 | }; -------------------------------------------------------------------------------- /scripts/cmds/ytb.js: -------------------------------------------------------------------------------- 1 | this.config = { 2 | name: "ytb", 3 | version: "1.0.2", 4 | author: { 5 | name: "NTKhang", 6 | contacts: "" 7 | }, 8 | cooldowns: 5, 9 | role: 0, 10 | shortDescription: "YouTube", 11 | longDescription: "Tải video, audio hoặc xem thông tin video trên YouTube", 12 | category: "media", 13 | guide: "{p}{n} [video|-v] [<tên video>|<link video>]: dùng để tải video từ youtube." 14 | + "\n{p}{n} [audio|-a] [<tên video>|<link video>]: dùng để tải audio từ youtube" 15 | + "\n{p}{n} [info|-i] [<tên video>|<link video>]: dùng để xem thông tin video từ youtube" 16 | + "\nVí dụ:" 17 | + "\n {p}{n} -v em gái mưa" 18 | + "\n {p}{n} -a em gái mưa" 19 | + "\n {p}{n} -i em gái mưa", 20 | packages: "ytdl-core", 21 | envGlobal: { 22 | youtube: "AIzaSyBZjYk2QtAvsZjAzUJ5o4qGl8eRl6gr2SA" 23 | } 24 | }; 25 | 26 | module.exports = { 27 | config: this.config, 28 | start: async function ({ api, globalGoat, args, download, message, event }) { 29 | const axios = require("axios"); 30 | const ytdl = require("ytdl-core"); 31 | const { createReadStream, unlinkSync } = require("fs-extra"); 32 | const API_KEY = globalGoat.configCommands.envGlobal.youtube; 33 | let type; 34 | if (["video", "-v"].includes(args[0])) type = "video"; 35 | else if (["audio", "-a", "sing", "-s"].includes(args[0])) type = "audio"; 36 | else if (["info", "-i"].includes(args[0])) type = "info"; 37 | else return message.SyntaxError(); 38 | 39 | const checkurl = /^(?:https?:\/\/)?(?:m\.|www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/; 40 | const urlYtb = checkurl.test(args[1]); 41 | 42 | if (urlYtb) { 43 | const infoVideo = await ytdl.getInfo(args[1]); 44 | const idvideo = infoVideo.videoDetails.videoId; 45 | await handle({ type, infoVideo, idvideo, message, api, event, download }); 46 | return; 47 | } 48 | 49 | const search = args.slice(1).join(" "); 50 | const maxResults = 6; 51 | const url = encodeURI(`https://www.googleapis.com/youtube/v3/search?key=${API_KEY}&part=snippet&q=${search}&maxResults=${maxResults}&type=video`); 52 | let result; 53 | try { 54 | result = (await axios.get(url)).data; 55 | } 56 | catch (err) { 57 | return message.reply("Đã xảy ra lỗi: " + err.response.data.error.message); 58 | } 59 | result = result.items; 60 | if (result.length == 0) return message.reply("Không có kết quả tìm kiếm nào phù hợp với từ khóa " + search); 61 | let msg = ""; 62 | let i = 1; 63 | const thumbnails = []; 64 | const arrayID = []; 65 | 66 | for (let info of result) { 67 | const idvideo = info.id.videoId; 68 | const infoWithApi = (await axios.get(`https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet&id=${idvideo}&key=${API_KEY}`)).data.items[0]; 69 | const time = infoWithApi.contentDetails.duration.slice(2).toLowerCase(); 70 | const listthumbnails = Object.values(infoWithApi.snippet.thumbnails); 71 | const linkthumbnails = listthumbnails[listthumbnails.length - 1].url; 72 | const streamThumbnail = (await axios.get(linkthumbnails, { 73 | responseType: "stream" 74 | })).data; 75 | thumbnails.push(streamThumbnail); 76 | arrayID.push(idvideo); 77 | 78 | msg += `${i++}. ${info.snippet.title}\nTime: ${time}\n\n`; 79 | } 80 | 81 | message.reply({ 82 | body: msg + "Reply tin nhắn với số để chọn hoặc nội dung bất kì để gỡ", 83 | attachment: thumbnails 84 | }, (err, info) => { 85 | globalGoat.whenReply[info.messageID] = { 86 | messageID: info.messageID, 87 | author: event.senderID, 88 | nameCmd: require(__filename).config.name, 89 | arrayID, 90 | result, 91 | type 92 | }; 93 | }); 94 | }, 95 | 96 | whenReply: async ({ event, api, Reply, download, message }) => { 97 | const ytdl = require("ytdl-core"); 98 | const { result, type } = Reply; 99 | const choice = event.body; 100 | if (!isNaN(choice) && choice <= 6) { 101 | const infochoice = result[choice - 1]; 102 | const idvideo = infochoice.id.videoId; 103 | const infoVideo = await ytdl.getInfo(idvideo); 104 | api.unsendMessage(Reply.messageID); 105 | await handle({ type, infoVideo, idvideo, message, api, event, download }); 106 | } 107 | else api.unsendMessage(Reply.messageID); 108 | } 109 | }; 110 | 111 | async function handle({ type, infoVideo, idvideo, api, event, download, message }) { 112 | const { createReadStream, createWriteStream, unlinkSync } = require("fs-extra"); 113 | const ytdl = require("ytdl-core"); 114 | const axios = require("axios"); 115 | if (type == "video") { 116 | const idvideo = infoVideo.videoDetails.videoId; 117 | const path_video = __dirname + `/cache/${idvideo}.mp4`; 118 | const getFormat = infoVideo.formats.filter(i => i.mimeType.includes("video/mp4") && i.mimeType.includes("mp4a")).sort((a, b) => parseInt(b.contentLength) - parseInt(a.contentLength)); 119 | if (getFormat.contentLength > 26214400) return api.sendMessage('Không thể gửi video này vì dung lượng lớn hơn 25MB.', event.threadID, event.messageID); 120 | message.reply("Đang tải xuống " + infoVideo.videoDetails.title); 121 | 122 | ytdl(idvideo) 123 | .pipe(createWriteStream(path_video)) 124 | .on("close", () => { 125 | return message.reply({ 126 | body: infoVideo.videoDetails.title, 127 | attachment: createReadStream(path_video) 128 | }, () => unlinkSync(path_video)); 129 | }) 130 | .on("error", (error) => message.reply(`Đã xảy ra lỗi khi tải video\n${error.stack}`)); 131 | } 132 | else if (type == "audio") { 133 | const audio = infoVideo.formats.find(item => item.mimeType.indexOf("audio/webm") != -1); 134 | if (audio.contentLength > 26214400) return api.sendMessage('Không thể gửi audio này vì dung lượng lớn hơn 25MB.', event.threadID, event.messageID); 135 | const linkaudio = audio.url; 136 | const path_audio = `${__dirname}/cache/${idvideo}.mp3`; 137 | await download(linkaudio, path_audio); 138 | return api.sendMessage({ 139 | body: infoVideo.videoDetails.title, 140 | attachment: createReadStream(path_audio) 141 | }, event.threadID, () => unlinkSync(path_audio), event.messageID); 142 | } 143 | else if (type == "info") { 144 | const info = infoVideo.videoDetails; 145 | const { title, lengthSeconds, viewCount, videoId, uploadDate, likes, dislikes } = infoVideo.videoDetails; 146 | 147 | let msg = ""; 148 | const hours = Math.floor(lengthSeconds / 3600); 149 | const minutes = Math.floor(lengthSeconds % 3600 / 60); 150 | const seconds = Math.floor(lengthSeconds % 3600 % 60); 151 | msg += "💠Tiêu đề: " + title + "\n"; 152 | msg += "🏪Channel: " + info.author.name + "\n"; 153 | if (info.author.subscriber_count) msg += "👨‍👩‍👧‍👦Subscriber: " + info.author.subscriber_count + "\n"; 154 | msg += `⏱Thời gian video: ${hours}:${minutes}:${seconds}\n`; 155 | msg += "👀Lượt xem: " + viewCount + "\n"; 156 | msg += "👍Lượt thích: " + likes + "\n"; 157 | msg += "👎Không thích: " + dislikes + "\n"; 158 | msg += "🆙Ngày tải lên: " + uploadDate + "\n"; 159 | msg += "#️⃣ID: " + videoId + "\n"; 160 | const paththumnailsChanel = __dirname + "/cache/thumbnailsChanel.jpg"; 161 | const paththumnailsVideo = __dirname + "/" + info.videoId + ".jpg"; 162 | await download(info.author.thumbnails[info.author.thumbnails.length - 1].url, paththumnailsChanel); 163 | await download(info.thumbnails[info.thumbnails.length - 1].url, paththumnailsVideo); 164 | const arrayThumnails = []; 165 | arrayThumnails.push(createReadStream(paththumnailsChanel)); 166 | arrayThumnails.push(createReadStream(paththumnailsVideo)); 167 | message.reply({ 168 | body: msg, 169 | attachment: arrayThumnails 170 | }, () => { 171 | unlinkSync(paththumnailsChanel); 172 | unlinkSync(paththumnailsVideo); 173 | }); 174 | } 175 | } -------------------------------------------------------------------------------- /bot/handler/handlerEvents.js: -------------------------------------------------------------------------------- 1 | module.exports = function ({ api, globalGoat, client, usersData, threadsData, download, }) { 2 | const print = globalGoat.print; 3 | const axios = require("axios"); 4 | const chalk = require("chalk"); 5 | const { readdirSync, writeFileSync, existsSync, mkdirSync, createReadStream } = require("fs-extra"); 6 | const moment = require("moment-timezone"); 7 | 8 | return async function ({ event, message }) { 9 | const { body, messageID, threadID, isGroup } = event; 10 | const senderID = event.senderID || event.author || event.userID; 11 | 12 | let prefix = globalGoat.config.prefix; 13 | client.allThreadData[threadID] ? prefix = client.allThreadData[threadID].prefix || prefix : ""; 14 | 15 | const contentSyntaxError = `Lệnh bạn đang sử dụng sai cú pháp, vui lòng gõ ${prefix}help {nameCmd} để xem chi tiết cách sử dụng lệnh này`; 16 | 17 | const parameters = { api, globalGoat, client, usersData, threadsData, message, event, download }; 18 | 19 | if (!isNaN(senderID) && !client.allUserData[senderID]) await usersData.createData(senderID); 20 | if (!isNaN(threadID) && !client.allThreadData[threadID]) await threadsData.createData(threadID); 21 | 22 | //===============================================// 23 | // WHEN CHAT // 24 | //===============================================// 25 | async function whenChat() { 26 | const { isGroup } = event; 27 | const allWhenChat = globalGoat.whenChat || []; 28 | const args = body ? body.split(" ") : []; 29 | for (const key of allWhenChat) { 30 | const command = globalGoat.commands.get(key); 31 | try { 32 | message.SyntaxError = function () { 33 | return message.reply(contentSyntaxError.replace("{nameCmd}", command.config.name)); 34 | }; 35 | command.whenChat({ 36 | ...parameters, 37 | ...{ args } 38 | }); 39 | } 40 | catch (err) { 41 | print.err("Đã xảy ra lỗi khi thực hiện commamd whenChat ở lệnh " + command.config.name + ", lỗi: " + err.stack, "WHEN CHAT"); 42 | } 43 | } 44 | } 45 | 46 | //===============================================// 47 | // WHEN CALL COMMAND // 48 | //===============================================// 49 | async function whenStart() { 50 | // —————————————— CHECK USE BOT —————————————— // 51 | if (body && !body.startsWith(prefix) || !body) return; 52 | const dateNow = Date.now(); 53 | const { adminBot } = globalGoat.config; 54 | const args = body.slice(prefix.length).trim().split(/ +/); 55 | // ————————— CHECK HAS IN DATABASE ————————— // 56 | if (!client.allThreadData[threadID]) await threadsData.createData(threadID); 57 | if (!client.allUserData[senderID]) await usersData.createData(senderID); 58 | // ———————————— CHECK HAS COMMAND ——————————— // 59 | var commandName = args.shift().toLowerCase(); 60 | const command = globalGoat.commands.get(commandName) || globalGoat.commands.get(globalGoat.shortNameCommands.get(commandName)); 61 | if (command) commandName = command.config.name; 62 | // ————————————— GET THREAD INFO ————————————— // 63 | const threadInfo = client.allThreadData[threadID] || {}; 64 | if (threadInfo.onlyAdminBox === true && !threadInfo.adminIDs.includes(senderID) && commandName != "rules") return message.reply("Hiện tại nhóm này đã được bật chế độ chỉ quản trị viên nhóm mới có thể sử dụng bot"); 65 | // —————————————— CHECK BANNED —————————————— // 66 | // +++++++++++ Check User +++++++++++ // 67 | const infoBannedUser = client.allUserData[senderID].banned; 68 | if (infoBannedUser.status == true) { 69 | return message.reply( 70 | `Bạn đã bị Admin cấm sử dụng bot` 71 | + `\n> Lý do: ${infoBannedUser.reason}` 72 | + `\n> Thời gian: ${infoBannedUser.date}` 73 | + `\n> User ID: ${senderID}`); 74 | } 75 | // +++++++++++ Check Thread +++++++++++ // 76 | if (isGroup == true) { 77 | const infoBannedThread = threadInfo.banned; 78 | if (infoBannedThread.status == true) return message.reply( 79 | `Nhóm của bạn đã bị Admin bot cấm dùng bot` 80 | + `\n> Lý do: ${infoBannedThread.reason}` 81 | + `\n> Thời gian: ${infoBannedThread.date}` 82 | + `\n> Thread ID: ${threadID}`); 83 | } 84 | if (!command) return message.reply(`Lệnh ${commandName ? `'${commandName}'` : 'bạn sử dụng'} không tồn tại, gõ ${prefix}help để xem tất cả lệnh hiện có`); 85 | //============================================// 86 | // ————————————— COMMAND BANNED ————————————— // 87 | if (client.commandBanned[commandName]) return message.reply(`Lệnh ${commandName} đã bị Admin cấm sử dụng trong hệ thống bot với lý do: ${client.commandBanned[commandName]}`); 88 | // ————————————— CHECK PERMISSION ———————————— // 89 | const needRole = command.config.role || 0; 90 | const adminBox = threadInfo.adminIDs || []; 91 | 92 | const role = adminBot.includes(senderID) ? 2 : 93 | adminBox.includes(senderID) ? 1 : 94 | 0; 95 | 96 | if (needRole > role && needRole == 1) return message.reply(`Chỉ quản trị viên của nhóm chat mới có thể dùng lệnh '${commandName}'`); 97 | if (needRole > role && needRole == 2) return message.reply(`Chỉ admin bot mới có thể dùng lệnh '${commandName}'`); 98 | // ———————————————— COOLDOWNS ———————————————— // 99 | if (!client.cooldowns[commandName]) client.cooldowns[commandName] = {}; 100 | const timestamps = client.cooldowns[commandName]; 101 | const configCommand = command.config; 102 | const cooldownCommand = (command.config.cooldowns || 1) * 1000; 103 | if (timestamps[senderID]) { 104 | const expirationTime = timestamps[senderID] + cooldownCommand; 105 | if (dateNow < expirationTime) return message.reply(`⏱ Bạn đang trong thời gian chờ sử dụng lệnh này, vui lòng quay lại sau ${((expirationTime - dateNow) / 1000).toString().slice(0, 3)}s`); 106 | } 107 | // ——————————————— RUN COMMAND ——————————————— // 108 | try { 109 | message.SyntaxError = function () { 110 | return message.reply(contentSyntaxError.replace("{nameCmd}", command.config.name)); 111 | }; 112 | message.guideCmd = async function () { 113 | let guide = configCommand.guide || { 114 | body: "" 115 | }; 116 | if (typeof (guide) == "string") guide = { 117 | body: guide 118 | }; 119 | const msg = '\n───────────────\n' 120 | + '» Hướng dẫn cách dùng:\n' 121 | + guide.body 122 | .replace(/\{prefix\}|\{p\}/g, prefix) 123 | .replace(/\{name\}|\{n\}/g, configCommand.name) 124 | + '\n───────────────\n' 125 | + '» Chú thích:\n• Nội dung bên trong <XXXXX> là có thể thay đổi\n• Nội dung bên trong [a|b|c] là a hoặc b hoặc c'; 126 | 127 | const formSendMessage = { 128 | body: msg 129 | }; 130 | 131 | if (guide.attachment) { 132 | if (guide.attachment && typeof (guide.attachment) == 'object' && !Array.isArray(guide.attachment)) { 133 | formSendMessage.attachment = []; 134 | for (const pathFile in guide.attachment) { 135 | if (!existsSync(pathFile)) await download(guide.attachment[pathFile], pathFile); 136 | formSendMessage.attachment.push(createReadStream(pathFile)); 137 | } 138 | } 139 | } 140 | message.reply(formSendMessage); 141 | }; 142 | const time = moment.tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY HH:mm:ss"); 143 | print(`${chalk.hex("#ffb300")(time)} | ${commandName} | ${senderID} | ${threadID} | ${args.join(" ")}`, "CALL CMD"); 144 | parameters.role = role; 145 | command.start({ ...parameters, ...{ args } }); 146 | timestamps[senderID] = dateNow; 147 | } 148 | catch (err) { 149 | print.err(`Đã xảy ra lỗi khi chạy lệnh ${commandName}, lỗi: ${err.stack}`, "CALL COMMAND"); 150 | return message.reply(`❎\nĐã có lỗi xảy ra khi thực thi lệnh ${commandName}\n${err.stack}`); 151 | } 152 | } 153 | 154 | //===============================================// 155 | // WHEN REPLY // 156 | //===============================================// 157 | async function whenReply() { 158 | if (!event.messageReply) return; 159 | const { whenReply } = globalGoat; 160 | const Reply = whenReply[event.messageReply.messageID]; 161 | if (!Reply) return; 162 | const command = globalGoat.commands.get(Reply.nameCmd); 163 | if (!command) throw new Error("Không tìm thấy tên lệnh để thực hiện phản hồi này"); 164 | const args = body ? body.split(" ") : []; 165 | try { 166 | message.SyntaxError = function () { 167 | return message.reply(contentSyntaxError.replace("{nameCmd}", command.config.name)); 168 | }; 169 | message.guideCmd = async function () { 170 | const formSendMessage = { 171 | body: command.config.guide.replace(/\{prefix\}|\{p\}/g, prefix).replace(/\{name\}|\{n\}/g, command.config.name) 172 | }; 173 | const { sendFile } = command.config; 174 | if (sendFile && 175 | typeof (sendFile) == 'object' && 176 | !Array.isArray(sendFile) 177 | ) { 178 | formSendMessage.attachment = []; 179 | for (let pathFile in sendFile) { 180 | if (!existsSync(pathFile)) await download(sendFile[pathFile], pathFile); 181 | formSendMessage.attachment.push(createReadStream(pathFile)); 182 | } 183 | } 184 | return api.sendMessage(formSendMessage, threadID, messageID); 185 | }; 186 | return command.whenReply({ ...parameters, ...{ Reply, args } }); 187 | } 188 | catch (err) { 189 | print.err(`Đã xảy ra lỗi khi thực thi lệnh reply ở lệnh ${Reply.nameCmd} ${err.stack}`, "WHEN REPLY"); 190 | message.reply(`❎\nĐã xảy ra lỗi tại command ${Reply.nameCmd}\n${err.stack}`); 191 | } 192 | } 193 | 194 | //===============================================// 195 | // WHEN REACTION // 196 | //===============================================// 197 | async function whenReaction() { 198 | const { whenReaction } = globalGoat; 199 | const Reaction = whenReaction[messageID]; 200 | if (!Reaction) return; 201 | const command = globalGoat.commands.get(Reaction.nameCmd); 202 | if (!command) throw new Error("Không tìm thấy tên lệnh để thực hiện phản hồi này"); 203 | const args = body ? body.split(" ") : []; 204 | try { 205 | message.SyntaxError = function () { 206 | return message.reply(contentSyntaxError.replace("{nameCmd}", command.config.name)); 207 | }; 208 | message.guideCmd = async function () { 209 | const formSendMessage = { 210 | body: command.config.guide.replace(/\{prefix\}|\{p\}/g, prefix).replace(/\{name\}|\{n\}/g, command.config.name) 211 | }; 212 | const { sendFile } = command.config; 213 | if (sendFile && 214 | typeof (sendFile) == 'object' && 215 | !Array.isArray(sendFile) 216 | ) { 217 | formSendMessage.attachment = []; 218 | for (let pathFile in sendFile) { 219 | if (!existsSync(pathFile)) await download(sendFile[pathFile], pathFile); 220 | formSendMessage.attachment.push(createReadStream(pathFile)); 221 | } 222 | } 223 | return api.sendMessage(formSendMessage, threadID, messageID); 224 | }; 225 | command.whenReaction({ ...parameters, ...{ Reaction, args } }); 226 | return; 227 | } 228 | catch (e) { 229 | print.err(`Đã xảy ra lỗi khi thực thi command Reaction tại lệnh ${Reaction.nameCmd}: ${e.stack}`, "HANDLE REACTION"); 230 | message.reply(`❎\nĐã xảy ra lỗi tại command Reaction ${Reaction.nameCmd}\n${e.stack}`); 231 | } 232 | } 233 | 234 | //===============================================// 235 | // EVENT // 236 | //===============================================// 237 | async function handlerEvent() { 238 | const { logMessageType, author } = event; 239 | for (const [key, value] of globalGoat.events.entries()) { 240 | const getEvent = globalGoat.events.get(key); 241 | if (!getEvent.config.type.includes(logMessageType)) continue; 242 | if (getEvent.config.condition && !eval(getEvent.config.condition)) continue; 243 | try { 244 | const time = moment.tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY HH:mm:ss"); 245 | print(`${chalk.hex("#ffb300")(time)} | Event: ${getEvent.config.name} | ${author} | ${threadID}`, "EVENT CMD"); 246 | getEvent.start({ event, api, globalGoat, usersData, threadsData, client, download, message }); 247 | } 248 | catch (err) { 249 | print.err(`Đã xảy ra lỗi tại command event ${chalk.hex("#ff0000")(getEvent.config.name)}, ${err.stack}`, "EVENT COMMAND"); 250 | message.reply(`❎\nĐã xảy ra lỗi tại command event ${getEvent.config.name}\n${err.stack}`) 251 | } 252 | } 253 | } 254 | 255 | //===============================================// 256 | // PRESENCE // 257 | //===============================================// 258 | async function presence() { 259 | // Your code here 260 | } 261 | 262 | //===============================================// 263 | // READ RECEIPT // 264 | //===============================================// 265 | async function read_receipt() { 266 | // Your code here 267 | } 268 | 269 | //===============================================// 270 | // TYP // 271 | //===============================================// 272 | async function typ() { 273 | // Your code here 274 | } 275 | 276 | 277 | return { 278 | whenChat, 279 | whenStart, 280 | whenReaction, 281 | whenReply, 282 | handlerEvent, 283 | presence, 284 | read_receipt, 285 | typ 286 | }; 287 | }; 288 | }; -------------------------------------------------------------------------------- /database/dataProcessing/handlerData.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs-extra"); 2 | const axios = require("axios"); 3 | const mongoose = require("mongoose"); 4 | 5 | module.exports = async function ({ globalGoat, client, api }) { 6 | const { print, config, loading } = globalGoat; 7 | const databaseType = config.database.type; 8 | const dataModels = require("./models/dataModels.js"); 9 | 10 | if (databaseType == "mongodb" && config.database.uriMongodb) { 11 | const P = "\\|/-"; 12 | let ij = 0; 13 | 14 | const loadmongo = setInterval(() => { 15 | loading(P[ij++] + " Đang kết nối CSDL mongodb", "MONGODB"); 16 | ij %= P.length; 17 | }, 120); 18 | 19 | const uriConnect = config.database.uriMongodb; 20 | try { 21 | await mongoose.connect(uriConnect, { 22 | useNewUrlParser: true, 23 | useUnifiedTopology: true 24 | }); 25 | loading.master("Kết nối cơ sở dữ liệu Mongodb thành công\n", "MONGODB"); 26 | clearInterval(loadmongo); 27 | } 28 | catch (err) { 29 | loading.err("Kết nối cơ sở dữ liệu Mongodb thất bại với lỗi: " + err.stack + "\n", "MONGODB"); 30 | clearInterval(loadmongo); 31 | } 32 | for (const type of ["thread", "user"]) { 33 | if ((await dataModels.find({ type })).length == 0) await dataModels.create({ 34 | type, 35 | data: {} 36 | }); 37 | } 38 | } 39 | /* 40 | ▀▀█▀▀ █░░█ █▀▀█ █▀▀ █▀▀█ █▀▀▄ █▀▀ 41 | ░░█░░ █▀▀█ █▄▄▀ █▀▀ █▄▄█ █░░█ ▀▀█ 42 | ░░▀░░ ▀░░▀ ▀░▀▀ ▀▀▀ ▀░░▀ ▀▀▀░ ▀▀▀ 43 | */ 44 | async function threadsData() { 45 | let Threads = {}; 46 | if (databaseType == "mongodb") { 47 | Threads = (await dataModels.find({ type: "thread" }))[0].data || {}; 48 | } 49 | else { 50 | if (!fs.existsSync(__dirname + "/../threadsData.json")) fs.writeFileSync(__dirname + "/../threadsData.json", "{}"); 51 | Threads = require("../threadsData.json"); 52 | } 53 | 54 | client.allThreadData = Threads; 55 | 56 | async function saveData(threadID) { 57 | threadID != "delete" ? Threads[threadID].lastUpdate = Date.now() : ""; 58 | client.allThreadData = Threads; 59 | if (databaseType == "local") { 60 | fs.writeFileSync(__dirname + "/../threadsData.json", JSON.stringify(Threads, null, 2)); 61 | } 62 | else if (databaseType == "mongodb") { 63 | try { 64 | await dataModels.updateOne({ 65 | type: "thread" 66 | }, { 67 | data: Threads 68 | }); 69 | } 70 | catch (err) { 71 | print.err("Đã xảy ra lỗi khi cập nhật dữ liệu của nhóm mang id " + threadID + "\n" + err, "MONGODB"); 72 | } 73 | } 74 | else throw new Error("Database Type không hợp lệ"); 75 | } 76 | 77 | async function createData(threadID, callback) { 78 | try { 79 | if (Threads[threadID]) throw new Error(`Nhóm mang id ${threadID} đã tồn tại trong database`); 80 | const threadInfo = await api.getThreadInfo(threadID); 81 | const name = threadInfo.threadName; 82 | const { userInfo } = threadInfo; 83 | const newadminsIDs = []; 84 | const newMembers = {}; 85 | threadInfo.adminIDs.forEach(item => newadminsIDs.push(item.id)); 86 | 87 | for (let user of userInfo) { 88 | const userID = user.id; 89 | const dataUser = { 90 | id: userID, 91 | name: user.name, 92 | gender: user.gender, 93 | nickname: threadInfo.nicknames[userID] || null, 94 | inGroup: true, 95 | count: 0 96 | }; 97 | newMembers[userID] = dataUser; 98 | } 99 | 100 | const data = { 101 | id: threadID, 102 | name: name, 103 | emoji: threadInfo.emoji, 104 | prefix: null, 105 | adminIDs: newadminsIDs, 106 | avatarbox: threadInfo.imageSrc, 107 | approvalMode: threadInfo.approvalMode, 108 | banned: { 109 | status: false, 110 | reason: null 111 | }, 112 | data: { 113 | createDate: Date.now() 114 | }, 115 | members: newMembers 116 | }; 117 | Threads[threadID] = data; 118 | await saveData(threadID); 119 | if (callback && typeof callback == "function") callback(null, Threads[threadID]); 120 | return Threads[threadID]; 121 | } 122 | catch (err) { 123 | print.err(err.stack, "CREATE THREAD DATA"); 124 | if (callback && typeof callback == "function") callback(err, null); 125 | return err; 126 | } 127 | } 128 | 129 | async function refreshInfo(threadID, callback) { 130 | try { 131 | if (!Threads[threadID]) throw new Error(`Nhóm mang id ${threadID} không tồn tại trong database`); 132 | const ThreadInfo = await getData(threadID); 133 | const newThreadInfo = await api.getThreadInfo(threadID); 134 | 135 | const { 136 | userInfo, 137 | adminIDs 138 | } = newThreadInfo; 139 | 140 | const oldMembers = ThreadInfo.members; 141 | const newMembers = {}; 142 | for (const user of userInfo) { 143 | const userID = user.id; 144 | const oldDataUser = oldMembers[userID]; 145 | const data = { 146 | name: user.name, 147 | gender: user.gender, 148 | nickname: newThreadInfo.nicknames[userID], 149 | count: oldMembers[userID] ? oldMembers[userID].count : 0, 150 | inGroup: true 151 | }; 152 | newMembers[userID] = { 153 | ...oldDataUser, 154 | ...data 155 | }; 156 | if (oldMembers[userID]) delete oldMembers[userID]; 157 | } 158 | for (const uid in oldMembers) oldMembers[uid].inGroup = false; 159 | 160 | const newadminsIDs = adminIDs.map(item => item.id); 161 | const ThreadInfoNew = { 162 | name: newThreadInfo.name, 163 | emoji: newThreadInfo.emoji, 164 | adminIDs: newadminsIDs, 165 | avatarbox: newThreadInfo.imageSrc, 166 | members: { 167 | ...oldMembers, 168 | ...newMembers 169 | } 170 | }; 171 | 172 | Threads[threadID] = { 173 | ...ThreadInfo, 174 | ...ThreadInfoNew 175 | }; 176 | 177 | await saveData(threadID); 178 | if (callback && typeof callback == "function") callback(null, Threads[threadID]); 179 | return Threads[threadID]; 180 | } 181 | catch (err) { 182 | if (callback && typeof callback == "function") callback(err, null); 183 | return err; 184 | } 185 | } 186 | 187 | async function getAll(keys, callback) { 188 | try { 189 | if (!keys) return Object.values(Threads); 190 | if (!Array.isArray(keys)) throw new Error("Tham số truyền vào phải là 1 array"); 191 | const data = []; 192 | for (const threadID in Threads) { 193 | const db = { 194 | id: threadID 195 | }; 196 | const dataT = Threads[threadID]; 197 | for (const key of keys) db[key] = dataT[key]; 198 | data.push(db); 199 | } 200 | if (callback && typeof callback == "function") callback(null, data); 201 | return data; 202 | } catch (err) { 203 | print.err(err.stack, "GETALL DATA THREAD"); 204 | if (callback && typeof callback == "function") callback(err, null); 205 | return err; 206 | } 207 | }; 208 | 209 | async function getData(threadID, callback) { 210 | try { 211 | const data = Threads[threadID]; 212 | if (callback && typeof callback == "function") callback(null, data); 213 | return data; 214 | } 215 | catch (err) { 216 | print.err(err.stack, "GET THREAD DATA"); 217 | if (callback && typeof callback == "function") callback(err, null); 218 | return err; 219 | } 220 | }; 221 | 222 | async function setData(threadID, options, callback) { 223 | try { 224 | if (!threadID) throw new Error("threadID không được để trống"); 225 | if (isNaN(threadID)) throw new Error("threadID không hợp lệ"); 226 | if (typeof options != 'object') throw new Error("Tham số options truyền vào phải là 1 object"); 227 | Threads[threadID] = { 228 | ...Threads[threadID], 229 | ...options 230 | }; 231 | await saveData(threadID); 232 | if (callback && typeof callback == "function") callback(null, Threads[threadID]); 233 | return Threads[threadID]; 234 | } 235 | catch (err) { 236 | print.err(err.stack, "SET THREAD DATA"); 237 | if (callback && typeof callback == "function") callback(err, null); 238 | return err; 239 | }; 240 | }; 241 | 242 | async function delData(threadID, callback) { 243 | try { 244 | delete Threads[threadID]; 245 | await saveData("delete"); 246 | if (callback && typeof callback == "function") callback(null, "DELDATA THREAD " + threadID + " SUCCES"); 247 | return true; 248 | } catch (err) { 249 | print.err(err.stack, "DEL THREAD DATA"); 250 | if (callback && typeof callback == "function") callback(err, null); 251 | return err; 252 | } 253 | }; 254 | 255 | return { 256 | createData, 257 | refreshInfo, 258 | getAll, 259 | getData, 260 | setData, 261 | delData 262 | }; 263 | }; 264 | 265 | 266 | /* 267 | *█░░█ █▀▀ █▀▀ █▀▀█ █▀▀ █▀▀▄ █▀▀█ ▀▀█▀▀ █▀▀█ 268 | █░░█ ▀▀█ █▀▀ █▄▄▀ ▀▀█ █░░█ █▄▄█ ░░█░░ █▄▄█ 269 | ░▀▀▀ ▀▀▀ ▀▀▀ ▀░▀▀ ▀▀▀ ▀▀▀░ ▀░░▀ ░░▀░░ ▀░░▀ 270 | * 271 | */ 272 | 273 | async function usersData() { 274 | let Users = {}; 275 | 276 | if (databaseType == 'mongodb') { 277 | Users = (await dataModels.find({ type: 'user' }))[0].data || {}; 278 | } 279 | else { 280 | if (!fs.existsSync(__dirname + "/../usersData.json")) fs.writeFileSync(__dirname + "/../usersData.json", "{}"); 281 | Users = require("../usersData.json"); 282 | } 283 | client.allUserData = Users; 284 | 285 | async function saveData(Uid) { 286 | Uid != "delete" ? Users[Uid].lastUpdate = Date.now() : ""; 287 | client.allUserData = Users; 288 | if (databaseType == 'local') { 289 | fs.writeFileSync(__dirname + "/../usersData.json", JSON.stringify(Users, null, 2)); 290 | } 291 | else if (databaseType == 'mongodb') { 292 | await dataModels.updateOne({ type: "user" }, { 293 | data: Users 294 | }) 295 | .catch(err => print.err("Đã xảy ra lỗi khi cập nhật dữ liệu của người dùng mang id " + Uid + "\n" + err, "MONGODB")); 296 | } 297 | else throw new Error("Database Type không hợp lệ"); 298 | } 299 | 300 | async function createData(userID, callback) { 301 | try { 302 | if (Users[userID]) throw new Error(`Người dùng mang id ${userID} đã tồn tại trong database`); 303 | const infoUser = (await api.getUserInfo(userID))[userID]; 304 | const data = { 305 | id: userID, 306 | name: infoUser.name, 307 | vanity: infoUser.vanity, 308 | gender: infoUser.gender, 309 | isFriend: infoUser.isFriend, 310 | money: 0, 311 | exp: 0, 312 | banned: { 313 | status: false, 314 | reason: null 315 | }, 316 | data: { 317 | createDate: Date.now() 318 | } 319 | }; 320 | 321 | Users[userID] = data; 322 | 323 | await saveData(userID); 324 | if (callback && typeof callback == "function") callback(null, data); 325 | return data; 326 | } 327 | catch (err) { 328 | if (callback && typeof callback == "function") callback(err, null); 329 | print.err(err.stack, "CREATEDATA USER"); 330 | return err; 331 | } 332 | }; 333 | 334 | async function refreshInfo(userID, callback) { 335 | try { 336 | if (!Users[userID]) throw new Error(`Người dùng mang id ${userID} không tồn tại trong database`); 337 | const InfoUser = await getData(userID); 338 | const updateInfoUser = (await api.getUserInfo(userID))[userID]; 339 | const newData = { 340 | name: updateInfoUser.name, 341 | vanity: updateInfoUser.vanity, 342 | gender: updateInfoUser.gender, 343 | isFriend: updateInfoUser.isFriend 344 | } 345 | 346 | Users[userID] = { 347 | ...InfoUser, 348 | ...newData 349 | }; 350 | 351 | await saveData(userID); 352 | if (callback && typeof callback == "function") callback(null, InfoUser); 353 | return InfoUser; 354 | } 355 | catch (err) { 356 | if (callback && typeof callback == "function") callback(err, null); 357 | print.err(err.stack, "CREATEDATA USER"); 358 | return err; 359 | } 360 | }; 361 | 362 | async function getAll(keys, callback) { 363 | try { 364 | if (!keys) return Object.values(Users); 365 | if (!Array.isArray(keys)) throw new Error("Tham số truyền vào phải là 1 array"); 366 | const data = []; 367 | for (let userID in Users) { 368 | const db = { id: userID }; 369 | const dataU = Users[userID]; 370 | for (let key of keys) db[key] = dataU[key]; 371 | data.push(db); 372 | }; 373 | if (callback && typeof callback == "function") callback(null, data); 374 | return data; 375 | } catch (err) { 376 | if (callback && typeof callback == "function") callback(err, null); 377 | print.err(err, "GETALL USER"); 378 | return err; 379 | } 380 | }; 381 | 382 | async function getData(userID, callback) { 383 | try { 384 | if (!Users[userID]) await createData(userID); 385 | const data = Users[userID]; 386 | if (callback && typeof callback == "function") callback(null, data); 387 | return data; 388 | } 389 | catch (err) { 390 | print.err(err.stack, "GETDATA USER"); 391 | if (callback && typeof callback == "function") callback(err, null); 392 | return err; 393 | } 394 | }; 395 | 396 | async function setData(userID, options, callback) { 397 | try { 398 | if (isNaN(userID)) throw new Error("userID không được để trống"); 399 | if (isNaN(userID)) throw new Error("userID không hợp lệ"); 400 | if (typeof options != 'object') throw new Error("Options truyền vào phải là 1 object"); 401 | var keys = Object.keys(options); 402 | if (!Users[userID]) throw new Error(`Người dùng mang id ${userID} không tồn tại trong database`); 403 | for (let key of keys) Users[userID][key] = options[key]; 404 | await saveData(userID); 405 | if (callback && typeof callback == "function") callback(null, userID[userID]); 406 | return userID[userID]; 407 | } 408 | catch (err) { 409 | print.err(err.stack, "SETDATA USER"); 410 | if (callback && typeof callback == "function") callback(err, null); 411 | return err; 412 | } 413 | }; 414 | 415 | async function delData(userID, callback) { 416 | try { 417 | delete Users[userID]; 418 | const data = await saveData('delete'); 419 | if (callback && typeof callback == "function") callback(null, data); 420 | } catch (err) { 421 | print.err(err.stack, "DELDATA USER"); 422 | if (callback && typeof callback == "function") callback(err, null); 423 | return err; 424 | } 425 | }; 426 | 427 | return { 428 | createData, 429 | refreshInfo, 430 | getAll, 431 | getData, 432 | setData, 433 | delData 434 | }; 435 | }; 436 | 437 | return { 438 | threadsData, 439 | usersData 440 | } 441 | } -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "version": "1.0.1", 4 | "info": { 5 | "scripts/cmds/banner.js": "fix error when call api", 6 | "scripts/cmds/banner2.js": "fix error when call api", 7 | "scripts/cmds/bannerbw.js": "fix error when call api", 8 | "scripts/cmds/cmd.js": "synchronized envGlobal & envConfig when load scripts", 9 | "scripts/cmds/adminonly.js": "new script command", 10 | "bot/loadAllScript.js": "synchronized envGlobal & envConfig when load scripts", 11 | "index.js": "Fix error can't use adminOnly" 12 | } 13 | }, 14 | { 15 | "version": "1.0.2", 16 | "info": { 17 | "scripts/cmds/user.js": "fix error", 18 | "scripts/cmds/adduser.js": "Additional features", 19 | "bot/handler/handlerEvents.js": "no description", 20 | "package.json": "remove unnecessary libraries" 21 | } 22 | }, 23 | { 24 | "version": "1.0.3", 25 | "info": { 26 | "update.js": "new features (update with command)", 27 | "versions.json": "new features (update with command)" 28 | } 29 | }, 30 | { 31 | "version": "1.0.4", 32 | "info": { 33 | "scripts/events/leave.js": "update default mod: on", 34 | "scripts/events/welcome.js": "update default mod: on", 35 | "scripts/events/logsbot.js": "no description", 36 | "scripts/cmds/leavemsg.js": "new script command (on/off send a message when a member leaves the group chat", 37 | "scripts/cmds/logsbot.js": "new script command (on/off logsbot event)", 38 | "index.js": "edit text check update" 39 | } 40 | }, 41 | { 42 | "version": "1.0.5", 43 | "info": { 44 | "config.json": "no description", 45 | "scripts/cmds/unsend.js": "new script unsend message bot" 46 | }, 47 | "notes": "this is version fix can't use bot" 48 | }, 49 | { 50 | "version": "1.0.6", 51 | "info": { 52 | "config.json": "no description" 53 | } 54 | }, 55 | { 56 | "version": "1.0.7", 57 | "info": { 58 | "index.js": "move text check version", 59 | "config.json": "logEvents default true", 60 | "update.js": "no description" 61 | } 62 | }, 63 | { 64 | "version": "1.0.8", 65 | "info": { 66 | "scripts/cmds/callad.js": "edit role 1 => 0" 67 | } 68 | }, 69 | { 70 | "version": "1.0.9", 71 | "info": { 72 | "scripts/cmds/batslap.js": "fix error api", 73 | "scripts/cmds/backupmongo.js": "fix error", 74 | "bot/handler/handlerEvents.js": "fix error" 75 | } 76 | }, 77 | { 78 | "version": "1.0.10", 79 | "info": { 80 | "scripts/events/autoUpdateInfoThread.js": "rename slpice => splice (line 43) :v" 81 | } 82 | }, 83 | { 84 | "version": "1.1.0", 85 | "info": { 86 | "bot/handler/handlerEvents.js": "add features on/off only admin thread use bot", 87 | "scripts/cmds/onlyadminbox.js": "new script command", 88 | "scripts/cmds/notification.js": "new script command send notification to all box" 89 | } 90 | }, 91 | { 92 | "version": "1.1.1", 93 | "info": { 94 | "scripts/cmds/notification.js": "fix error when send multimedia & auto move mediaFile after send", 95 | "scripts/cmds/setbox.js": "new script command", 96 | "index.js": "no description" 97 | } 98 | }, 99 | { 100 | "version": "1.1.2", 101 | "info": { 102 | "package.json": "added package canvas", 103 | "scripts/cmds/prefix.js": "edit role 2 => 0" 104 | } 105 | }, 106 | { 107 | "version": "1.1.3", 108 | "info": { 109 | "scripts/cmds/thread.js": "fix error" 110 | } 111 | }, 112 | { 113 | "version": "1.1.4", 114 | "info": { 115 | "database/dataProcessing/handlerData.js": "auto write file threadsData.json & usersData.json if does not exist" 116 | } 117 | }, 118 | { 119 | "version": "1.1.5", 120 | "info": { 121 | "index.js": "Short command name feature update", 122 | "bot/loadAllScript.js": "Short command name feature update", 123 | "bot/handler/handlerEvents.js": "Short command name feature update", 124 | "scripts/cmds/help.js": "Short command name feature update" 125 | } 126 | }, 127 | { 128 | "version": "1.1.6", 129 | "info": { 130 | "scripts/cmds/cmd.js": "Short command name feature update", 131 | "scripts/cmds/help.js": "fix error", 132 | "scripts/cmds/qrcode.js": "new script command" 133 | } 134 | }, 135 | { 136 | "version": "1.1.7", 137 | "info": { 138 | "scripts/cmds/batslap.js": "fix invalid apikey" 139 | } 140 | }, 141 | { 142 | "version": "1.1.8", 143 | "info": { 144 | "scripts/cmds/jail.js": "fix invalid apikey" 145 | } 146 | }, 147 | { 148 | "version": "1.1.9", 149 | "info": { 150 | "scripts/cmds/rank.js": "no description" 151 | } 152 | }, 153 | { 154 | "version": "1.1.10", 155 | "info": { 156 | "update.js": "added feature to delete redundant files" 157 | } 158 | }, 159 | { 160 | "version": "1.1.11", 161 | "info": { 162 | "bot/handler/handlerCreateDB.js": "check id != 0", 163 | "bot/handler/handlerEvents.js": "check has database" 164 | } 165 | }, 166 | { 167 | "version": "1.1.12", 168 | "info": { 169 | "bot/handler/handlerEvents.js": "fix error" 170 | } 171 | }, 172 | { 173 | "version": "1.1.13", 174 | "info": { 175 | "index.js": "added listenMqtt restart feature", 176 | "config.json": "added listenMqtt restart feature", 177 | "bot/login.js": "added listenMqtt restart feature" 178 | } 179 | }, 180 | { 181 | "version": "1.1.14", 182 | "info": { 183 | "scripts/cmds/cmd.js": "" 184 | } 185 | }, 186 | { 187 | "version": "1.1.15", 188 | "info": { 189 | "scripts/cmds/avatar.js": "fix api error" 190 | } 191 | }, 192 | { 193 | "version": "1.1.16", 194 | "info": { 195 | "scripts/cmds/notification.js": "fix error 408" 196 | } 197 | }, 198 | { 199 | "version": "1.1.17", 200 | "info": { 201 | "scripts/cmds/rules.js": "fix lỗi remove" 202 | } 203 | }, 204 | { 205 | "version": "1.1.18", 206 | "info": { 207 | "scripts/cmds/count.js": "thêm thứ tự số hạng" 208 | } 209 | }, 210 | { 211 | "version": "1.1.19", 212 | "info": { 213 | "scripts/cmds/thread.js": "fix lỗi band không tác dụng" 214 | } 215 | }, 216 | { 217 | "version": "1.1.20", 218 | "info": { 219 | "database/dataProcessing/handlerData.js": "thêm giới tính vào dữ liệu members của nhóm", 220 | "scripts/cmds/pairing.js": "lệnh mới - ghép đôi ngẫu nhiên với một người trong nhóm chat", 221 | "scripts/cmds/refresh.js": "lệnh mới - cập nhật dữ liệu", 222 | "scripts/cmds/user.js": "fix lỗi tìm kiếm người dùng", 223 | "scripts/cmds/thread.js": "fix lỗi tìm kiếm nhóm" 224 | } 225 | }, 226 | { 227 | "version": "1.1.21", 228 | "info": { 229 | "scripts/cmds/unsend.js": "" 230 | } 231 | }, 232 | { 233 | "version": "1.1.22", 234 | "info": { 235 | "scripts/cmds/avatar.js": "" 236 | } 237 | }, 238 | { 239 | "version": "1.1.23", 240 | "info": { 241 | "scripts/cmds/avatar.js": "hiển thị lỗi khi tải thất bại" 242 | } 243 | }, 244 | { 245 | "version": "1.1.24", 246 | "info": { 247 | "bot/handler/handlerEvents.js": "", 248 | "scripts/cmds/thread.js": "fix lỗi ban thread & unban", 249 | "scripts/cmds/bannedlist.js": "lệnh mới - xem danh sách nhóm/người dùng bị cấm" 250 | } 251 | }, 252 | { 253 | "version": "1.1.25", 254 | "info": { 255 | "scripts/cmds/thread.js": "tối ưu hoá code", 256 | "scripts/cmds/user.js": "tối ưu hoá code", 257 | "scripts/cmds/bannedlist.js": "tối ưu hoá code" 258 | } 259 | }, 260 | { 261 | "version": "1.2.0", 262 | "info": { 263 | "database/dataProcessing/handlerData.js": "add lastUpdate to data" 264 | } 265 | }, 266 | { 267 | "version": "1.2.1", 268 | "info": { 269 | "scripts/cmds/rules.js": "tối ưu hoá code & fix bugs" 270 | } 271 | }, 272 | { 273 | "version": "1.2.2", 274 | "info": { 275 | "scripts/cmds/avatar.js": "code optimization", 276 | "scripts/cmds/banner.js": "code optimization", 277 | "scripts/cmds/banner2.js": "code optimization", 278 | "scripts/cmds/bannerbw.js": "code optimization" 279 | } 280 | }, 281 | { 282 | "version": "1.2.3", 283 | "info": { 284 | "scripts/cmds/moon.js": "get image moon on date of birth", 285 | "scripts/cmds/src/font/Kanit-SemiBoldItalic.ttf": "new font" 286 | } 287 | }, 288 | { 289 | "version": "1.2.4", 290 | "info": { 291 | "scripts/cmds/moon.js": "fix bugs" 292 | } 293 | }, 294 | { 295 | "version": "1.2.5", 296 | "info": { 297 | "scripts/events/logsbot.js": "automatically change the bot's nickname when entering a new box" 298 | } 299 | }, 300 | { 301 | "version": "1.2.6", 302 | "info": { 303 | "scripts/cmds/adduser.js": "fix bugs" 304 | } 305 | }, 306 | { 307 | "version": "1.2.7", 308 | "info": { 309 | "scripts/cmds/adduser.js": "change category \"info\" => \"box chat\"", 310 | "scripts/cmds/backupmongo.js": "update", 311 | "scripts/cmds/help.js": "simplify code", 312 | "scripts/cmds/reload.js": "add guide to config", 313 | "scripts/cmds/uptime.js": "change category \"system-bot\" => \"info\"", 314 | "scripts/cmds/setbox.js": "fix bugs when set img" 315 | } 316 | }, 317 | { 318 | "version": "1.2.8", 319 | "info": { 320 | "scripts/cmds/refresh.js": "fix bugs", 321 | "database/dataProcessing/handlerData.js": "code optimization" 322 | } 323 | }, 324 | { 325 | "version": "1.3.0", 326 | "info": { 327 | "bot/handler/handlerEvents.js": "fix args" 328 | } 329 | }, 330 | { 331 | "version": "1.3.1", 332 | "info": { 333 | "scripts/cmds/count.js": "shorten message", 334 | "scripts/cmds/setname.js": "new command set nickname for a group member", 335 | "scripts/events/autoUpdateInfoThread.js": "fix bugs that lose user data when leaving the group" 336 | } 337 | }, 338 | { 339 | "version": "1.3.2", 340 | "info": { 341 | "scripts/cmds/ytb.js": "fix bugs" 342 | } 343 | }, 344 | { 345 | "version": "1.3.3", 346 | "info": { 347 | "scripts/cmds/rules.js": "add new features" 348 | } 349 | }, 350 | { 351 | "version": "1.3.4", 352 | "info": { 353 | "scripts/cmds/cmd.js": "synchronized envGlobal & envConfig when load scripts", 354 | "scripts/cmds/help.js": "add version to info", 355 | "scripts/cmds/sleep.js": "new command", 356 | "scripts/cmds/wakeup.js": "new command", 357 | "bot/loadAllScript.js": "synchronized envGlobal & envConfig when load scripts", 358 | "index.js": "no description" 359 | } 360 | }, 361 | { 362 | "version": "1.4.0", 363 | "info": { 364 | "config.json": "có thể đăng nhập bot bằng email & password (nhập vào config)", 365 | "index.js": "có thể đăng nhập bot bằng email & password (nhập vào config)", 366 | "scripts/cmds/cmd.js": "đổi quyền sử dụng lệnh (1 => 2)", 367 | "scripts/cmds/help.js": "sửa vài lỗi chính tả", 368 | "scripts/cmds/logsbot.js": "đổi quyền sử dụng lệnh (1 => 2) & sửa vài lỗi chính tả", 369 | "scripts/cmds/uptime.js": "fix hiển thị giờ" 370 | } 371 | }, 372 | { 373 | "version": "1.4.1", 374 | "info": { 375 | "scripts/cmds/cmd.js": "no description", 376 | "scripts/cmds/help.js": "sửa vài lỗi chính tả", 377 | "scripts/cmds/logsbot.js": "đổi category (box chat => owner)", 378 | "scripts/cmds/prefix.js": "đổi category (custom => box chat)", 379 | "scripts/cmds/adminonly.js": "đổi category (admin => owner)", 380 | "scripts/cmds/leavemsg.js": "đổi category (box chat => custom)", 381 | "scripts/cmds/welcome.js": "đổi category (box chat => custom)", 382 | "scripts/cmds/setleave.js": "đổi category (box chat => custom)", 383 | "scripts/cmds/setwelcome.js": "đổi category (box chat => custom)", 384 | "scripts/cmds/reload.js": "fix bugs", 385 | "bot/loadAllScript.js": "no description", 386 | "index.js": "no description" 387 | } 388 | }, 389 | { 390 | "version": "1.4.2", 391 | "info": { 392 | "index.js": "fix error config is not defined" 393 | } 394 | }, 395 | { 396 | "version": "1.4.3", 397 | "info": { 398 | "scripts/cmds/help.js": "đổi giao diện ăn Tết 🙈", 399 | "scripts/cmds/avatar.js": "fix lỗi download", 400 | "scripts/cmds/count.js": "chỉ hiển thị số tin nhắn của thành viên trong nhóm", 401 | "scripts/cmds/customrankcard.js": "no description", 402 | "bot/handler/handlerEvents.js": "cập nhật message.guide()" 403 | } 404 | }, 405 | { 406 | "version": "1.4.4", 407 | "info": { 408 | "index.js": "no description", 409 | "logger/loading.js": "đổi màu hex trong exports.error (#000000 => #ff0000)", 410 | "logger/print.js": "đổi màu hex trong exports.error (#000000 => #ff0000)", 411 | "bot/createFuncMessage.js": "bổ sung event.threadID (dòng 4)", 412 | "bot/loadAllScript.js": "no description", 413 | "scripts/cmds/warn.js": "new commnad", 414 | "scripts/events/checkwarn.js": "new event commnad", 415 | "scripts/events/welcome.js": "no description" 416 | } 417 | }, 418 | { 419 | "version": "1.4.5", 420 | "info": { 421 | "scripts/cmds/warn.js": "update role" 422 | } 423 | }, 424 | { 425 | "version": "1.4.6", 426 | "info": { 427 | "scripts/cmds/leavemsg.js": "fix bugs" 428 | } 429 | }, 430 | { 431 | "version": "1.4.7", 432 | "info": { 433 | "scripts/events/autoUpdateInfoThread.js": "fix lỗi mất số tin nhắn (count) của thành viên khi out khỏi nhóm vào lại" 434 | } 435 | }, 436 | { 437 | "version": "1.4.8", 438 | "info": { 439 | "index.js": "đổi tên globalGoat.shortName thành globalGoat.shortNameCommands", 440 | "bot/loadAllScript.js": "đổi tên globalGoat.shortName thành globalGoat.shortNameCommands", 441 | "bot/handler/handlerEvents.js": "no description", 442 | "scripts/cmds/help.js": "có thể lấy commandName từ shortName" 443 | } 444 | }, 445 | { 446 | "version": "1.4.9", 447 | "info": { 448 | "bot/handler/handlerEvents.js": "no description" 449 | } 450 | }, 451 | { 452 | "version": "1.4.10", 453 | "info": { 454 | "update.js": "bỏ qua giá trị cũ của config.json (nếu có cập nhật file này)", 455 | "bot/handler/handlerEvents.js": "sửa lỗi commandName undefined" 456 | } 457 | }, 458 | { 459 | "version": "1.4.11", 460 | "info": { 461 | "config.json": "sửa lỗi listenMqtt", 462 | "index.js": "", 463 | "bot/login.js": "sửa lỗi listenMqtt bị x2", 464 | "bot/handlerAction.js": "kiểm tra database trước khi thực hiện lệnh", 465 | "scripts/cmds/adduser.js": "có thể thêm nhiều thành viên" 466 | } 467 | }, 468 | { 469 | "version": "1.4.12", 470 | "info": { 471 | "scripts/cmds/adduser.js": "sửa vài lỗi nhỏ" 472 | } 473 | }, 474 | { 475 | "version": "1.4.13", 476 | "info": { 477 | "scripts/cmds/adduser.js": "sửa vài lỗi nhỏ T.T" 478 | } 479 | }, 480 | { 481 | "version": "1.4.14", 482 | "info": { 483 | "scripts/cmds/help.js": "sửa lỗi \"cannot read property 'toLowerCase' of undefined\"" 484 | } 485 | }, 486 | { 487 | "version": "1.4.15", 488 | "info": { 489 | "scripts/cmds/rules.js": "thêm tính năng edit/chuyển đổi vị trí của 2 rules", 490 | "scripts/events/welcome.js": "tự đổi biệt danh bot khi vào box (nếu có điền trong config.json)" 491 | } 492 | }, 493 | { 494 | "version": "1.4.16", 495 | "info": { 496 | "scripts/cmds/adduser.js": "" 497 | } 498 | }, 499 | { 500 | "version": "1.4.17", 501 | "info": { 502 | "bot/createFuncMessage.js": "" 503 | } 504 | }, 505 | { 506 | "version": "1.4.18", 507 | "info": { 508 | "scripts/cmds/rules.js": "fix bug" 509 | } 510 | }, 511 | { 512 | "version": "1.4.19", 513 | "info": { 514 | "bot/login.js": "" 515 | } 516 | }, 517 | { 518 | "version": "1.4.20", 519 | "info": { 520 | "scripts/cmds/tikuser.js": "xem thông tin người dùng tiktok" 521 | } 522 | }, 523 | { 524 | "version": "1.4.21", 525 | "info": { 526 | "bot/login.js": "fix lỗi restart listenMqtt" 527 | } 528 | }, 529 | { 530 | "version": "1.4.22", 531 | "info": { 532 | "bot/loadData.js": "fix error Cannot find module '../database/dataProcessing/models/threadsModel.js'", 533 | "database/dataProcessing/handlerData.js": "", 534 | "bot/handler/handlerEvents.js": "" 535 | } 536 | }, 537 | { 538 | "version": "1.4.23", 539 | "info": { 540 | "scripts/cmds/logsbot.js": "fix bug" 541 | } 542 | }, 543 | { 544 | "version": "1.4.24", 545 | "info": { 546 | "scripts/cmds/callad.js": "fix bug", 547 | "scripts/cmds/cmd.js": "fix bug" 548 | } 549 | }, 550 | { 551 | "version": "1.4.25", 552 | "info": { 553 | "scripts/cmds/count.js": "", 554 | "database/dataProcessing/handlerData.js": "update function refreshInfo for thread" 555 | } 556 | }, 557 | { 558 | "version": "1.4.26", 559 | "info": { 560 | "scripts/cmds/user.js": "fix error \"Cannot read property 'toLowerCase' of null\" if user name is null", 561 | "scripts/cmds/thread.js": "fix error \"Cannot read property 'toLowerCase' of null\" if thread name is null" 562 | } 563 | }, 564 | { 565 | "version": "1.4.27", 566 | "info": { 567 | "bot/login.js": "fix error is undefined when error no stack" 568 | } 569 | }, 570 | { 571 | "version": "1.4.28", 572 | "info": { 573 | "scripts/cmds/moon.js": "fix error" 574 | } 575 | }, 576 | { 577 | "version": "1.4.29", 578 | "info": { 579 | "scripts/cmds/rules.js": "edit guide" 580 | } 581 | }, 582 | { 583 | "version": "1.4.30", 584 | "info": { 585 | "bot/login.js": "" 586 | } 587 | }, 588 | { 589 | "version": "1.4.31", 590 | "info": { 591 | "scripts/cmds/kick.js": "new command" 592 | } 593 | }, 594 | { 595 | "version": "1.4.32", 596 | "info": { 597 | "scripts/cmds/adduser.js": "new command" 598 | }, 599 | "del": { 600 | "scripts/cmds/sdtfb.js": "" 601 | } 602 | }, 603 | { 604 | "version": "1.4.32-extra", 605 | "info": { 606 | "bot/login.js": "change domain in 5 days", 607 | "scripts/cmds/avatar.js": "change domain in 5 days", 608 | "scripts/cmds/banner.js": "change domain in 5 days", 609 | "scripts/cmds/banner2.js": "change domain in 5 days", 610 | "scripts/cmds/bannerbw.js": "change domain in 5 days", 611 | "scripts/cmds/batslap.js": "change domain in 5 days", 612 | "scripts/cmds/customrankcard.js": "change domain in 5 days", 613 | "scripts/cmds/dhbc.js": "change domain in 5 days", 614 | "scripts/cmds/dhbcemoji.js": "change domain in 5 days", 615 | "scripts/cmds/jail.js": "change domain in 5 days", 616 | "scripts/cmds/rank.js": "change domain in 5 days" 617 | } 618 | }, 619 | { 620 | "version": "1.4.33", 621 | "info": { 622 | "update.js": "fixes data.del is not iterable" 623 | } 624 | }, 625 | { 626 | "version": "1.4.34", 627 | "info": { 628 | "scripts/cmds/adduser.js": "add require pkg axios", 629 | "bot/login.js": "go back to domain goatbot.tk", 630 | "scripts/cmds/avatar.js": "go back to domain goatbot.tk", 631 | "scripts/cmds/banner.js": "go back to domain goatbot.tk", 632 | "scripts/cmds/banner2.js": "go back to domain goatbot.tk", 633 | "scripts/cmds/bannerbw.js": "go back to domain goatbot.tk", 634 | "scripts/cmds/batslap.js": "go back to domain goatbot.tk", 635 | "scripts/cmds/customrankcard.js": "go back to domain goatbot.tk", 636 | "scripts/cmds/dhbc.js": "go back to domain goatbot.tk", 637 | "scripts/cmds/dhbcemoji.js": "go back to domain goatbot.tk", 638 | "scripts/cmds/jail.js": "go back to domain goatbot.tk", 639 | "scripts/cmds/rank.js": "go back to domain goatbot.tk" 640 | } 641 | }, 642 | { 643 | "version": "1.4.35", 644 | "info": { 645 | "update.js": "", 646 | "bot/login.js": "close project when listenMqtt returns error", 647 | "scripts/cmds/avatar.js": "" 648 | } 649 | }, 650 | { 651 | "version": "1.4.36", 652 | "info": { 653 | "bot/login.js": "change domain", 654 | "scripts/cmds/avatar.js": "change domain", 655 | "scripts/cmds/banner.js": "change domain", 656 | "scripts/cmds/banner2.js": "change domain", 657 | "scripts/cmds/bannerbw.js": "change domain", 658 | "scripts/cmds/batslap.js": "change domain", 659 | "scripts/cmds/customrankcard.js": "change domain", 660 | "scripts/cmds/dhbc.js": "change domain", 661 | "scripts/cmds/dhbcemoji.js": "change domain", 662 | "scripts/cmds/jail.js": "change domain", 663 | "scripts/cmds/rank.js": "change domain" 664 | } 665 | }, 666 | { 667 | "version": "1.4.37", 668 | "info": { 669 | "bot/login.js": "", 670 | "package.json": "change version dependences ytdl-core to 4.10.0" 671 | } 672 | }, 673 | { 674 | "version": "1.4.38", 675 | "info": { 676 | "bot/handler/handlerEvents.js": "fix bugs", 677 | "scripts/cmds/help.js": "fix bugs" 678 | } 679 | } 680 | ] --------------------------------------------------------------------------------