From 3c448d4e36e1b1ddb76dc4d6892034766466ba12 Mon Sep 17 00:00:00 2001 From: hemanth5055 Date: Sun, 12 Oct 2025 15:56:09 +0530 Subject: [PATCH 1/2] Added language detection and KV-based usage analytics --- backend/src/index.ts | 71 +++++++++++++++++++++++++++++++++--------- backend/wrangler.jsonc | 6 +++- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index ce40246..1f7a703 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -2,6 +2,7 @@ import { GoogleGenerativeAI } from '@google/generative-ai'; export interface Env { RATE_LIMIT: KVNamespace; + LANG_TRANSLATION_ANALYTICS: KVNamespace; GEMINI_API_KEY: string; } @@ -15,7 +16,7 @@ const MAX_REQUESTS_ALLOWED = 10; const DURATION = 60_000; async function checkRateLimit(ip: string, env: Env) { - const key = `ip_key:${ip}`; + const key = `ip_key:${ip}`.toLowerCase(); const now = Date.now(); let value = await env.RATE_LIMIT.get(key); let data = { count: 0, time: now }; @@ -38,7 +39,25 @@ async function checkRateLimit(ip: string, env: Env) { return data.count <= MAX_REQUESTS_ALLOWED; } -async function handleTranslate(request: Request, model: ReturnType) { + +async function updateAnalytics(source: string, dest: string, env: Env) { + const key = `${source}-${dest}`; + let value = await env.LANG_TRANSLATION_ANALYTICS.get(key); + + let data = { count: 0 }; + if (value) { + try { + data = JSON.parse(value); + } catch { + data = { count: 0 }; + } + } + + data.count += 1; // increment usage count + + await env.LANG_TRANSLATION_ANALYTICS.put(key, JSON.stringify(data)); +} +async function handleTranslate(request: Request, model: ReturnType, env: Env) { const { code, targetLanguage } = await request.json<{ code: string; targetLanguage: string }>(); if (!code || !targetLanguage) { @@ -47,7 +66,7 @@ async function handleTranslate(request: Request, model: ReturnType = {}; + for (const key of list.keys) { + const val = await env.LANG_TRANSLATION_ANALYTICS.get(key.name); + stats[key.name] = JSON.parse(val || '{}'); + } + return new Response(JSON.stringify(stats, null, 2), { + headers: { ...corsHeaders, 'Content-Type': 'application/json' }, + }); + } - if(path==="/test-rate-limit"){ - return new Response(JSON.stringify("Proceed !")) + if (path === '/test-rate-limit') { + return new Response(JSON.stringify('Proceed !')); } if (path === '/' || path === '/v1/translate') { - return await handleTranslate(request, model); + return await handleTranslate(request, model, env); } if (path === '/v1/explain') { @@ -138,3 +168,14 @@ export default { } }, }; + +async function detectLanguage(code: string, model: ReturnType) { + const prompt = `Identify the programming language of the following code. +Only respond with the exact language name (e.g., "python", "javascript", "c++", "java", etc.) without any extra text or punctuation. + +Code: +${code}`; + + const result = await model.generateContent(prompt); + return result.response.text().trim(); +} diff --git a/backend/wrangler.jsonc b/backend/wrangler.jsonc index aa2104c..0ef46ed 100644 --- a/backend/wrangler.jsonc +++ b/backend/wrangler.jsonc @@ -13,7 +13,11 @@ "kv_namespaces": [ { "binding": "RATE_LIMIT", - "id": "" + "id": "", + } + ,{ + "binding": "LANG_TRANSLATION_ANALYTICS", + "id":"" } ] From c8bd2f4a23f780866ecc18972c808f5c2c71a972 Mon Sep 17 00:00:00 2001 From: hemanth5055 Date: Tue, 14 Oct 2025 14:07:54 +0530 Subject: [PATCH 2/2] fix issues according to copilot review --- backend/src/index.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index 1f7a703..0dce003 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -41,7 +41,9 @@ async function checkRateLimit(ip: string, env: Env) { } async function updateAnalytics(source: string, dest: string, env: Env) { - const key = `${source}-${dest}`; + const normalizedSource = source.trim().toLowerCase(); + const normalizedDest = dest.trim().toLowerCase(); + const key = `${normalizedSource}-${normalizedDest}`; let value = await env.LANG_TRANSLATION_ANALYTICS.get(key); let data = { count: 0 }; @@ -78,7 +80,7 @@ ${code}`; const result = await model.generateContent(prompt); const translatedCode = result.response.text(); await updateAnalytics(sourceLanguage, targetLanguage, env); - return new Response(JSON.stringify({ translation: translatedCode, sourceLanguage }), { + return new Response(JSON.stringify({ translation: translatedCode}), { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); @@ -137,7 +139,12 @@ export default { const stats: Record = {}; for (const key of list.keys) { const val = await env.LANG_TRANSLATION_ANALYTICS.get(key.name); - stats[key.name] = JSON.parse(val || '{}'); + try { + stats[key.name] = JSON.parse(val || '{}'); + } catch (e) { + console.error(`Failed to parse analytics value for key "${key.name}":`, e); + stats[key.name] = {}; + } } return new Response(JSON.stringify(stats, null, 2), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, @@ -177,5 +184,5 @@ Code: ${code}`; const result = await model.generateContent(prompt); - return result.response.text().trim(); + return result.response.text().trim().toLowerCase(); }