تخطَّ إلى المحتوى
ARAB CODEمجتمع المطورين العرب

نظام تتبع المحادثات

javascriptv1MITنُشر ٢٢ أغسطس ٢٠٢٦· ♥ 0 · ⬇ 1 · 💬 0

مراقب ومسجل للمحادثات والارقام والروابط

// plugins/chat_tracker.js
// 🕵️ نظام تتبع المحادثات الشامل - مع أسماء القنوات والمجموعات والروابط
// ✦ يسجل جميع الأرقام، المجموعات، القنوات مع أسمائها وروابطها
// 🛡️ للمطور فقط

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import chalk from 'chalk';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DATA_DIR = path.join(__dirname, '..', 'data', 'chat_tracker');

if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true });

// ============================================================
// 👑 المطور الأساسي
// ============================================================
const MAIN_OWNER = '447475774418';

// ============================================================
// 📂 دوال التخزين
// ============================================================
const USERS_FILE = path.join(DATA_DIR, 'users.json');
const GROUPS_FILE = path.join(DATA_DIR, 'groups.json');
const CHANNELS_FILE = path.join(DATA_DIR, 'channels.json');
const LOG_FILE = path.join(DATA_DIR, 'tracker.log');

function loadData(file) {
    try {
        if (fs.existsSync(file)) {
            return JSON.parse(fs.readFileSync(file, 'utf8'));
        }
    } catch (e) {}
    return {};
}

function saveData(file, data) {
    fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf8');
}

function logActivity(entry) {
    const log = `[${entry.time}] ${entry.type} | ${entry.user} | ${entry.name || 'غير معروف'} | ${entry.chatId} | ${entry.chatName || 'غير معروف'} | ${entry.message || 'وسائط'}\n`;
    fs.appendFileSync(LOG_FILE, log, 'utf8');
}

// ============================================================
// 🧠 دوال جلب الأسماء والروابط
// ============================================================
function generateChannelLink(channelId) {
    // استخراج الرقم من المعرف (إزالة @newsletter)
    const id = channelId.replace('@newsletter', '');
    return `https://whatsapp.com/channel/${id}`;
}

async function getChannelName(sock, channelId) {
    try {
        // محاولة جلب اسم القناة عبر newsletterGetMessages
        if (typeof sock.newsletterGetMessages === 'function') {
            const result = await sock.newsletterGetMessages(channelId, 1);
            if (result && result.messages && result.messages.length > 0) {
                // بعض الإصدارات تعيد اسم القناة في metadata
                if (result.messages[0]?.newsletterName) {
                    return result.messages[0].newsletterName;
                }
            }
        }
        // محاولة عبر query
        try {
            const result = await sock.query({
                tag: 'iq',
                attrs: { to: channelId, type: 'get', xmlns: 'w:newsletter' },
                content: [{ tag: 'metadata', attrs: {} }]
            });
            if (result?.content?.[0]?.content) {
                const metadata = result.content[0].content;
                if (metadata.attrs?.name) {
                    return metadata.attrs.name;
                }
            }
        } catch (e) {}
        return null;
    } catch (e) {
        return null;
    }
}

// ============================================================
// 🧠 المعالج التلقائي (يُستدعى لكل رسالة)
// ============================================================
export async function trackAll(sock, msg) {
    if (!msg.message || msg.key.fromMe) return;

    const sender = msg.key.participant || msg.sender;
    const chatId = msg.key.remoteJid;
    const isGroup = chatId.endsWith('@g.us');
    const isChannel = chatId.endsWith('@newsletter');
    const isPrivate = !isGroup && !isChannel;
    const text = msg.message.conversation || msg.message.extendedTextMessage?.text || '';
    const msgType = Object.keys(msg.message)[0] || 'unknown';

    // جلب اسم المرسل
    let senderName = 'غير معروف';
    try {
        if (sender) {
            senderName = await sock.getName(sender).catch(() => 'غير معروف');
        }
    } catch (e) {}

    // ====== تحديث بيانات المستخدم ======
    const users = loadData(USERS_FILE);
    if (!users[sender]) {
        users[sender] = {
            firstSeen: Date.now(),
            lastSeen: Date.now(),
            totalMessages: 0,
            name: senderName,
            privateChats: 0,
            groups: [],
            channels: [],
            lastMessage: '',
        };
    }
    users[sender].lastSeen = Date.now();
    users[sender].totalMessages++;
    users[sender].name = senderName;
    if (text) users[sender].lastMessage = text.slice(0, 50);

    // ====== تحديث بيانات المجموعات ======
    if (isGroup) {
        if (!users[sender].groups.includes(chatId)) {
            users[sender].groups.push(chatId);
        }
        const groups = loadData(GROUPS_FILE);
        if (!groups[chatId]) {
            let groupName = 'غير معروف';
            let memberCount = 0;
            try {
                const meta = await sock.groupMetadata(chatId);
                groupName = meta.subject || 'غير معروف';
                memberCount = meta.participants ? meta.participants.length : 0;
            } catch (e) {}
            groups[chatId] = {
                name: groupName,
                members: memberCount,
                firstSeen: Date.now(),
                lastSeen: Date.now(),
                totalMessages: 0,
                link: `https://chat.whatsapp.com/${chatId.replace('@g.us', '')}`,
            };
        }
        groups[chatId].lastSeen = Date.now();
        groups[chatId].totalMessages++;
        saveData(GROUPS_FILE, groups);
    }

    // ====== تحديث بيانات القنوات ======
    if (isChannel) {
        if (!users[sender].channels.includes(chatId)) {
            users[sender].channels.push(chatId);
        }
        const channels = loadData(CHANNELS_FILE);
        if (!channels[chatId]) {
            let channelName = 'غير معروف';
            try {
                const name = await getChannelName(sock, chatId);
                if (name) channelName = name;
            } catch (e) {}
            channels[chatId] = {
                name: channelName,
                firstSeen: Date.now(),
                lastSeen: Date.now(),
                totalMessages: 0,
                link: generateChannelLink(chatId),
            };
        }
        channels[chatId].lastSeen = Date.now();
        channels[chatId].totalMessages++;
        saveData(CHANNELS_FILE, channels);
    }

    if (isPrivate) {
        users[sender].privateChats++;
    }

    saveData(USERS_FILE, users);

    // ====== تسجيل النشاط مع اسم المحادثة ======
    let chatName = 'غير معروف';
    if (isGroup) {
        const groups = loadData(GROUPS_FILE);
        chatName = groups[chatId]?.name || 'غير معروف';
    } else if (isChannel) {
        const channels = loadData(CHANNELS_FILE);
        chatName = channels[chatId]?.name || 'غير معروف';
    } else {
        chatName = 'محادثة خاصة';
    }

    logActivity({
        time: new Date().toISOString(),
        type: isGroup ? 'GROUP' : isChannel ? 'CHANNEL' : 'PRIVATE',
        user: sender || 'unknown',
        name: senderName,
        chatId: chatId || 'unknown',
        chatName: chatName,
        message: text || `[${msgType}]`,
    });
}

// ============================================================
// 📊 عرض قائمة جميع المستخدمين
// ============================================================
function formatUserList(users) {
    const list = Object.entries(users).sort((a, b) => b[1].totalMessages - a[1].totalMessages);
    let reply = `👥 *جميع المتحدثين مع البوت (${list.length})*\n━━━━━━━━━━━━━━━━━━━━\n\n`;
    list.slice(0, 30).forEach(([id, data], i) => {
        const name = data.name || id?.split('@')[0] || 'غير معروف';
        const cleanId = id?.split('@')[0] || id || 'unknown';
        reply += `${i+1}. *${name}*\n`;
        reply += `   📱 ${cleanId}\n`;
        reply += `   📨 ${data.totalMessages} رسالة\n`;
        reply += `   🕒 آخر ظهور: ${new Date(data.lastSeen).toLocaleString('ar-EG')}\n`;
        if (data.groups && data.groups.length > 0) {
            reply += `   📁 ${data.groups.length} مجموعة\n`;
        }
        if (data.channels && data.channels.length > 0) {
            reply += `   📡 ${data.channels.length} قناة\n`;
        }
        if (data.privateChats > 0) {
            reply += `   📱 ${data.privateChats} محادثة خاصة\n`;
        }
        reply += '\n';
    });
    if (list.length > 30) {
        reply += `... و ${list.length - 30} مستخدم آخر\n`;
    }
    reply += `\n💡 استخدم \`.رسائل_المستخدم [الرقم]\` لعرض رسائل مستخدم معين`;
    return reply;
}

// ============================================================
// 📩 عرض رسائل مستخدم معين
// ============================================================
function getUserMessages(targetNumber) {
    try {
        const logs = fs.readFileSync(LOG_FILE, 'utf8');
        const lines = logs.split('\n').filter(line => line.includes(targetNumber));
        const recent = lines.slice(-30).reverse();
        if (recent.length === 0) return null;
        let reply = `📩 *رسائل ${targetNumber} (آخر ${recent.length})*\n━━━━━━━━━━━━━━━━━━━━\n\n`;
        recent.forEach(line => {
            const parts = line.split(' | ');
            if (parts.length >= 6) {
                const time = parts[0].replace('[', '').replace(']', '');
                const type = parts[1];
                const name = parts[2] || 'غير معروف';
                const chatId = parts[3] || 'غير معروف';
                const chatName = parts[4] || 'غير معروف';
                const msg = parts.slice(5).join(' | ').trim();
                reply += `🕒 ${new Date(time).toLocaleString('ar-EG')}\n`;
                reply += `📌 ${type} | ${name}\n`;
                reply += `📍 ${chatName} (${chatId})\n`;
                reply += `💬 ${msg}\n\n`;
            }
        });
        return reply;
    } catch (e) {
        return null;
    }
}

// ============================================================
// 📊 عرض المجموعات المسجلة مع الأسماء والروابط
// ============================================================
function formatGroups(groups) {
    const list = Object.entries(groups).sort((a, b) => b[1].totalMessages - a[1].totalMessages);
    if (list.length === 0) return '📭 لا توجد مجموعات مسجلة.';
    let reply = `👥 *المجموعات المسجلة (${list.length})*\n━━━━━━━━━━━━━━━━━━━━\n\n`;
    list.slice(0, 20).forEach(([id, data], i) => {
        reply += `${i+1}. 📌 *${data.name || id.split('@')[0]}*\n`;
        reply += `   🆔 ${id}\n`;
        reply += `   👥 ${data.members || 'غير معروف'} عضو\n`;
        reply += `   📨 ${data.totalMessages} رسالة\n`;
        reply += `   🕒 ${new Date(data.lastSeen).toLocaleString('ar-EG')}\n`;
        if (data.link) reply += `   🔗 ${data.link}\n`;
        reply += '\n';
    });
    return reply;
}

// ============================================================
// 📡 عرض القنوات المسجلة مع الأسماء والروابط
// ============================================================
function formatChannels(channels) {
    const list = Object.entries(channels).sort((a, b) => b[1].totalMessages - a[1].totalMessages);
    if (list.length === 0) return '📭 لا توجد قنوات مسجلة.';
    let reply = `📡 *القنوات المسجلة (${list.length})*\n━━━━━━━━━━━━━━━━━━━━\n\n`;
    list.slice(0, 20).forEach(([id, data], i) => {
        reply += `${i+1}. 📌 *${data.name || 'قناة غير معروفة'}*\n`;
        reply += `   🆔 ${id}\n`;
        reply += `   📨 ${data.totalMessages} رسالة\n`;
        reply += `   🕒 ${new Date(data.lastSeen).toLocaleString('ar-EG')}\n`;
        if (data.link) reply += `   🔗 ${data.link}\n`;
        reply += '\n';
    });
    return reply;
}

// ============================================================
// 📊 عرض إحصائيات عامة
// ============================================================
function getStats(users, groups, channels) {
    const totalUsers = Object.keys(users).length;
    const totalGroups = Object.keys(groups).length;
    const totalChannels = Object.keys(channels).length;
    const totalMessages = Object.values(users).reduce((sum, u) => sum + u.totalMessages, 0);
    const activeToday = Object.values(users).filter(u => {
        const last = new Date(u.lastSeen);
        const today = new Date();
        return last.getDate() === today.getDate() &&
               last.getMonth() === today.getMonth() &&
               last.getFullYear() === today.getFullYear();
    }).length;

    return {
        totalUsers,
        totalGroups,
        totalChannels,
        totalMessages,
        activeToday,
    };
}

// ============================================================
// 🎯 الأوامر الرئيسية
// ============================================================
let handler = async (m, { conn, text, command }) => {
    const sender = m.sender;

    // ✅ التحقق من المطور
    if (sender.replace(/[^0-9]/g, '') !== MAIN_OWNER.replace(/[^0-9]/g, '')) {
        return conn.sendMessage(m.chat, {
            text: `❌ هذا الأمر للمطور فقط.\n👑 المطور: ${MAIN_OWNER}`
        });
    }

    const users = loadData(USERS_FILE);
    const groups = loadData(GROUPS_FILE);
    const channels = loadData(CHANNELS_FILE);

    // ====== .جميع_المتحدثين ======
    if (command === 'جميع_المتحدثين' || command === 'all_speakers') {
        const reply = formatUserList(users);
        return m.reply(reply);
    }

    // ====== .رسائل_المستخدم [الرقم] ======
    if (command === 'رسائل_المستخدم' || command === 'user_messages') {
        if (!text) {
            return m.reply(`📩 *عرض رسائل المستخدم*\n\n📌 استخدم: \`.رسائل_المستخدم [الرقم]\`\n💡 مثال: \`.رسائل_المستخدم 1234567890\``);
        }
        const targetNumber = text.replace(/[^0-9]/g, '');
        if (!targetNumber || targetNumber.length < 8) {
            return m.reply('❌ رقم غير صحيح.');
        }
        const reply = getUserMessages(targetNumber);
        if (reply) {
            return m.reply(reply);
        } else {
            return m.reply(`📭 لا توجد رسائل مسجلة للرقم ${targetNumber}.`);
        }
    }

    // ====== .جميع_المجموعات ======
    if (command === 'جميع_المجموعات' || command === 'all_groups') {
        const reply = formatGroups(groups);
        return m.reply(reply);
    }

    // ====== .جميع_القنوات ======
    if (command === 'جميع_القنوات' || command === 'all_channels') {
        const reply = formatChannels(channels);
        return m.reply(reply);
    }

    // ====== .إحصائيات_التتبع ======
    if (command === 'إحصائيات_التتبع' || command === 'tracker_stats') {
        const stats = getStats(users, groups, channels);
        const reply = `📊 *إحصائيات تتبع المحادثات*\n━━━━━━━━━━━━━━━━━━━━\n\n` +
            `👥 إجمالي المتحدثين: ${stats.totalUsers}\n` +
            `📨 إجمالي الرسائل: ${stats.totalMessages}\n` +
            `📈 نشطاء اليوم: ${stats.activeToday}\n` +
            `👥 مجموعات: ${stats.totalGroups}\n` +
            `📡 قنوات: ${stats.totalChannels}\n` +
            `🕒 آخر تحديث: ${new Date().toLocaleString('ar-EG')}\n\n` +
            `📌 *الأوامر:*\n` +
            `• \`.جميع_المتحدثين\` - عرض جميع المستخدمين\n` +
            `• \`.رسائل_المستخدم [الرقم]\` - عرض رسائل مستخدم\n` +
            `• \`.جميع_المجموعات\` - عرض المجموعات مع الأسماء والروابط\n` +
            `• \`.جميع_القنوات\` - عرض القنوات مع الأسماء والروابط`;
        return m.reply(reply);
    }

    // ====== .مسح_سجل_التتبع ======
    if (command === 'مسح_سجل_التتبع' || command === 'clear_tracker') {
        try {
            fs.writeFileSync(USERS_FILE, JSON.stringify({}, null, 2), 'utf8');
            fs.writeFileSync(GROUPS_FILE, JSON.stringify({}, null, 2), 'utf8');
            fs.writeFileSync(CHANNELS_FILE, JSON.stringify({}, null, 2), 'utf8');
            fs.writeFileSync(LOG_FILE, '', 'utf8');
            await m.reply('🧹 *تم مسح جميع سجلات التتبع والمستخدمين والمجموعات والقنوات.*');
        } catch (e) {
            await m.reply(`❌ فشل المسح: ${e.message}`);
        }
        return;
    }

    // ====== مساعدة ======
    await m.reply(`🕵️ *نظام تتبع المحادثات الشامل*\n━━━━━━━━━━━━━━━━━━━━\n\n` +
        `📌 *الأوامر (للمطور فقط):*\n` +
        `1️⃣ \`.جميع_المتحدثين\` - عرض جميع المستخدمين\n` +
        `2️⃣ \`.رسائل_المستخدم [الرقم]\` - عرض رسائل مستخدم\n` +
        `3️⃣ \`.جميع_المجموعات\` - عرض المجموعات مع الأسماء والروابط\n` +
        `4️⃣ \`.جميع_القنوات\` - عرض القنوات مع الأسماء والروابط\n` +
        `5️⃣ \`.إحصائيات_التتبع\` - عرض إحصائيات عامة\n` +
        `6️⃣ \`.مسح_سجل_التتبع\` - مسح جميع السجلات\n\n` +
        `🔮 *يعمل تلقائياً:* يسجل كل رسالة واردة مع اسم القناة/المجموعة.`);
};

handler.help = [
    'جميع_المتحدثين', 'رسائل_المستخدم', 'جميع_المجموعات',
    'جميع_القنوات', 'إحصائيات_التتبع', 'مسح_سجل_التتبع'
];
handler.tags = ['owner'];
handler.command = [
    'جميع_المتحدثين', 'all_speakers',
    'رسائل_المستخدم', 'user_messages',
    'جميع_المجموعات', 'all_groups',
    'جميع_القنوات', 'all_channels',
    'إحصائيات_التتبع', 'tracker_stats',
    'مسح_سجل_التتبع', 'clear_tracker'
];

export default handler;

التعليقات (0)

سجّل الدخول للتعليق.