Integra estrategias LinkedIn en calendarios (backlog publicado vs pendiente), unifica roles/cookies de vista agencia y permite deshacer cambios de brandbook dejando constancia en el historial. Co-authored-by: Cursor <cursoragent@cursor.com>
133 lines
3.8 KiB
TypeScript
133 lines
3.8 KiB
TypeScript
/**
|
|
* Create client Drive roots for ECP + TSP under 03-Clientes if missing,
|
|
* link integrations + tenants.drive_folder_id, ensure Ads/RRSS creatives folders,
|
|
* re-enrich brandbooks.
|
|
*
|
|
* npx tsx scripts/ensure_ecp_tsp_drive.ts
|
|
*/
|
|
import { config } from 'dotenv';
|
|
import { resolve } from 'path';
|
|
config({ path: resolve(process.cwd(), '.env.local') });
|
|
|
|
import { enrichTenantBrandbook } from '../src/lib/brandbook-enrich';
|
|
import { ensureCreativesDriveFolders } from '../src/lib/creatives-drive';
|
|
import {
|
|
ensureChildFolder,
|
|
findClientesRootFolder,
|
|
listClientFoldersUnderClientes,
|
|
} from '../src/lib/google-drive';
|
|
|
|
const url = process.env.NEXT_PUBLIC_SUPABASE_URL!;
|
|
const key = process.env.SUPABASE_SERVICE_ROLE_KEY!;
|
|
const h = {
|
|
apikey: key,
|
|
Authorization: `Bearer ${key}`,
|
|
'Content-Type': 'application/json',
|
|
Prefer: 'return=minimal',
|
|
};
|
|
|
|
const TARGETS: { slug: string; folderName: string }[] = [
|
|
{ slug: 'ecp', folderName: '50-ECP Escuela de Cuidadores' },
|
|
{ slug: 'tsp', folderName: '51-TSP Talento Scholar Program' },
|
|
];
|
|
|
|
async function main() {
|
|
const listed = await listClientFoldersUnderClientes();
|
|
const root = listed.clientesRoot || (await findClientesRootFolder());
|
|
if (!root?.id) throw new Error('No se encontró carpeta Clientes en Drive');
|
|
console.log('Clientes root', root.name, root.id);
|
|
|
|
const folders = listed.folders;
|
|
|
|
for (const t of TARGETS) {
|
|
const tr = await fetch(
|
|
`${url}/rest/v1/tenants?slug=eq.${t.slug}&select=id,slug,name`,
|
|
{ headers: h }
|
|
);
|
|
const tenant = (await tr.json())[0] as
|
|
| { id: string; slug: string; name: string }
|
|
| undefined;
|
|
if (!tenant) {
|
|
console.log(`[skip] ${t.slug} no existe`);
|
|
continue;
|
|
}
|
|
|
|
let folder = folders.find((f) =>
|
|
t.slug === 'ecp'
|
|
? /ecp|cuidadores/i.test(f.name) && !/navidad/i.test(f.name)
|
|
: /tsp|scholar/i.test(f.name)
|
|
);
|
|
|
|
if (!folder) {
|
|
const id = await ensureChildFolder(root.id, t.folderName);
|
|
folder = { id, name: t.folderName };
|
|
console.log(`[create] ${t.folderName} → ${id}`);
|
|
} else {
|
|
console.log(`[exist] ${folder.name} → ${folder.id}`);
|
|
}
|
|
|
|
await fetch(
|
|
`${url}/rest/v1/integrations?tenant_id=eq.${tenant.id}&provider=eq.google_drive`,
|
|
{
|
|
method: 'PATCH',
|
|
headers: h,
|
|
body: JSON.stringify({
|
|
status: 'connected',
|
|
enabled: true,
|
|
external_account_id: folder.id,
|
|
label: folder.name,
|
|
updated_at: new Date().toISOString(),
|
|
}),
|
|
}
|
|
);
|
|
|
|
// Upsert if no google_drive row
|
|
const check = await fetch(
|
|
`${url}/rest/v1/integrations?tenant_id=eq.${tenant.id}&provider=eq.google_drive&select=id`,
|
|
{ headers: h }
|
|
);
|
|
const rows = (await check.json()) as { id: string }[];
|
|
if (!rows.length) {
|
|
await fetch(`${url}/rest/v1/integrations`, {
|
|
method: 'POST',
|
|
headers: h,
|
|
body: JSON.stringify({
|
|
tenant_id: tenant.id,
|
|
provider: 'google_drive',
|
|
status: 'connected',
|
|
enabled: true,
|
|
external_account_id: folder.id,
|
|
label: folder.name,
|
|
}),
|
|
});
|
|
}
|
|
|
|
await fetch(`${url}/rest/v1/tenants?id=eq.${tenant.id}`, {
|
|
method: 'PATCH',
|
|
headers: h,
|
|
body: JSON.stringify({ drive_folder_id: folder.id }),
|
|
});
|
|
|
|
const creatives = await ensureCreativesDriveFolders(tenant.id, t.slug);
|
|
console.log(
|
|
`[creatives] ${t.slug}`,
|
|
creatives.ok ? 'Ads+RRSS ok' : creatives.warning
|
|
);
|
|
|
|
const enrich = await enrichTenantBrandbook({
|
|
tenantId: tenant.id,
|
|
forceSeed: true,
|
|
});
|
|
console.log(
|
|
`[enrich] ${t.slug} ok=${enrich.ok} score=${enrich.completenessAfter} warn=${enrich.warning || '-'}`
|
|
);
|
|
}
|
|
|
|
console.log('Done');
|
|
}
|
|
|
|
main().catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
});
|