package telegramloginhttp import ( "crypto/sha256" "encoding/base64" "net/http" ) // telegramLoginJavaScript intentionally follows the public Telegram Login // SDK contract (programmatic API, data-* auto-init, popup auth_result events, // and the Mini App oauth_* bridge). It derives the provider from its own // script origin so the same file works on a self-hosted issuer. const telegramLoginJavaScript = `(function(global){ 'use strict'; var current=document.currentScript; if(!current){throw new Error('Telegram Login SDK must be loaded by a script element');} var provider=new URL(current.src,document.baseURI).origin; var saved=null,active=null,inApp=false,inAppPending=false; function callback(cb,value){if(typeof cb==='function'){try{cb(value);}catch(error){setTimeout(function(){throw error;},0);}}} function decode(token){try{var part=token.split('.')[1].replace(/-/g,'+').replace(/_/g,'/');while(part.length%4){part+='=';}return JSON.parse(decodeURIComponent(Array.from(atob(part),function(c){return '%'+c.charCodeAt(0).toString(16).padStart(2,'0');}).join('')));}catch(_){return null;}} function build(data){if(data&&data.error){return {error:String(data.error)};}var token=data&&data.result;if(typeof token!=='string'||!token){return {error:'missing id_token'};}var user=decode(token);return user?{id_token:token,user:user}:{error:'malformed id_token'};} function normalize(options){ if(!options||!/^[0-9]{1,64}$/.test(String(options.client_id||''))){throw new Error('Telegram.Login client_id is required');} var scopes=['openid'],input=options.scope; if(input===undefined||input===null||input===''){scopes.push('profile');input=options.request_access||[];} if(typeof input==='string'){input=input.trim()?input.trim().split(/\s+/):[];} if(!Array.isArray(input)){throw new Error('Telegram.Login scope must be an array or string');} var allowed={profile:'profile',phone:'phone',write:'telegram:bot_access','telegram:bot_access':'telegram:bot_access'}; input.forEach(function(value){var mapped=allowed[value];if(!mapped){throw new Error('Telegram.Login scope is invalid');}if(scopes.indexOf(mapped)<0){scopes.push(mapped);}}); return {client_id:String(options.client_id),scope:scopes.join(' '),nonce:String(options.nonce||'').slice(0,1024),lang:String(options.lang||'').slice(0,16)}; } function randomURL(bytes){var data=new Uint8Array(bytes);crypto.getRandomValues(data);var raw='';data.forEach(function(value){raw+=String.fromCharCode(value);});return btoa(raw).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'');} function finish(flow,result){if(active!==flow){return;}active=null;if(flow.timer){clearInterval(flow.timer);}if(flow.listener){global.removeEventListener('message',flow.listener);}callback(flow.callback,result);} function sendEvent(type,data){if(global.TelegramWebviewProxy&&typeof global.TelegramWebviewProxy.postEvent==='function'){global.TelegramWebviewProxy.postEvent(type,JSON.stringify(data||{}));}} async function receiveEvent(type,data){ if(type==='oauth_supported'){inApp=true;return;} if(type==='oauth_result_failed'){if(active){finish(active,{error:'access_denied'});}return;} if(type!=='oauth_result_confirmed'||!active||!data||!data.result_url){return;} try{var resultURL=new URL(data.result_url);if(resultURL.origin!==provider||resultURL.pathname!=='/inapp'){throw new Error('invalid in-app result URL');}var token=resultURL.searchParams.get('token');if(!token){throw new Error('missing in-app token');} var response=await fetch(provider+'/inapp?code='+encodeURIComponent(token),{credentials:'omit',cache:'no-store'}),result=await response.json(); if(!response.ok){throw new Error(result.error||'in-app exchange failed');}finish(active,build(result)); }catch(error){finish(active,{error:error.message||'in_app_failed'});} } function begin(options,cb,isNormalized){ var normalized;try{normalized=isNormalized?options:normalize(options);}catch(error){callback(cb,{error:error.message});return null;} if(active){callback(cb,{error:'login_in_progress'});return null;} var flow={popup:null,callback:cb,listener:null,timer:null};active=flow; if(inApp){ if(inAppPending){finish(flow,{error:'login_in_progress'});return null;}inAppPending=true; var inAppParams=new URLSearchParams({scope:normalized.scope,origin:global.location.origin,client_id:normalized.client_id,response_type:'id_token'}); fetch(provider+'/inapp?'+inAppParams.toString(),{credentials:'omit',cache:'no-store'}).then(function(response){return response.json().then(function(body){if(!response.ok){throw new Error(body.error||'in-app request failed');}return body;});}).then(function(body){if(!body.url){throw new Error('missing OAuth deep link');}sendEvent('oauth_request',{url:body.url});}).catch(function(error){finish(flow,{error:error.message||'in_app_failed'});}).finally(function(){setTimeout(function(){inAppPending=false;},600);}); return null; } var popup=global.open('about:blank','telegram-login-'+randomURL(8),'popup,width=550,height=650,resizable=yes,scrollbars=yes'); if(!popup){finish(flow,{error:'popup_blocked'});return null;}flow.popup=popup; flow.listener=function(event){if(event.origin!==provider||event.source!==popup){return;}var data=event.data;try{if(typeof data==='string'){data=JSON.parse(data);}}catch(_){return;}if(!data||data.event!=='auth_result'){return;}finish(flow,build(data));}; global.addEventListener('message',flow.listener);flow.timer=setInterval(function(){if(popup.closed){finish(flow,{error:'popup_closed'});}},500); try{var params=new URLSearchParams({client_id:normalized.client_id,redirect_uri:global.location.origin+global.location.pathname,response_type:'post_message',scope:normalized.scope});if(normalized.nonce){params.set('nonce',normalized.nonce);}if(normalized.lang){params.set('lang',normalized.lang);}popup.location.replace(provider+'/auth?'+params.toString());} catch(error){try{popup.close();}catch(_){}finish(flow,{error:error.message||'login_failed'});} return popup; } var api={ init:function(options,cb){saved={options:normalize(options),callback:cb};return api;}, open:function(cb){if(!saved){callback(cb,{error:'not_initialized'});return null;}return begin(saved.options,cb||saved.callback,true);}, auth:function(options,cb){return begin(options,cb,false);}, close:function(){if(active&&active.popup){try{active.popup.close();}catch(_){}}if(active){finish(active,{error:'popup_closed'});}} }; global.Telegram=global.Telegram||{};global.Telegram.Login=api; global.Telegram.WebView=global.Telegram.WebView||{};global.Telegram.WebView.receiveEvent=receiveEvent; global.Telegram.TelegramGameProxy=global.Telegram.TelegramGameProxy||{};global.Telegram.TelegramGameProxy.receiveEvent=receiveEvent; if(global.TelegramWebviewProxy){sendEvent('oauth_request',{});} document.addEventListener('click',function(event){var node=event.target;while(node&&node!==document){if(node.classList&&node.classList.contains('tg-auth-button')){api.open();return;}node=node.parentNode;}}); function resolveCallback(source){var match=/^([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*\(\s*data\s*\)\s*;?$/.exec(source||'');if(!match){return null;}return function(data){var target=global,parts=match[1].split('.');for(var i=0;i