Created
February 1, 2026 03:36
-
-
Save taiapi/b0a11593082f4b4664bf9181553023be to your computer and use it in GitHub Desktop.
Upload code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const fs = require("fs-extra"); | |
| const path = require("path"); | |
| const axios = require("axios"); | |
| const crypto = require("crypto"); | |
| module.exports.config = { | |
| name: "code", | |
| version: "1.2.5", | |
| hasPermssion: 0, | |
| credits: "yamato", | |
| description: "Nhập giftcode Play Together", | |
| commandCategory: "Tiện ích", | |
| usages: "/code set <id> | add <id> | del <id> | list | clear | <giftcode>", | |
| cooldowns: 5 | |
| }; | |
| const URL = "https://vgrapi-sea.vnggames.com/coordinator/api/v1/code/redeem"; | |
| const SERVER_ID = "2"; | |
| const GAME_CODE = "661"; | |
| const LOGIN_URL = "https://billing.vnggames.com/fe/api/auth/quick"; | |
| const CLIENT_KEY = | |
| "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjIjoxMDY2MSwiYSI6MTA2NjEsInMiOjF9.B08-6v9oP3rNxrvImC-WBO-AN0mru77ZNLOgqosNIjA"; | |
| const DATA_DIR = path.join(__dirname, "cache"); | |
| const DB_FILE = path.join(DATA_DIR, "pt_ids_by_thread.json"); | |
| const TEMP_FILE = path.join(DATA_DIR, "pt_redeem_temp.json"); | |
| const EXPIRE_TIME = 24 * 60 * 60 * 1000; | |
| function uuid() { | |
| return crypto.randomUUID(); | |
| } | |
| function sleep(ms) { | |
| return new Promise(r => setTimeout(r, ms)); | |
| } | |
| function norm(s) { | |
| return String(s || "").trim(); | |
| } | |
| async function loadDB() { | |
| await fs.ensureDir(DATA_DIR); | |
| if (!(await fs.pathExists(DB_FILE))) await fs.writeJson(DB_FILE, {}); | |
| return fs.readJson(DB_FILE); | |
| } | |
| async function saveDB(db) { | |
| await fs.writeJson(DB_FILE, db, { spaces: 2 }); | |
| } | |
| async function loadTemp() { | |
| await fs.ensureDir(DATA_DIR); | |
| if (!(await fs.pathExists(TEMP_FILE))) await fs.writeJson(TEMP_FILE, {}); | |
| const data = await fs.readJson(TEMP_FILE); | |
| const now = Date.now(); | |
| for (const k in data) { | |
| if (now - data[k] > EXPIRE_TIME) delete data[k]; | |
| } | |
| await fs.writeJson(TEMP_FILE, data); | |
| return data; | |
| } | |
| async function saveTemp(d) { | |
| await fs.writeJson(TEMP_FILE, d); | |
| } | |
| async function checkRoleValid(roleId) { | |
| const data = new URLSearchParams({ | |
| platform: "mobile", | |
| clientKey: CLIENT_KEY, | |
| loginType: 9, | |
| lang: "VI", | |
| jtoken: "", | |
| userID: "", | |
| roleID: roleId, | |
| roleName: roleId, | |
| serverID: "", | |
| getVgaId: 1 | |
| }).toString(); | |
| try { | |
| const res = await axios.post(LOGIN_URL, data, { | |
| headers: { | |
| accept: "application/json, text/plain, */*", | |
| "content-type": "application/x-www-form-urlencoded; charset=UTF-8", | |
| origin: "https://shop.vnggames.com", | |
| referer: "https://shop.vnggames.com/", | |
| "user-agent": | |
| "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 Chrome/137.0.0.0 Mobile Safari/537.36" | |
| }, | |
| timeout: 15000, | |
| validateStatus: () => true | |
| }); | |
| if (res.data?.returnCode !== 1) return null; | |
| return { | |
| id: roleId, | |
| name: res.data?.data?.roleName || "Không rõ tên" | |
| }; | |
| } catch { | |
| return null; | |
| } | |
| } | |
| async function getRoleName(roleId) { | |
| const info = await checkRoleValid(roleId); | |
| return info ? info.name : roleId; | |
| } | |
| async function redeemForRole(roleId, giftcode) { | |
| const res = await axios.post( | |
| URL, | |
| { | |
| serverId: SERVER_ID, | |
| gameCode: GAME_CODE, | |
| roleId, | |
| roleName: roleId, | |
| code: giftcode | |
| }, | |
| { | |
| headers: { | |
| accept: "application/json, text/plain, */*", | |
| "content-type": "application/json", | |
| origin: "https://giftcode.vnggames.com", | |
| referer: "https://giftcode.vnggames.com/", | |
| "user-agent": | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/143.0.0.0 Safari/537.36", | |
| "x-client-region": "VN", | |
| "x-request-id": uuid() | |
| }, | |
| timeout: 20000, | |
| validateStatus: () => true | |
| } | |
| ); | |
| const d = res.data || {}; | |
| return ( | |
| d.success === true || | |
| d.code === 1 || | |
| d.errorCode === 0 || | |
| String(d.message || "").toLowerCase().includes("success") | |
| ); | |
| } | |
| module.exports.run = async function ({ api, event, args }) { | |
| const { threadID, messageID } = event; | |
| const sub = (args[0] || "").toLowerCase(); | |
| const db = await loadDB(); | |
| const temp = await loadTemp(); | |
| db[threadID] = Array.isArray(db[threadID]) ? db[threadID] : []; | |
| const saved = db[threadID]; | |
| if (sub === "list") { | |
| if (!saved.length) | |
| return api.sendMessage("ℹ️ Nhóm chưa có ID nào.", threadID, messageID); | |
| return api.sendMessage( | |
| `📌 ID đã lưu (${saved.length}):\n` + | |
| saved.map((x, i) => `${i + 1}. ${x}`).join("\n"), | |
| threadID, | |
| messageID | |
| ); | |
| } | |
| if (sub === "clear") { | |
| db[threadID] = []; | |
| await saveDB(db); | |
| return api.sendMessage("✅ Đã xoá toàn bộ ID.", threadID, messageID); | |
| } | |
| if (sub === "set" || sub === "add") { | |
| const ids = args.slice(1).map(norm).filter(Boolean); | |
| if (!ids.length) | |
| return api.sendMessage("❎ Dùng: /code add <id1> <id2> ...", threadID, messageID); | |
| let added = []; | |
| let existed = []; | |
| let invalid = []; | |
| for (const id of ids) { | |
| if (saved.includes(id)) { | |
| existed.push(id); | |
| continue; | |
| } | |
| const info = await checkRoleValid(id); | |
| if (!info) { | |
| invalid.push(id); | |
| continue; | |
| } | |
| saved.push(id); | |
| added.push(`${id} (${info.name})`); | |
| } | |
| db[threadID] = saved; | |
| await saveDB(db); | |
| let msg = ""; | |
| if (added.length) | |
| msg += `✅ Đã thêm (${added.length}):\n${added.join("\n")}\n`; | |
| if (existed.length) | |
| msg += `⚠️ Đã tồn tại (${existed.length}):\n${existed.join("\n")}\n`; | |
| if (invalid.length) | |
| msg += `❌ Không hợp lệ (${invalid.length}):\n${invalid.join("\n")}\n`; | |
| msg += `📦 Tổng ID: ${saved.length}`; | |
| return api.sendMessage(msg.trim(), threadID, messageID); | |
| } | |
| if (sub === "del") { | |
| const id = norm(args[1]); | |
| if (!id) return api.sendMessage("❎ Dùng: /code del <id>", threadID, messageID); | |
| db[threadID] = saved.filter(x => x !== id); | |
| await saveDB(db); | |
| return api.sendMessage( | |
| `✅ Đã xoá ID: ${id}\nCòn lại: ${db[threadID].length}`, | |
| threadID, | |
| messageID | |
| ); | |
| } | |
| const giftcode = norm(args[0]); | |
| if (!giftcode) { | |
| return api.sendMessage( | |
| "/code set <id>\n/code add <id>\n/code del <id>\n/code list\n/code clear\n/code <giftcode>", | |
| threadID, | |
| messageID | |
| ); | |
| } | |
| if (!saved.length) { | |
| return api.sendMessage("ℹ️ Chưa có ID nào. Dùng /code add trước.", threadID, messageID); | |
| } | |
| api.sendMessage( | |
| `⏳ Đang nhập code "${giftcode}" cho ${saved.length} ID...\n⏱️ Delay: 2s / 20ID`, | |
| threadID, | |
| messageID | |
| ); | |
| let success = 0; | |
| let fail = 0; | |
| let failList = []; | |
| for (let i = 0; i < saved.length; i++) { | |
| const rid = saved[i]; | |
| const key = rid + "|" + giftcode; | |
| if (temp[key]) continue; | |
| try { | |
| const ok = await redeemForRole(rid, giftcode); | |
| if (ok) { | |
| success++; | |
| temp[key] = Date.now(); | |
| await saveTemp(temp); | |
| } else { | |
| fail++; | |
| const name = await getRoleName(rid); | |
| failList.push(name); | |
| } | |
| } catch { | |
| fail++; | |
| const name = await getRoleName(rid); | |
| failList.push(name); | |
| } | |
| if ((i + 1) % 20 === 0 && i + 1 < saved.length) { | |
| await sleep(2000); | |
| } | |
| } | |
| let msg = | |
| `🎁 Giftcode: ${giftcode}\n` + | |
| `✅ Thành công: ${success}\n` + | |
| `❌ Thất bại: ${fail}`; | |
| if (failList.length) | |
| msg += `\n📄 Nhân vật lỗi:\n` + failList.join("\n"); | |
| return api.sendMessage(msg, threadID, messageID); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment