chat-dev / server /webSearchUsageStore.js
incognitolm
More things - 2
cac3e38
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)),
};
}