-
- {group.name}
+
+ {group.name}
+ {isIgnored && (
+
+ ⛔ Ignorado
+
+ )}
{group.jid}
@@ -534,7 +584,11 @@ export default function AdminWhatsAppGroupsPage() {
- {isSelected ? (
+ {isIgnored ? (
+
+ Bloqueado
+
+ ) : isSelected ? (
Monitorear
diff --git a/dripzone-app/src/app/api/webhook/whatsapp/route.ts b/dripzone-app/src/app/api/webhook/whatsapp/route.ts
index 4a6d8a2..0cdf785 100644
--- a/dripzone-app/src/app/api/webhook/whatsapp/route.ts
+++ b/dripzone-app/src/app/api/webhook/whatsapp/route.ts
@@ -1,5 +1,5 @@
import { NextResponse } from 'next/server';
-import { dataService } from '@/lib/data-service';
+import { dataService, isGroupIgnoredOrBlacklisted } from '@/lib/data-service';
import { parseSupplierMessage, detectCategory } from '@/lib/gemini-parser';
import { sanitizePublicationTitle } from '@/lib/sanitizer';
import { generateAttractiveProductCopy } from '@/lib/attractive-copy';
@@ -14,6 +14,7 @@ import {
} from '@/lib/evolution-api';
import {
getMonitoredGroupsFromAppwrite,
+ saveMonitoredGroupToAppwrite,
saveProductToAppwrite,
saveSupplierPostToAppwrite,
updateSupplierPostStatusInAppwrite,
@@ -238,7 +239,7 @@ export async function POST(request: Request) {
}
// =========================================================================
- // CASO B: GRUPOS MAYORISTAS DE PROVEEDORES (Publicación Automática Incondicional)
+ // CASO B: GRUPOS MAYORISTAS DE PROVEEDORES (Monitoreo Estricto por Lista Blanca)
// =========================================================================
// Resolver el nombre del grupo de forma precisa usando Evolution API si no viene en el payload
let groupSubject = data.groupInfo?.subject || data.chatName || '';
@@ -255,6 +256,17 @@ export async function POST(request: Request) {
}
}
+ // 0. LISTA NEGRA PERMANENTE DE GRUPOS IGNORADOS (Blacklist incondicional)
+ if (isGroupIgnoredOrBlacklisted(remoteJid, groupSubject)) {
+ console.log(`[DripZone Webhook] Grupo IGNORADO por lista negra: "${groupSubject}" (${remoteJid})`);
+ return NextResponse.json({
+ success: true,
+ ignored: 'Grupo en lista negra comercial permanente (no monitorear ni publicar)',
+ chat: groupSubject,
+ remoteJid,
+ });
+ }
+
// 1. FILTRAR EXCLUSIVAMENTE GRUPOS DE PRENSA Y GOBIERNO (Reenviar a portal de noticias Almeira)
const isNonProductNews = /gob cauca|gobernacion|alcaldia|prensa|medios|noticias|comunicaciones|sedes asociadas|notificaciones almeira|inelpac|meliextra|almeira producciones|publicaciones almeira|quilichao en medios/i.test(
groupSubject
@@ -292,25 +304,68 @@ export async function POST(request: Request) {
});
}
- // Auto-registrar grupo como monitoreado y activo si no existía previamente
- try {
- const currentGroups = dataService.getMonitoredGroups();
- const existingGrp = currentGroups.find((g) => g.jid === remoteJid);
- if (!existingGrp) {
- dataService.saveMonitoredGroups([
- ...currentGroups,
- {
- id: `grp-${remoteJid.replace(/\D/g, '').slice(-8)}`,
- jid: remoteJid,
- name: groupSubject,
- isMonitored: true,
- autoPublish: true,
- notes: 'Auto-registrado desde Webhook activo de WhatsApp',
- supplierName: groupSubject,
- },
- ]);
- }
- } catch (_) {}
+ // 1.2 FILTRAR CONTENIDO DE EVENTOS, CONFERENCIAS, REUNIONES VIRTUALES O SPAM
+ const isSpamOrAnnouncement = /conferencia|webinar|zoom\.us|pantalla de zoom|podcast|mañanas millonarias|liderazgo|liderea|orador|taller virtual|evento online|conversaciones m[aá]s dinero|estrategia que funciona|elevax10n|smoothie|strawberry flavored|smartwatch|reloj inteligente|forex|cripto|trading|hoy 🚨|empezamos en \d+ minutos|llamada 911/i.test(
+ `${messageContent} ${groupSubject}`
+ );
+ if (isSpamOrAnnouncement) {
+ console.log(`[DripZone Webhook] Mensaje descartado por ser anuncio/evento/no calzado: "${messageContent.slice(0, 60)}"`);
+ return NextResponse.json({
+ success: true,
+ ignored: 'Mensaje es un anuncio, evento o contenido no calzado',
+ chat: groupSubject,
+ remoteJid,
+ });
+ }
+
+ // 1.3 VERIFICAR QUE EL GRUPO ESTÉ EXPRESAMENTE MONITOREADO Y ACTIVO
+ let currentGroups = dataService.getMonitoredGroups();
+ let existingGrp = currentGroups.find(
+ (g) => g.jid === remoteJid || g.name.toLowerCase().replace(/\s+/g, ' ').trim() === groupSubject.toLowerCase().replace(/\s+/g, ' ').trim()
+ );
+
+ if (!existingGrp) {
+ try {
+ const appwriteGroups = await getMonitoredGroupsFromAppwrite();
+ existingGrp = appwriteGroups.find((g) => g.jid === remoteJid);
+ if (existingGrp) {
+ dataService.saveMonitoredGroups([...currentGroups, existingGrp]);
+ }
+ } catch (_) {}
+ }
+
+ // Si el grupo nunca se ha configurado, registrarlo como INACTIVO (pendiente de aprobación en panel)
+ if (!existingGrp) {
+ const newGroupDoc = {
+ id: `grp-${remoteJid.replace(/\D/g, '').slice(-8)}`,
+ jid: remoteJid,
+ name: groupSubject,
+ isMonitored: false,
+ autoPublish: false,
+ notes: 'Detectado en webhook (inactivo por defecto)',
+ supplierName: groupSubject,
+ };
+ dataService.saveMonitoredGroups([...currentGroups, newGroupDoc]);
+ saveMonitoredGroupToAppwrite(newGroupDoc).catch(() => {});
+ console.log(`[DripZone Webhook] Nuevo grupo detectado pero REGISTRADO COMO INACTIVO: "${groupSubject}" (${remoteJid})`);
+ return NextResponse.json({
+ success: true,
+ ignored: 'Grupo nuevo no monitoreado (registrado inactivo en panel admin)',
+ chat: groupSubject,
+ remoteJid,
+ });
+ }
+
+ // Si el grupo está desactivado o tiene auto-publicación apagada
+ if (!existingGrp.isMonitored || existingGrp.autoPublish === false) {
+ console.log(`[DripZone Webhook] Mensaje descartado: grupo no monitoreado o autoPublish apagado: "${groupSubject}" (${remoteJid})`);
+ return NextResponse.json({
+ success: true,
+ ignored: 'Grupo no monitoreado o auto-publicación apagada',
+ chat: groupSubject,
+ remoteJid,
+ });
+ }
// 2. VERIFICACIÓN DE DUPLICADOS
if (isDuplicateMessage(whatsappMessageId, messageContent)) {
@@ -397,6 +452,17 @@ export async function POST(request: Request) {
};
}
+ // Validación de coherencia y descarte de spam
+ const invalidTitleCheck = /hoy 🚨|conferencia|evento|zoom|podcast|mañanas millonarias|liderea|sin producto|elevax10n|smoothie|no especificado/i;
+ if (invalidTitleCheck.test(extracted.name || '') || invalidTitleCheck.test(messageContent)) {
+ console.log(`[DripZone Webhook] Publicación cancelada por contenido no comercial/calzado: "${extracted.name}"`);
+ return NextResponse.json({
+ success: true,
+ ignored: 'Contenido descartado por no ser calzado o producto legítimo',
+ name: extracted.name,
+ });
+ }
+
// Categorización segura
if (!extracted.category || extracted.category === 'Calzado / Sneakers' || extracted.category === 'Sneakers / Colección') {
extracted.category = detectCategory(`${extracted.name || ''} ${messageContent}`).category;
diff --git a/dripzone-app/src/app/api/whatsapp-groups/route.ts b/dripzone-app/src/app/api/whatsapp-groups/route.ts
index ea8d76a..29a6559 100644
--- a/dripzone-app/src/app/api/whatsapp-groups/route.ts
+++ b/dripzone-app/src/app/api/whatsapp-groups/route.ts
@@ -1,5 +1,5 @@
import { NextResponse } from 'next/server';
-import { dataService } from '@/lib/data-service';
+import { dataService, isGroupIgnoredOrBlacklisted } from '@/lib/data-service';
import { MonitoredWhatsAppGroup } from '@/types';
import {
getMonitoredGroupsFromAppwrite,
@@ -22,7 +22,7 @@ export async function GET(request: Request) {
const appwriteGroups = await getMonitoredGroupsFromAppwrite();
if (appwriteGroups.length > 0) {
dataService.saveMonitoredGroups(appwriteGroups);
- localGroups = appwriteGroups;
+ localGroups = dataService.getMonitoredGroups();
}
} catch (err) {
console.warn('Error leyendo grupos desde Appwrite:', err);
@@ -36,24 +36,46 @@ export async function GET(request: Request) {
});
}
- // Consultar grupos en vivo desde Evolution API usando findChats (base de datos local rápida sin rate-limits)
+ // Consultar grupos en vivo desde Evolution API usando findChats y fetchAllGroups
try {
- const response = await fetch(
- `${EVOLUTION_API_URL}/chat/findChats/${EVOLUTION_INSTANCE_NAME}`,
- {
- method: 'POST',
- headers: {
- apikey: EVOLUTION_API_KEY,
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({}),
+ let liveGroups: any[] = [];
+ try {
+ const response = await fetch(
+ `${EVOLUTION_API_URL}/group/fetchAllGroups/${EVOLUTION_INSTANCE_NAME}?getParticipants=false`,
+ {
+ headers: { apikey: EVOLUTION_API_KEY },
+ signal: AbortSignal.timeout(8000),
+ }
+ );
+ if (response.ok) {
+ const all = await response.json();
+ if (Array.isArray(all) && all.length > 0) {
+ liveGroups = all.map((g: any) => ({
+ remoteJid: g.id || g.jid,
+ name: g.subject || g.name || 'Grupo WhatsApp',
+ size: g.size,
+ }));
+ }
}
- );
+ } catch (_) {}
- const allChats = await response.json();
- const liveGroups = (Array.isArray(allChats) ? allChats : []).filter(
- (c: any) => (c.remoteJid && c.remoteJid.includes('@g.us')) || (c.id && c.id.includes('@g.us'))
- );
+ if (liveGroups.length === 0) {
+ const response = await fetch(
+ `${EVOLUTION_API_URL}/chat/findChats/${EVOLUTION_INSTANCE_NAME}`,
+ {
+ method: 'POST',
+ headers: {
+ apikey: EVOLUTION_API_KEY,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({}),
+ }
+ );
+ const allChats = await response.json();
+ liveGroups = (Array.isArray(allChats) ? allChats : []).filter(
+ (c: any) => (c.remoteJid && c.remoteJid.includes('@g.us')) || (c.id && c.id.includes('@g.us'))
+ );
+ }
if (liveGroups.length > 0) {
const merged: MonitoredWhatsAppGroup[] = await Promise.all(
@@ -61,49 +83,34 @@ export async function GET(request: Request) {
const jid = lg.remoteJid || lg.id || lg.jid;
const name = lg.name || lg.pushName || lg.subject || 'Grupo WhatsApp';
let isStillMember = true;
- let participants = undefined;
+ let participants = lg.size || undefined;
- try {
- const infoRes = await fetch(
- `${EVOLUTION_API_URL}/group/findGroupInfos/${EVOLUTION_INSTANCE_NAME}?groupJid=${jid}`,
- {
- headers: { apikey: EVOLUTION_API_KEY },
- signal: AbortSignal.timeout(3500),
- }
- );
- if (infoRes.status === 404 || infoRes.status === 401 || infoRes.status === 403) {
- isStillMember = false;
- } else if (infoRes.ok) {
- const infoData = await infoRes.json();
- if (Array.isArray(infoData.participants)) {
- participants = infoData.participants.length;
- }
- }
- } catch {
- // Si falla por timeout, mantener estado previo
- }
+ const isBlacklisted = isGroupIgnoredOrBlacklisted(jid, name);
+ const existing = localGroups.find(
+ (g) => g.jid === jid || g.name.toLowerCase().replace(/\s+/g, ' ').trim() === name.toLowerCase().replace(/\s+/g, ' ').trim()
+ );
- const existing = localGroups.find((g) => g.jid === jid || g.name.toLowerCase() === name.toLowerCase());
-
- // Pre-marcar como monitoreados grupos reconocidos de proveedores si no había configuración previa
- const isKnownSupplierGroup = /exclusive|emporio|jovic|diamonds|mayorista|calzado|sneakers|zapatillas/i.test(name);
- const isMonitored = existing
+ // Pre-marcar SOLO proveedores exclusivos verificados de calzado si no había configuración previa
+ const isKnownSupplierGroup = !isBlacklisted && /exclusive cc|jovic store/i.test(name);
+ const isMonitored = isBlacklisted ? false : (existing
? (existing.isMonitored && isStillMember)
- : (isKnownSupplierGroup && isStillMember);
+ : (isKnownSupplierGroup && isStillMember));
return {
- id: existing?.id || `grp-${jid.replace(/\D/g, '').slice(-6)}`,
+ id: existing?.id || `grp-${jid.replace(/\D/g, '').slice(-8)}`,
jid,
name,
- isMonitored: isStillMember ? isMonitored : false,
+ isMonitored: isBlacklisted ? false : (isStillMember ? isMonitored : false),
isStillMember,
hasLeft: !isStillMember,
supplierId: existing?.supplierId,
supplierName: existing?.supplierName || name,
profitMarginOverride: existing?.profitMarginOverride || 35,
- autoPublish: existing?.autoPublish ?? true,
+ autoPublish: isBlacklisted ? false : (existing?.autoPublish ?? true),
participantsCount: participants ?? lg.unreadCount,
- notes: isStillMember ? (existing?.notes || '') : 'Saliste de este grupo en WhatsApp',
+ notes: isBlacklisted
+ ? 'IGNORADO EXPLICITAMENTE'
+ : isStillMember ? (existing?.notes || '') : 'Saliste de este grupo en WhatsApp',
};
})
);
@@ -145,7 +152,8 @@ export async function POST(request: Request) {
if (body.action === 'toggle' || body.action === 'deactivate-group') {
const { idOrJid, isMonitored } = body;
- const targetState = isMonitored !== undefined ? isMonitored : false;
+ const isBlacklisted = isGroupIgnoredOrBlacklisted(idOrJid);
+ const targetState = isBlacklisted ? false : (isMonitored !== undefined ? isMonitored : false);
const updated = dataService.toggleGroupMonitoring(idOrJid, targetState);
toggleMonitoredGroupInAppwrite(idOrJid, targetState).catch((e) =>
console.warn('Error sincronizando toggle con Appwrite:', e)
@@ -154,8 +162,14 @@ export async function POST(request: Request) {
}
if (Array.isArray(body.groups)) {
- const saved = dataService.saveMonitoredGroups(body.groups);
- Promise.all(body.groups.map((g: any) => saveMonitoredGroupToAppwrite(g))).catch((e) =>
+ const sanitized = body.groups.map((g: any) => {
+ if (isGroupIgnoredOrBlacklisted(g.jid, g.name)) {
+ return { ...g, isMonitored: false, autoPublish: false, notes: 'IGNORADO EXPLICITAMENTE' };
+ }
+ return g;
+ });
+ const saved = dataService.saveMonitoredGroups(sanitized);
+ Promise.all(sanitized.map((g: any) => saveMonitoredGroupToAppwrite(g))).catch((e) =>
console.warn('Error sincronizando grupos con Appwrite:', e)
);
return NextResponse.json({ success: true, groups: saved });
diff --git a/dripzone-app/src/lib/data-service.ts b/dripzone-app/src/lib/data-service.ts
index f675195..afe5269 100644
--- a/dripzone-app/src/lib/data-service.ts
+++ b/dripzone-app/src/lib/data-service.ts
@@ -227,6 +227,19 @@ export const INITIAL_USERS: User[] = [
},
];
+export const BLACKLISTED_WHATSAPP_GROUPS: string[] = [
+ '120363400148850031@g.us', // SOMOS BLACK DIAMONDS 💎💎💎
+ '120363420942364759@g.us', // 💎TEAM EMPORIO💎🔥👑❤️🔥🤯
+];
+
+export function isGroupIgnoredOrBlacklisted(jid: string, name?: string): boolean {
+ if (!jid) return false;
+ const cleanJid = jid.trim();
+ if (BLACKLISTED_WHATSAPP_GROUPS.includes(cleanJid)) return true;
+ if (name && /black diamonds|team emporio|emporio/i.test(name)) return true;
+ return false;
+}
+
export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [];
function getFsModule() {
@@ -1092,21 +1105,48 @@ class DataService {
return user || null;
}
- private monitoredGroups: MonitoredWhatsAppGroup[] = [...INITIAL_MONITORED_GROUPS];
+ private monitoredGroups: MonitoredWhatsAppGroup[] = loadPersistedData(
+ 'persisted_monitored_groups.json',
+ [...INITIAL_MONITORED_GROUPS]
+ );
getMonitoredGroups(): MonitoredWhatsAppGroup[] {
- return this.monitoredGroups;
+ if (!this.monitoredGroups || this.monitoredGroups.length === 0) {
+ this.monitoredGroups = loadPersistedData(
+ 'persisted_monitored_groups.json',
+ [...INITIAL_MONITORED_GROUPS]
+ );
+ }
+ return this.monitoredGroups.map((g) => {
+ if (isGroupIgnoredOrBlacklisted(g.jid, g.name)) {
+ return { ...g, isMonitored: false, autoPublish: false, notes: 'IGNORADO EXPLICITAMENTE' };
+ }
+ return g;
+ });
}
saveMonitoredGroups(groups: MonitoredWhatsAppGroup[]): MonitoredWhatsAppGroup[] {
- this.monitoredGroups = groups;
+ this.monitoredGroups = groups.map((g) => {
+ if (isGroupIgnoredOrBlacklisted(g.jid, g.name)) {
+ return { ...g, isMonitored: false, autoPublish: false, notes: 'IGNORADO EXPLICITAMENTE' };
+ }
+ return g;
+ });
+ savePersistedData('persisted_monitored_groups.json', this.monitoredGroups);
return this.monitoredGroups;
}
toggleGroupMonitoring(idOrJid: string, isMonitored: boolean): MonitoredWhatsAppGroup | null {
const grp = this.monitoredGroups.find((g) => g.id === idOrJid || g.jid === idOrJid);
if (grp) {
- grp.isMonitored = isMonitored;
+ if (isGroupIgnoredOrBlacklisted(grp.jid, grp.name)) {
+ grp.isMonitored = false;
+ grp.autoPublish = false;
+ grp.notes = 'IGNORADO EXPLICITAMENTE';
+ } else {
+ grp.isMonitored = isMonitored;
+ }
+ savePersistedData('persisted_monitored_groups.json', this.monitoredGroups);
return grp;
}
return null;
diff --git a/dripzone-app/src/lib/server-appwrite.ts b/dripzone-app/src/lib/server-appwrite.ts
index bdcbedc..0e95010 100644
--- a/dripzone-app/src/lib/server-appwrite.ts
+++ b/dripzone-app/src/lib/server-appwrite.ts
@@ -11,7 +11,7 @@ import {
MessageTemplate,
CustomProductRequest,
} from '@/types';
-import { INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_SUPPLIERS } from './data-service';
+import { INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_SUPPLIERS, isGroupIgnoredOrBlacklisted } from './data-service';
import { DEFAULT_MESSAGE_TEMPLATES } from './templates-service';
import { sanitizePublicationTitle, sanitizePublicationText } from './sanitizer';
@@ -717,15 +717,18 @@ export async function getMonitoredGroupsFromAppwrite(): Promise 0) {
- return res.documents.map((d: any) => ({
- id: d.$id,
- jid: d.jid || '',
- name: d.name || '',
- isMonitored: Boolean(d.isMonitored),
- autoPublish: d.autoPublish !== false,
- notes: d.notes || '',
- supplierName: d.name || '',
- }));
+ return res.documents.map((d: any) => {
+ const isBlacklisted = isGroupIgnoredOrBlacklisted(d.jid, d.name);
+ return {
+ id: d.$id,
+ jid: d.jid || '',
+ name: d.name || '',
+ isMonitored: isBlacklisted ? false : Boolean(d.isMonitored),
+ autoPublish: isBlacklisted ? false : d.autoPublish !== false,
+ notes: isBlacklisted ? 'IGNORADO EXPLICITAMENTE' : d.notes || '',
+ supplierName: d.name || '',
+ };
+ });
}
return [];
} catch (e: any) {
@@ -737,13 +740,14 @@ export async function getMonitoredGroupsFromAppwrite(): Promise
): Promise {
+ const isBlacklisted = isGroupIgnoredOrBlacklisted(group.jid || '', group.name);
const docId = group.id || `grp-${(group.jid || '').replace(/\D/g, '').slice(-8)}` || `grp-${Date.now()}`;
const payload = {
jid: group.jid || '',
name: group.name || '',
- isMonitored: Boolean(group.isMonitored),
- autoPublish: group.autoPublish !== false,
- notes: group.notes || '',
+ isMonitored: isBlacklisted ? false : Boolean(group.isMonitored),
+ autoPublish: isBlacklisted ? false : group.autoPublish !== false,
+ notes: isBlacklisted ? 'IGNORADO EXPLICITAMENTE' : group.notes || '',
};
try {
@@ -780,12 +784,24 @@ export async function toggleMonitoredGroupInAppwrite(
isMonitored: boolean
): Promise {
try {
- const groups = await getMonitoredGroupsFromAppwrite();
- const found = groups.find((g) => g.id === idOrJid || g.jid === idOrJid);
- if (found) {
- await serverDatabases.updateDocument(DB_ID, 'monitored_groups', found.id, {
- isMonitored,
- });
+ const isBlacklisted = isGroupIgnoredOrBlacklisted(idOrJid);
+ const finalState = isBlacklisted ? false : isMonitored;
+
+ const res = await serverDatabases.listDocuments(DB_ID, 'monitored_groups', [Query.limit(100)]);
+ const matchingDocs = res.documents.filter(
+ (d: any) => d.$id === idOrJid || d.jid === idOrJid || d.name === idOrJid
+ );
+
+ if (matchingDocs.length > 0) {
+ await Promise.all(
+ matchingDocs.map((doc: any) =>
+ serverDatabases.updateDocument(DB_ID, 'monitored_groups', doc.$id, {
+ isMonitored: finalState,
+ autoPublish: finalState,
+ notes: isBlacklisted ? 'IGNORADO EXPLICITAMENTE' : doc.notes,
+ })
+ )
+ );
return true;
}
return false;
diff --git a/scripts/clean_unwanted_supplier_products.js b/scripts/clean_unwanted_supplier_products.js
new file mode 100644
index 0000000..cc7d8f4
--- /dev/null
+++ b/scripts/clean_unwanted_supplier_products.js
@@ -0,0 +1,114 @@
+const sdk = require('node-appwrite');
+const client = new sdk.Client()
+ .setEndpoint('https://appwrite.almeira.com.co/v1')
+ .setProject('69b84df5003bd8957c5c')
+ .setKey('standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3');
+const dbs = new sdk.Databases(client);
+
+const DB_ID = 'sneakers_multistore_db';
+
+async function main() {
+ console.log('=== [1] ELIMINANDO PRODUCTOS BASURA DE LOS GRUPOS IGNORADOS ===');
+ let offset = 0;
+ const limit = 100;
+ const toDelete = [];
+
+ while (true) {
+ const res = await dbs.listDocuments(DB_ID, 'products', [
+ sdk.Query.limit(limit),
+ sdk.Query.offset(offset)
+ ]);
+ if (!res.documents || res.documents.length === 0) break;
+
+ for (const doc of res.documents) {
+ const sup = (doc.supplierName || '').toLowerCase();
+ const name = (doc.name || '').toLowerCase();
+ const raw = JSON.stringify(doc).toLowerCase();
+
+ if (
+ sup.includes('emporio') ||
+ sup.includes('black diamonds') ||
+ raw.includes('120363400148850031') ||
+ raw.includes('120363420942364759') ||
+ name.includes('hoy 🚨') ||
+ name.includes('liderea con')
+ ) {
+ // Asegurar que no borramos productos legítimos de Jovic o CC Mío
+ if (sup.includes('jovic') || sup.includes('cc mío') || sup.includes('exclusive')) {
+ continue;
+ }
+ toDelete.push({ id: doc['$id'], name: doc.name, supplier: doc.supplierName });
+ }
+ }
+ offset += limit;
+ if (offset >= res.total) break;
+ }
+
+ console.log(`Encontrados ${toDelete.length} productos para eliminar:`);
+ for (const p of toDelete) {
+ try {
+ await dbs.deleteDocument(DB_ID, 'products', p.id);
+ console.log(` ✓ Eliminado producto: ${p.id} - ${p.name} (${p.supplier})`);
+ } catch (e) {
+ console.error(` ✗ Error eliminando ${p.id}:`, e.message);
+ }
+ }
+
+ console.log('\n=== [2] SANITIZANDO COLECCIÓN MONITORED_GROUPS EN APPWRITE ===');
+ const groupsRes = await dbs.listDocuments(DB_ID, 'monitored_groups', [sdk.Query.limit(100)]);
+ console.log(`Total grupos en Appwrite: ${groupsRes.total}`);
+
+ const blacklistedJids = [
+ '120363400148850031@g.us', // SOMOS BLACK DIAMONDS
+ '120363420942364759@g.us', // TEAM EMPORIO
+ ];
+
+ // Agrupar por JID para eliminar duplicados
+ const groupsByJid = new Map();
+ for (const doc of groupsRes.documents) {
+ const jid = doc.jid;
+ if (!groupsByJid.has(jid)) {
+ groupsByJid.set(jid, []);
+ }
+ groupsByJid.get(jid).push(doc);
+ }
+
+ for (const [jid, docs] of groupsByJid.entries()) {
+ const isBlacklisted = blacklistedJids.includes(jid) ||
+ docs.some(d => /black diamonds|team emporio|emporio/i.test(d.name || ''));
+
+ // Mantener 1 documento canónico y eliminar duplicados
+ const canonicalDoc = docs[0];
+ const duplicates = docs.slice(1);
+
+ for (const dup of duplicates) {
+ try {
+ await dbs.deleteDocument(DB_ID, 'monitored_groups', dup['$id']);
+ console.log(` ✓ Eliminado documento duplicado: ${dup['$id']} (${jid})`);
+ } catch (e) {
+ console.error(` ✗ Error eliminando duplicado ${dup['$id']}:`, e.message);
+ }
+ }
+
+ if (isBlacklisted) {
+ try {
+ await dbs.updateDocument(DB_ID, 'monitored_groups', canonicalDoc['$id'], {
+ isMonitored: 0,
+ autoPublish: 0,
+ notes: 'IGNORADO EXPLICITAMENTE - NO PUBLICAR NI MONITOREAR',
+ });
+ console.log(` 🛑 Grupo marcado como IGNORADO permanentemente: ${canonicalDoc.name} (${jid})`);
+ } catch (e) {
+ console.error(` ✗ Error actualizando grupo ${canonicalDoc['$id']}:`, e.message);
+ }
+ }
+ }
+
+ console.log('\n=== [3] VERIFICACIÓN FINAL DE GRUPOS EN APPWRITE ===');
+ const finalRes = await dbs.listDocuments(DB_ID, 'monitored_groups', [sdk.Query.limit(100)]);
+ finalRes.documents.forEach((d) => {
+ console.log(`ID: ${d['$id']} | JID: ${d.jid} | isMonitored: ${d.isMonitored} | Name: ${d.name}`);
+ });
+}
+
+main().catch(console.error);
diff --git a/scripts/find_all_unwanted_products.js b/scripts/find_all_unwanted_products.js
new file mode 100644
index 0000000..4aa5dc8
--- /dev/null
+++ b/scripts/find_all_unwanted_products.js
@@ -0,0 +1,45 @@
+const sdk = require('node-appwrite');
+const client = new sdk.Client()
+ .setEndpoint('https://appwrite.almeira.com.co/v1')
+ .setProject('69b84df5003bd8957c5c')
+ .setKey('standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3');
+const dbs = new sdk.Databases(client);
+
+async function inspectAll() {
+ let offset = 0;
+ const limit = 100;
+ const toDelete = [];
+
+ while (true) {
+ const res = await dbs.listDocuments('sneakers_multistore_db', 'products', [
+ sdk.Query.limit(limit),
+ sdk.Query.offset(offset)
+ ]);
+ if (!res.documents || res.documents.length === 0) break;
+
+ for (const doc of res.documents) {
+ const sup = (doc.supplierName || '').toLowerCase();
+ const name = (doc.name || '').toLowerCase();
+ const raw = JSON.stringify(doc).toLowerCase();
+
+ if (
+ sup.includes('emporio') ||
+ sup.includes('black diamonds') ||
+ raw.includes('120363400148850031') ||
+ raw.includes('120363420942364759') ||
+ name.includes('hoy 🚨') ||
+ name.includes('liderea con')
+ ) {
+ toDelete.push({ id: doc.$id, name: doc.name, supplier: doc.supplierName });
+ }
+ }
+
+ offset += limit;
+ if (offset >= res.total) break;
+ }
+
+ console.log(`Encontrados ${toDelete.length} productos publicados de estos grupos:`);
+ toDelete.forEach(p => console.log(` - ID: ${p.id} | Nombre: ${p.name} | Proveedor: ${p.supplier}`));
+}
+
+inspectAll().catch(console.error);
diff --git a/scripts/inspect_target_products.js b/scripts/inspect_target_products.js
new file mode 100644
index 0000000..0e015b0
--- /dev/null
+++ b/scripts/inspect_target_products.js
@@ -0,0 +1,24 @@
+const sdk = require('node-appwrite');
+const client = new sdk.Client()
+ .setEndpoint('https://appwrite.almeira.com.co/v1')
+ .setProject('69b84df5003bd8957c5c')
+ .setKey('standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3');
+const dbs = new sdk.Databases(client);
+
+async function inspect() {
+ const ids = ['snk-1789056531032-5ut8', 'snk-1789057093753-lz2a', 'snk-1789058687729-e6zk'];
+ for (const id of ids) {
+ try {
+ const doc = await dbs.getDocument('sneakers_multistore_db', 'products', id);
+ console.log('--- PRODUCT:', doc['$id']);
+ console.log('Name:', doc.name);
+ console.log('Description:', (doc.description || '').slice(0, 150));
+ console.log('SupplierPostId:', doc.supplierPostId);
+ console.log('SupplierName:', doc.supplierName);
+ console.log('IsActive:', doc.isActive);
+ } catch(e) {
+ console.log('Error', id, e.message);
+ }
+ }
+}
+inspect().catch(console.error);
diff --git a/scripts/seed_monitored_groups.js b/scripts/seed_monitored_groups.js
index d412cf0..865aa41 100644
--- a/scripts/seed_monitored_groups.js
+++ b/scripts/seed_monitored_groups.js
@@ -20,9 +20,9 @@ const GROUPS_TO_SEED = [
{
jid: '120363420942364759@g.us',
name: '💎TEAM EMPORIO💎🔥👑❤️🔥🤯',
- isMonitored: true,
- autoPublish: true,
- notes: 'Proveedor Mayorista Team Emporio Sneakers',
+ isMonitored: false,
+ autoPublish: false,
+ notes: 'IGNORADO EXPLICITAMENTE - NO PUBLICAR NI MONITOREAR',
},
{
jid: '120363027254133375@g.us',
@@ -34,9 +34,9 @@ const GROUPS_TO_SEED = [
{
jid: '120363400148850031@g.us',
name: 'SOMOS BLACK DIAMONDS 💎💎💎',
- isMonitored: true,
- autoPublish: true,
- notes: 'Proveedor Mayorista Black Diamonds Sneakers',
+ isMonitored: false,
+ autoPublish: false,
+ notes: 'IGNORADO EXPLICITAMENTE - NO PUBLICAR NI MONITOREAR',
},
{
jid: '120363317242539420@g.us',