import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'; import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts'; const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app']; function getCorsHeaders(origin?: string | null): Record { const allowedOrigin = origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0]; return { 'Access-Control-Allow-Origin': allowedOrigin, 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-supabase-client-platform', 'Access-Control-Allow-Methods': 'POST, OPTIONS', }; } interface TelegramUser { id: number; first_name: string; last_name?: string; username?: string; } function validateInitData(initData: string, botToken: string): TelegramUser | null { try { const params = new URLSearchParams(initData); const hash = params.get('hash'); if (!hash) return null; params.delete('hash'); const sortedParams = Array.from(params.entries()) .sort(([a], [b]) => a.localeCompare(b)) .map(([key, value]) => `${key}=${value}`) .join('\n'); const secretKey = createHmac('sha256', 'WebAppData').update(botToken).digest(); const calculatedHash = createHmac('sha256', secretKey).update(sortedParams).digest('hex'); if (calculatedHash !== hash) return null; const authDate = parseInt(params.get('auth_date') || '0'); const now = Math.floor(Date.now() / 1000); if (now - authDate > 86400) return null; const userStr = params.get('user'); if (!userStr) return null; return JSON.parse(userStr) as TelegramUser; } catch { return null; } } function generateDepositCode(): string { const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; let result = 'PEZ-'; for (let i = 0; i < 8; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } serve(async (req) => { const origin = req.headers.get('origin'); const corsHeaders = getCorsHeaders(origin); if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }); } try { const body = await req.json(); const { initData } = body; if (!initData) { return new Response(JSON.stringify({ error: 'Missing initData' }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } const supabaseUrl = Deno.env.get('SUPABASE_URL')!; const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; const botTokens: string[] = []; const _mainToken = Deno.env.get('TELEGRAM_BOT_TOKEN'); const _krdToken = Deno.env.get('TELEGRAM_BOT_TOKEN_KRD'); if (_mainToken) botTokens.push(_mainToken); if (_krdToken) botTokens.push(_krdToken); if (botTokens.length === 0) { return new Response(JSON.stringify({ error: 'Server configuration error' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } let telegramUser: TelegramUser | null = null; for (const bt of botTokens) { telegramUser = validateInitData(initData, bt); if (telegramUser) break; } if (!telegramUser) { return new Response(JSON.stringify({ error: 'Invalid Telegram data' }), { status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } const supabase = createClient(supabaseUrl, supabaseServiceKey, { auth: { autoRefreshToken: false, persistSession: false }, }); // Get or create user let userId: string; const { data: existingUser } = await supabase .from('tg_users') .select('id') .eq('telegram_id', telegramUser.id) .single(); if (existingUser) { userId = existingUser.id; } else { const { data: newUser, error: createError } = await supabase .from('tg_users') .insert({ telegram_id: telegramUser.id, username: telegramUser.username || null, first_name: telegramUser.first_name, last_name: telegramUser.last_name || null, }) .select('id') .single(); if (createError || !newUser) { return new Response(JSON.stringify({ error: 'Failed to create user' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } userId = newUser.id; } // Get or create deposit code const { data: existingCode } = await supabase .from('tg_user_deposit_codes') .select('code') .eq('user_id', userId) .single(); if (existingCode) { return new Response(JSON.stringify({ code: existingCode.code }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } // Create new code const newCode = generateDepositCode(); const { error: insertError } = await supabase .from('tg_user_deposit_codes') .insert({ user_id: userId, code: newCode }); if (insertError) { return new Response(JSON.stringify({ error: 'Failed to create deposit code' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } return new Response(JSON.stringify({ code: newCode }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } catch { return new Response(JSON.stringify({ error: 'Internal server error' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } });