diff --git a/static/tba.mjs b/static/tba.mjs index bbd77a8..3efdc30 100644 --- a/static/tba.mjs +++ b/static/tba.mjs @@ -1,150 +1,62 @@ -/** @param {Response} response */ -async function validateResponse(response){ - if(!response.ok){ - throw new Error(response.status+' '+response.url+' '+await response.text()) - } - return response -} +import * as TwitchAuth from './TwitchAuth.mjs' +/** @type {import('./TwitchAuth.mjs').TwitchToken} */ +let token=null; export function request_auth(client_id,scope,redirect_uri=location.origin+location.pathname){ - const url=new URL('https://id.twitch.tv/oauth2/authorize') - url.search=new URLSearchParams({ - client_id:client_id, - response_type:'code', - scope:scope - }) - const dialog=document.createElement('dialog') - dialog.innerHTML='Redirecting you to Twitch for authorization
' - dialog.innerHTML+='If you see this multiple times, please report it as a bug
' - const okButton=document.createElement('button') - okButton.innerHTML='OK' - okButton.onclick=()=>location.assign(url.href+'&redirect_uri='+redirect_uri) - dialog.appendChild(okButton) - const cancelButton=document.createElement('button') - cancelButton.innerHTML='Cancel' - cancelButton.onclick=()=>dialog.close() - dialog.appendChild(cancelButton) - document.body.appendChild(dialog) - dialog.showModal() - //if(window.confirm((document.title||location.origin+location.pathname)+' redirecting you to twitch for authorization')){ - // location.assign(url.href+'&redirect_uri='+redirect_uri) - //} + return TwitchAuth.requestAuthCode(client_id,scope.split(' ')) } export function get_url_params(){ return Object.fromEntries(new URLSearchParams(location.search)) } -export function fetch_tokens(client_id,code,redirect_uri=location.origin+location.path){ - const url=new URL('/oauth2/token',import.meta.url) - const body=new URLSearchParams({ - client_id:client_id, - code:code, - grant_type:'authorization_code', - redirect_uri:redirect_uri - }).toString() - return fetch(url.href,{ - method:'POST', - headers:{'Content-Type':'application/x-www-form-urlencoded'}, - body:body - }) - .then(validateResponse) - .then(response=>response.json()) +export async function fetch_tokens(client_id,code,redirect_uri=location.origin+location.path){ + client_id=client_id + token=await TwitchAuth.exchangeCode(client_id,code) + token.client_id=client_id + return token } export function get_headers(tokens){ return { - 'Authorization':'Bearer '+tokens.access_token, - 'Client-ID':tokens.client_id + 'Authorization':'Bearer '+token.access_token, + 'Client-ID':token.client_id } } -export function validate_tokens(tokens){ - const url=new URL('https://id.twitch.tv/oauth2/validate')//,import.meta.url) - return fetch(url,{headers:{ - 'Authorization':'OAuth '+tokens.access_token - }}).then(validateResponse) - .then(response=>response.json()) - .then(validation=>{ - if('message' in validation){ - throw new Error(validation.message) - } - Object.assign(tokens,validation) - delete tokens.scope - return tokens - }) +export async function validate_tokens(tokens){ + const validation=await TwitchAuth.validateToken(tokens.auth_token) + Object.assign(tokens,validation) + tokens.scopes=validation.scope + token=tokens + return token } export function set_local_tokens(client_id,tokens){ - localStorage.setItem(client_id,JSON.stringify(tokens)) - return tokens + token=tokens + return token } export function get_local_tokens(client_id){ - return JSON.parse(localStorage.getItem(client_id)) + return token } -export function refresh_tokens(client_id,refresh_token){ - const url=new URL('/oauth2/token',import.meta.url) - const body=new URLSearchParams({ - client_id:client_id, - grant_type:'refresh_token', - refresh_token:refresh_token - }).toString() - return fetch(url.href,{ - method:'POST', - headers:{'Content-Type':'application/x-www-form-urlencoded'}, - body:body - }) - .then(validateResponse) - .then(response=>response.json()) +export async function refresh_tokens(client_id,refresh_token){ + token=await TwitchAuth.refreshToken(client_id,refresh_token) + return token } export function set_refresh_timeout(client_id,tokens){ return setTimeout(()=>{ - get_tokens(client_id) + TwitchAuth.refreshToken(client_id,tokens.refresh_token) .then(new_tokens=>Object.assign(tokens,new_tokens)) - },tokens.expires_in*1000) + },tokens.expires_in*999) } export async function get_tokens(client_id,scope=null,redirect_uri=location.origin+location.pathname,auth_return=false){ - let tokens=get_local_tokens(client_id)||get_url_params() - if('code' in tokens){ - tokens=await fetch_tokens(client_id,tokens.code,redirect_uri) - .catch((error)=>console.warn(error)) - } - if(!tokens){ - tokens={refresh_token:undefined} - } - return refresh_tokens(client_id,tokens.refresh_token) - .then(validate_tokens) - .then(tokens=>{ - tokens.auth_headers=get_headers(tokens) - set_refresh_timeout(client_id,tokens) - return set_local_tokens(client_id,tokens) - }) - .catch(async (error)=>{ - if(error.message==="Failed to fetch"){ - await new Promise(function(resolve,reject){ - setTimeout(resolve,1000) - }) - return get_tokens(client_id,scope,redirect_uri,auth_return) - } - if(scope){ - request_auth(client_id,scope,redirect_uri) - }else{ - const dialog=document.createElement('dialog') - dialog.innerHTML=(document.title||location.origin+location.pathname)+' has been logged out of your twitch account
' - const okButton=document.createElement('button') - okButton.innerHTML='OK' - okButton.onclick=()=>dialog.close() - dialog.appendChild(okButton) - document.body.appendChild(dialog) - dialog.showModal() - localStorage.clear(client_id) - } - throw error - }) + token=await TwitchAuth.getUserToken(client_id,scope.split(' ')).then(validate_tokens) + set_refresh_timeout(client_id,token) + return token } export default get_tokens \ No newline at end of file