telegram-media-bot/src/telegram/keyboards.ts
2026-03-01 09:24:35 +00:00

61 lines
1.7 KiB
TypeScript

import { InlineKeyboard } from 'grammy';
import { payloadClient, type TenantDoc } from '../payload/client.js';
import { createLogger } from '../utils/logger.js';
const log = createLogger('Keyboards');
// Tenant cache with 5-minute TTL
let tenantCache: TenantDoc[] | null = null;
let cacheExpiresAt = 0;
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
async function loadTenants(): Promise<TenantDoc[]> {
const now = Date.now();
// Return valid cache
if (tenantCache && cacheExpiresAt > now) {
return tenantCache;
}
try {
const tenants = await payloadClient.listTenants();
tenantCache = tenants;
cacheExpiresAt = now + CACHE_TTL;
log.info(`Loaded ${tenants.length} tenants from API`);
return tenants;
} catch (error) {
// Stale cache fallback: if API fails but we have old data, return it
if (tenantCache) {
log.warn('API failed, returning stale tenant cache', error);
return tenantCache;
}
log.error('Failed to load tenants and no cache available', error);
throw error;
}
}
export async function buildTenantKeyboard(): Promise<InlineKeyboard> {
const tenants = await loadTenants();
const keyboard = new InlineKeyboard();
for (let i = 0; i < tenants.length; i++) {
const tenant = tenants[i];
keyboard.text(tenant.name, `tenant:${tenant.id}`);
// 2 buttons per row
if (i % 2 === 1 && i < tenants.length - 1) {
keyboard.row();
}
}
return keyboard;
}
export async function getTenantName(tenantId: number): Promise<string> {
try {
const tenants = await loadTenants();
const tenant = tenants.find((t) => t.id === tenantId);
return tenant?.name ?? `Tenant ${tenantId}`;
} catch {
return `Tenant ${tenantId}`;
}
}