goat
command
e2ee
No description
0
views
0
likes
0
installs
raw source
/**
* e2ee.js — ported from Mari-v4's modules/commands/e2ee.js
*
* Purpose: interactive E2EE (Labyrinth encrypted chat) bridge test + an
* "info" explainer for how the bot tells a normal inbox DM apart from an
* E2EE inbox DM apart from an E2EE group.
*
* Detection logic (identical to Mari-v4's handleCommand.js / e2ee.js):
* - isE2EEThread : threadID is a JID string, i.e. it contains "@".
* Normal (non-E2EE) threads are plain numeric IDs.
* - isE2EEDM : isE2EEThread && !event.isGroup — by the time a
* command runs, event.isGroup has already been
* corrected against the DB (see shared.js buildContext,
* "resolvedIsGroup"), so this is reliable even though
* the raw MQTT guess for a brand-new E2EE JID can't
* always tell a DM from a group on its own.
* - normal inbox : senderID === threadID (Messenger's own convention
* for 1-to-1 threads — not a JID, no "@").
*
* Gating: this project already has a config-level inbox switch —
* global.GoatBot.config.antiInbox (toggled via the `security` command,
* {pn}security antiinbox on/off) — and includes/listen.js already blocks
* *all* non-group traffic (normal DM + E2EE DM) at the event level when
* antiInbox is true. That's the equivalent of Mari-v4's `allowInbox`
* flag, just inverted (antiInbox: true == allowInbox: false) and
* enforced earlier in the pipeline. So this command does NOT introduce a
* second config key — it reads the same global.GoatBot.config.antiInbox
* that security.js already writes, and adds a silent isE2EEDM-specific
* check as defense-in-depth for anyone who calls the command directly.
*/
module.exports = {
config: {
name: "e2ee",
version: "1.0.0",
author: "rX",
countDown: 5,
role: 0,
description: {
vi: "Kiểm tra cầu nối E2EE (mã hóa đầu cuối) và xem cách bot phân biệt inbox thường / inbox E2EE.",
en: "Test the E2EE (end-to-end encrypted) bridge and see how the bot tells normal inbox apart from E2EE inbox."
},
category: "system",
guide: {
vi:
` {pn}: chạy bài test tương tác (chỉ hoạt động trong đoạn chat E2EE)
{pn} info: giải thích cách bot nhận diện inbox thường / E2EE
{pn} status: xem trạng thái E2EE + Anti-Inbox hiện tại
Dùng {pn}security e2ee/antiinbox on|off để bật/tắt (chỉ bot admin).`,
en:
` {pn}: run the interactive bridge test (only works inside E2EE chats)
{pn} info: explain how the bot detects normal inbox vs E2EE inbox
{pn} status: show current E2EE + Anti-Inbox state
Use {pn}security e2ee/antiinbox on|off to toggle (bot admin only).`
}
},
langs: {
vi: {
testMsg: "🔒 Thử nghiệm E2EE\n━━━━━━━━━━━━━━━━\nTin nhắn của bạn đã được mã hóa đầu cuối.\n\nPhản hồi bằng số:\n1️⃣ 1 — Thử nghiệm Ping\n2️⃣ 2 — Thông tin luồng chat",
reply1: "✅ Pong! Cầu nối E2EE đang hoạt động hoàn hảo.",
reply2: "📋 Thông tin luồng chat E2EE\n━━━━━━━━━━━━━━━━\n• Thread: %1\n• Mã hóa: ✅ Có\n• Giao thức: Labyrinth\n• Cầu nối: Hoạt động",
replyOther: "❓ Tùy chọn không xác định. Vui lòng phản hồi bằng 1 hoặc 2.",
e2eeDisabled: "⚠️ Tính năng E2EE hiện đang bị tắt trong config.json (e2ee.enable). Dùng {pn}security e2ee on để bật (cần khởi động lại bot).",
notE2EE: "⚠️ Lệnh này chỉ hoạt động trong các cuộc trò chuyện mã hóa đầu cuối (E2EE).",
statusText: "🔐 E2EE: %1\n📥 Anti-Inbox: %2",
groupExplainer: "💡 Cách bot phân biệt các loại inbox:\n1️⃣ Inbox thường (DM): senderID == threadID (không có \"@\").\n2️⃣ E2EE inbox (DM): threadID là JID (chứa \"@\") và event.isGroup = false.\n3️⃣ E2EE nhóm: threadID là JID (chứa \"@\") nhưng event.isGroup = true — KHÔNG bị chặn bởi Anti-Inbox.\n\nKhi Anti-Inbox (antiInbox) đang BẬT, cả (1) và (2) đều bị bot bỏ qua hoàn toàn — chỉ (3) và các nhóm thường vẫn hoạt động."
},
en: {
testMsg: "🔒 E2EE Test\n━━━━━━━━━━━━━━━━\nYour message is end-to-end encrypted.\n\nReply with a number:\n1️⃣ 1 — Ping test\n2️⃣ 2 — Thread info",
reply1: "✅ Pong! E2EE bridge is working perfectly.",
reply2: "📋 E2EE Thread Info\n━━━━━━━━━━━━━━━━\n• Thread: %1\n• Encrypted: ✅ Yes\n• Protocol: Labyrinth\n• Bridge: Active",
replyOther: "❓ Unknown option. Reply with 1 or 2.",
e2eeDisabled: "⚠️ E2EE is currently disabled in config.json (e2ee.enable). Use {pn}security e2ee on to enable it (bot restart required).",
notE2EE: "⚠️ This command only works in E2EE (end-to-end encrypted) chats.",
statusText: "🔐 E2EE: %1\n📥 Anti-Inbox: %2",
groupExplainer: "💡 How the bot tells inbox types apart:\n1️⃣ Normal inbox (DM): senderID == threadID (no \"@\").\n2️⃣ E2EE inbox (DM): threadID is a JID (contains \"@\") and event.isGroup = false.\n3️⃣ E2EE group: threadID is a JID (contains \"@\") but event.isGroup = true — NEVER blocked by Anti-Inbox.\n\nWhen Anti-Inbox is ON, both (1) and (2) are silently ignored by the bot — only (3) and normal groups keep working."
}
},
onStart: async function ({ api, args, event, message, getLang }) {
const { threadID, messageID, senderID } = event;
const sub = (args[0] || "").toLowerCase();
if (sub === "info") {
return message.reply(getLang("groupExplainer"));
}
if (sub === "status") {
const config = global.GoatBot.config;
const e2eeState = config.e2ee?.enable === true ? "ON ✅" : "OFF ❌";
const antiInboxState = config.antiInbox === true ? "ON ✅ (inbox blocked)" : "OFF ❌ (inbox allowed)";
return message.reply(getLang("statusText", e2eeState, antiInboxState));
}
// ── Interactive bridge test ──────────────────────────────────────────
const e2eeEnabled = global.GoatBot.config.e2ee?.enable === true;
if (!e2eeEnabled) return message.reply(getLang("e2eeDisabled"));
// A JID threadID (contains "@") means an E2EE (Labyrinth) chat —
// normal Facebook thread IDs are plain numeric strings.
const isE2EEThread = typeof threadID === "string" && threadID.includes("@");
if (!isE2EEThread) return message.reply(getLang("notE2EE"));
// event.isGroup here is already the DB-resolved value (buildContext
// in shared.js corrects it against threadData before any command
// runs), so this reliably tells an E2EE 1-1 DM apart from an E2EE
// group even though the raw MQTT guess alone can't.
const isE2EEDM = isE2EEThread && !event.isGroup;
if (isE2EEDM && global.GoatBot.config.antiInbox === true) {
return; // Anti-Inbox is ON → silently ignore E2EE inbox, same as normal inbox
}
await api.setMessageReaction("🔒", messageID, () => {}, true).catch(() => {});
try {
await api.sendTypingIndicator(true, threadID, () => {}).catch(() => {});
await new Promise(resolve => setTimeout(resolve, 5000));
await api.sendTypingIndicator(false, threadID, () => {}).catch(() => {});
} catch (_) {
await new Promise(resolve => setTimeout(resolve, 5000));
}
return api.sendMessage(getLang("testMsg"), threadID, (err, info) => {
if (info && info.messageID) {
global.GoatBot.onReply.set(info.messageID, {
commandName: "e2ee",
messageID: info.messageID,
author: senderID,
threadID
});
}
}, messageID);
},
onReply: async function ({ api, event, Reply, getLang }) {
if (String(event.senderID) !== String(Reply.author)) return;
Reply.delete && Reply.delete();
const choice = (event.body || "").trim();
const { threadID, messageID } = event;
if (choice === "1") return api.sendMessage(getLang("reply1"), threadID, messageID);
if (choice === "2") return api.sendMessage(getLang("reply2", threadID), threadID, messageID);
return api.sendMessage(getLang("replyOther"), threadID, messageID);
}
};