Spaces:
Paused
Paused
File size: 4,968 Bytes
ee826ee | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | /**
* ============================================
* π¦ extractor.js β Extractor Integrado v0.1+v0.2
* ============================================
* Zelin puede extraer datos del servidor cuando
* necesita actualizar su conocimiento.
* Combina la lΓ³gica de los bots v0.1 y v0.2.
*/
import { ChannelType, PermissionsBitField } from 'discord.js';
import * as db from './db.js';
import { sleep } from './utils.js';
// ββ ExtracciΓ³n de informaciΓ³n del servidor ββββββββββββββββββββββββββββββββββββ
export async function extractServerInfo(guild) {
return {
id : guild.id,
name : guild.name,
description : guild.description,
ownerId : guild.ownerId,
memberCount : guild.memberCount,
boostLevel : guild.premiumTier,
boostCount : guild.premiumSubscriptionCount ?? 0,
features : guild.features,
createdAt : guild.createdAt.toISOString(),
extractedAt : new Date().toISOString(),
};
}
// ββ ExtracciΓ³n y sync de roles ββββββββββββββββββββββββββββββββββββββββββββββββ
export async function syncAllRoles(guild) {
let count = 0;
for (const role of guild.roles.cache.values()) {
await db.upsertRole(role);
count++;
}
console.log(`[Extractor] ${count} roles sincronizados`);
return count;
}
// ββ ExtracciΓ³n y sync de canales βββββββββββββββββββββββββββββββββββββββββββββ
export async function syncAllChannels(guild) {
let count = 0;
for (const channel of guild.channels.cache.values()) {
await db.upsertChannel(channel);
count++;
}
console.log(`[Extractor] ${count} canales sincronizados`);
return count;
}
// ββ ExtracciΓ³n y sync de miembros βββββββββββββββββββββββββββββββββββββββββββββ
export async function syncAllMembers(guild, onProgress = null) {
await guild.members.fetch();
const members = [...guild.members.cache.values()];
let count = 0;
for (const member of members) {
await db.upsertUser(member);
const roleIds = [...member.roles.cache.keys()].filter(id => id !== guild.id);
await db.syncUserRoles(member.id, roleIds);
count++;
if (onProgress && count % 50 === 0) {
await onProgress(count, members.length);
}
await sleep(50); // Rate limit suave
}
console.log(`[Extractor] ${count} miembros sincronizados`);
return count;
}
// ββ ExtracciΓ³n de historial de mensajes de un canal βββββββββββββββββββββββββββ
export async function extractChannelMessages(channel, limit = 10000) {
let lastId = null;
let total = 0;
let hasMore = true;
while (hasMore && total < limit) {
const options = { limit: 100 };
if (lastId) options.before = lastId;
let batch;
try {
batch = await channel.messages.fetch(options);
} catch {
break;
}
if (batch.size === 0) break;
for (const message of batch.values()) {
if (message.author.bot) continue;
try {
await db.saveMessage(message);
total++;
} catch {
// Mensaje ya guardado o error, continuar
}
}
lastId = batch.last()?.id;
hasMore = batch.size === 100;
await sleep(1200); // Rate limit Discord
}
return total;
}
// ββ ExtracciΓ³n completa del servidor (para uso interno de Zelin) ββββββββββββββ
export async function runFullExtraction(guild, notifyProgress) {
console.log('[Extractor] Iniciando extracciΓ³n completa...');
const results = { members: 0, roles: 0, channels: 0, messages: 0 };
// Roles
if (notifyProgress) await notifyProgress('π Sincronizando roles...');
results.roles = await syncAllRoles(guild);
// Canales
if (notifyProgress) await notifyProgress('π Sincronizando canales...');
results.channels = await syncAllChannels(guild);
// Miembros
if (notifyProgress) await notifyProgress('π₯ Sincronizando miembros...');
results.members = await syncAllMembers(guild, async (done, total) => {
if (notifyProgress) await notifyProgress(`π₯ Miembros: ${done}/${total}`);
});
// Mensajes (canales de texto pΓΊblicos, ΓΊltimos 5000)
if (notifyProgress) await notifyProgress('π¬ Extrayendo mensajes recientes...');
const textChannels = [...guild.channels.cache.values()]
.filter(c => c.type === ChannelType.GuildText);
for (const channel of textChannels) {
try {
const count = await extractChannelMessages(channel, 5000);
results.messages += count;
} catch {
// Canal sin permisos, continuar
}
}
console.log('[Extractor] ExtracciΓ³n completa:', results);
return results;
}
|