Ctrl K
ComunidadGuías…

src/trial-mail.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { trialOf } from './billing.js';
import { Weave } from './engine.js';
import { trialEmail } from './mail.js';

export const TRIAL_MAIL_DAYS = 3;
export const TRIAL_MAIL_EVERY = 60 * 60_000;

export function trialMailStage(trial, sent = {}) {
  if (!trial) return null;
  if (trial.daysLeft <= 1) return sent.last ? null : 'last';
  if (trial.daysLeft <= TRIAL_MAIL_DAYS) return sent.ending ? null : 'ending';
  return null;
}

export function architectAddresses(accounts = []) {
  const found = new Set();
  for (const a of accounts) {
    if (Weave.roleName(a.role) !== 'architect') continue;
    const mail = a.identities?.find((i) => i.verifiedEmail)?.verifiedEmail;
    if (mail) found.add(mail);
  }
  return [...found];
}

export async function sweepTrialMail({ hub, billing, mail, origin = '', now = Date.now, log = console.error } = {}) {
  const sent = [];
  if (!billing?.trialDays || typeof mail !== 'function') return { sent };
  for (const { name } of hub.list()) {
    const w = hub.get(name);
    if (!w?.state.meta.trialFrom || w.state.meta.deletedAt) continue;
    const trial = trialOf(w.billing(), billing.trialDays, now());
    const stage = trialMailStage(trial, w.state.meta.trialMail ?? {});
    if (!stage) continue;
    const to = architectAddresses(w.listAccounts());
    if (!to.length) continue;
    let standing;
    try {
      standing = await billing.standing({ workspace: w.billing(), accounts: w.listAccounts() });
    } catch (err) {
      log(`weave: the trial sweep could not read '${name}'s plan, so its mail waits: ${err?.message ?? err}`);
      continue;
    }
    if (standing.plan !== 'trial') continue;
    const letter = trialEmail({ workspace: name, stage, daysLeft: trial.daysLeft, endsAt: trial.endsAt, billing: `${origin}/w/${name}/billing`, origin });
    let went = 0;
    for (const address of to) {
      try {
        await mail({ to: address, subject: letter.subject, html: letter.html, text: letter.text });
        went += 1;
      } catch (err) {
        log(`weave: the ${stage} trial mail for '${name}' did not reach ${address}: ${err?.message ?? err}`);
      }
    }
    if (!went) continue;
    w.markTrialMail(stage, new Date(now()).toISOString());
    sent.push({ workspace: name, stage, to });
  }
  return { sent };
}