@@ -2,6 +2,7 @@ import { GoogleGenerativeAI } from '@google/generative-ai';
22
33export interface Env {
44 RATE_LIMIT : KVNamespace ;
5+ LANG_TRANSLATION_ANALYTICS : KVNamespace ;
56 GEMINI_API_KEY : string ;
67}
78
@@ -15,7 +16,7 @@ const MAX_REQUESTS_ALLOWED = 10;
1516const DURATION = 60_000 ;
1617
1718async function checkRateLimit ( ip : string , env : Env ) {
18- const key = `ip_key:${ ip } ` ;
19+ const key = `ip_key:${ ip } ` . toLowerCase ( ) ;
1920 const now = Date . now ( ) ;
2021 let value = await env . RATE_LIMIT . get ( key ) ;
2122 let data = { count : 0 , time : now } ;
@@ -38,7 +39,25 @@ async function checkRateLimit(ip: string, env: Env) {
3839
3940 return data . count <= MAX_REQUESTS_ALLOWED ;
4041}
41- async function handleTranslate ( request : Request , model : ReturnType < GoogleGenerativeAI [ 'getGenerativeModel' ] > ) {
42+
43+ async function updateAnalytics ( source : string , dest : string , env : Env ) {
44+ const key = `${ source } -${ dest } ` ;
45+ let value = await env . LANG_TRANSLATION_ANALYTICS . get ( key ) ;
46+
47+ let data = { count : 0 } ;
48+ if ( value ) {
49+ try {
50+ data = JSON . parse ( value ) ;
51+ } catch {
52+ data = { count : 0 } ;
53+ }
54+ }
55+
56+ data . count += 1 ; // increment usage count
57+
58+ await env . LANG_TRANSLATION_ANALYTICS . put ( key , JSON . stringify ( data ) ) ;
59+ }
60+ async function handleTranslate ( request : Request , model : ReturnType < GoogleGenerativeAI [ 'getGenerativeModel' ] > , env : Env ) {
4261 const { code, targetLanguage } = await request . json < { code : string ; targetLanguage : string } > ( ) ;
4362
4463 if ( ! code || ! targetLanguage ) {
@@ -47,7 +66,7 @@ async function handleTranslate(request: Request, model: ReturnType<GoogleGenerat
4766 headers : { ...corsHeaders , 'Content-Type' : 'application/json' } ,
4867 } ) ;
4968 }
50-
69+ const sourceLanguage = await detectLanguage ( code , model ) ;
5170 const prompt = `Translate the following code snippet to ${ targetLanguage } .
5271Do not add any explanation, commentary, or markdown formatting like \`\`\` around the code.
5372**IMPORTANT: Preserve all original comments and their exact placement in the translated code. Do not add extra spaces in between.**
@@ -58,8 +77,8 @@ ${code}`;
5877
5978 const result = await model . generateContent ( prompt ) ;
6079 const translatedCode = result . response . text ( ) ;
61-
62- return new Response ( JSON . stringify ( { translation : translatedCode } ) , {
80+ await updateAnalytics ( sourceLanguage , targetLanguage , env ) ;
81+ return new Response ( JSON . stringify ( { translation : translatedCode , sourceLanguage } ) , {
6382 status : 200 ,
6483 headers : { ...corsHeaders , 'Content-Type' : 'application/json' } ,
6584 } ) ;
@@ -102,23 +121,34 @@ export default {
102121
103122 try {
104123 const ip = request . headers . get ( 'CF-Connecting-IP' ) || 'unknown' ;
105- const allowed = await checkRateLimit ( ip , env ) ;
106- if ( ! allowed ) {
107- return new Response ( JSON . stringify ( { error : " Too many requests. Try again later." } ) , {
108- status : 429 ,
109- headers : { ...corsHeaders , 'Content-Type' : 'application/json' } ,
110- } ) ;
111- }
124+ const allowed = await checkRateLimit ( ip , env ) ;
125+ if ( ! allowed ) {
126+ return new Response ( JSON . stringify ( { error : ' Too many requests. Try again later.' } ) , {
127+ status : 429 ,
128+ headers : { ...corsHeaders , 'Content-Type' : 'application/json' } ,
129+ } ) ;
130+ }
112131 const url = new URL ( request . url ) ;
113132 const path = url . pathname ;
114133 const genAI = new GoogleGenerativeAI ( env . GEMINI_API_KEY ) ;
115134 const model = genAI . getGenerativeModel ( { model : 'gemini-2.0-flash' } ) ;
135+ if ( path === '/v1/analytics' ) {
136+ const list = await env . LANG_TRANSLATION_ANALYTICS . list ( ) ;
137+ const stats : Record < string , any > = { } ;
138+ for ( const key of list . keys ) {
139+ const val = await env . LANG_TRANSLATION_ANALYTICS . get ( key . name ) ;
140+ stats [ key . name ] = JSON . parse ( val || '{}' ) ;
141+ }
142+ return new Response ( JSON . stringify ( stats , null , 2 ) , {
143+ headers : { ...corsHeaders , 'Content-Type' : 'application/json' } ,
144+ } ) ;
145+ }
116146
117- if ( path === " /test-rate-limit" ) {
118- return new Response ( JSON . stringify ( " Proceed !" ) )
147+ if ( path === ' /test-rate-limit' ) {
148+ return new Response ( JSON . stringify ( ' Proceed !' ) ) ;
119149 }
120150 if ( path === '/' || path === '/v1/translate' ) {
121- return await handleTranslate ( request , model ) ;
151+ return await handleTranslate ( request , model , env ) ;
122152 }
123153
124154 if ( path === '/v1/explain' ) {
@@ -138,3 +168,14 @@ export default {
138168 }
139169 } ,
140170} ;
171+
172+ async function detectLanguage ( code : string , model : ReturnType < GoogleGenerativeAI [ 'getGenerativeModel' ] > ) {
173+ const prompt = `Identify the programming language of the following code.
174+ Only respond with the exact language name (e.g., "python", "javascript", "c++", "java", etc.) without any extra text or punctuation.
175+
176+ Code:
177+ ${ code } `;
178+
179+ const result = await model . generateContent ( prompt ) ;
180+ return result . response . text ( ) . trim ( ) ;
181+ }
0 commit comments