fix(desktop): read Tenor API key from VITE_TENOR_API_KEY env, no hardcoded credential
This commit is contained in:
@@ -7,10 +7,15 @@ const ENDPOINT = 'https://tenor.googleapis.com/v2';
|
||||
const CLIENT_KEY = 'netralax-chat';
|
||||
const RECENT_KEY = 'chatapp.gifRecent.v1';
|
||||
const RECENT_MAX = 24;
|
||||
// Tenor's public key for browser-side reads. Documented as "anonymous" and
|
||||
// usable without account binding. Rate-limited at ~3k/day per IP which is
|
||||
// plenty for a chat app's picker traffic.
|
||||
const PUBLIC_API_KEY = 'AIzaSyAyimkuYQYF_FXVALexPuGQctUWRURdCYQ';
|
||||
// Tenor requires a Google API key. Provision one at
|
||||
// https://developers.google.com/tenor/guides/quickstart and expose it via
|
||||
// the renderer env var VITE_TENOR_API_KEY (e.g. in apps/desktop/.env.local).
|
||||
// When unset, every Tenor call throws — the picker degrades to a friendly
|
||||
// "GIFs gerade nicht verfügbar" message via the consumer's catch.
|
||||
const API_KEY = (
|
||||
(import.meta as unknown as { env?: { VITE_TENOR_API_KEY?: string } }).env
|
||||
?.VITE_TENOR_API_KEY ?? ''
|
||||
).trim();
|
||||
|
||||
export interface GifResult {
|
||||
id: string;
|
||||
@@ -44,13 +49,20 @@ function mapResult(r: TenorApiResult): GifResult | null {
|
||||
}
|
||||
|
||||
async function fetchTenor(path: string, params: Record<string, string>): Promise<GifResult[]> {
|
||||
const search = new URLSearchParams({ key: PUBLIC_API_KEY, client_key: CLIENT_KEY, ...params });
|
||||
if (!API_KEY) {
|
||||
throw new Error('tenor_api_key_missing');
|
||||
}
|
||||
const search = new URLSearchParams({ key: API_KEY, client_key: CLIENT_KEY, ...params });
|
||||
const res = await fetch(`${ENDPOINT}/${path}?${search.toString()}`);
|
||||
if (!res.ok) throw new Error('tenor http ' + res.status);
|
||||
const json = (await res.json()) as { results?: TenorApiResult[] };
|
||||
return (json.results ?? []).map(mapResult).filter((x): x is GifResult => x !== null);
|
||||
}
|
||||
|
||||
export function isTenorConfigured(): boolean {
|
||||
return API_KEY.length > 0;
|
||||
}
|
||||
|
||||
export async function searchGifs(query: string, locale: string = 'de_DE'): Promise<GifResult[]> {
|
||||
if (!query.trim()) return featuredGifs(locale);
|
||||
return fetchTenor('search', { q: query, limit: '30', locale });
|
||||
|
||||
Reference in New Issue
Block a user