File size: 2,234 Bytes
0f84d64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import fs from 'fs/promises';
import path from 'path';

const DATA_DIR = '/data';
const STORE_FILE = path.join(DATA_DIR, 'web-search-usage.json');
const APP_TIMEZONE = process.env.APP_TIMEZONE || 'America/New_York';

let state = { days: {} };
let loaded = false;
let saveChain = Promise.resolve();

function todayKey() {
  return new Intl.DateTimeFormat('en-CA', {
    timeZone: APP_TIMEZONE,
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
  }).format(new Date());
}

function pruneDays() {
  const keepKey = todayKey();
  state.days = Object.fromEntries(
    Object.entries(state.days || {}).filter(([key]) => key === keepKey)
  );
}

async function ensureLoaded() {
  if (loaded) return;
  loaded = true;
  try {
    await fs.mkdir(DATA_DIR, { recursive: true });
    const raw = await fs.readFile(STORE_FILE, 'utf8');
    const parsed = JSON.parse(raw);
    if (parsed && typeof parsed === 'object') state = parsed;
  } catch {}
  pruneDays();
}

function saveState() {
  saveChain = saveChain.then(async () => {
    pruneDays();
    await fs.mkdir(DATA_DIR, { recursive: true });
    await fs.writeFile(STORE_FILE, JSON.stringify(state, null, 2), 'utf8');
  }).catch((err) => {
    console.error('Failed to persist web search usage:', err);
  });
  return saveChain;
}

function getCounterRecord(key) {
  const day = todayKey();
  if (!state.days[day]) state.days[day] = {};
  if (!state.days[day][key]) state.days[day][key] = 0;
  return {
    day,
    used: state.days[day][key],
    set(nextValue) {
      state.days[day][key] = nextValue;
    },
  };
}

export async function getWebSearchUsage(key, limit = 15) {
  await ensureLoaded();
  const record = getCounterRecord(key);
  return {
    limit,
    used: record.used,
    remaining: Math.max(0, limit - record.used),
    window: record.day,
    period: 'daily',
  };
}

export async function consumeWebSearchUsage(key, limit = 15) {
  await ensureLoaded();
  const record = getCounterRecord(key);
  if (record.used >= limit) {
    return {
      allowed: false,
      ...(await getWebSearchUsage(key, limit)),
    };
  }
  record.set(record.used + 1);
  await saveState();
  return {
    allowed: true,
    ...(await getWebSearchUsage(key, limit)),
  };
}