1class m{apiEndpoints={"user.login":"https://users-637480833683.europe-west1.run.app/login/google","url.shorten":"https://shortcode-api.shortify.pro/create"};EndpointUserLogin(){return this.apiEndpoints["user.login"]}ShortenUrlEndpoint(){return this.apiEndpoints["url.shorten"]}SetShortCodeEndpoint(e){return`${new URL(this.apiEndpoints["url.shorten"]).origin}/set/sortcode/${encodeURIComponent(e)}`}}const y=new TextEncoder,w=new TextDecoder;function h(s){return btoa(String.fromCharCode(...new Uint8Array(s)))}function l(s){return Uint8Array.from(atob(s),e=>e.charCodeAt(0))}async function C(s){return crypto.subtle.importKey("raw",y.encode(s),"PBKDF2",!1,["deriveKey"])}async function g(s,e){const t=await C(s);return crypto.subtle.deriveKey({name:"PBKDF2",salt:e,iterations:15e4,hash:"SHA-256"},t,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function u(s,e){const t=crypto.getRandomValues(new Uint8Array(16)),o=await g(s,t),n=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:n},o,y.encode(e));return`${h(t)}.${h(n)}.${h(i)}`}async function k(s,e){const[t,o,n]=e.split("."),i=l(t),a=l(o),c=l(n),r=await g(s,i),d=await crypto.subtle.decrypt({name:"AES-GCM",iv:a},r,c);return w.decode(d)}function E(s,e,{maxAge:t=900,exp:o,skew:n=30,path:i="/",sameSite:a="Lax",secure:c=!0}={}){if(typeof o=="number"){const f=Math.floor(Date.now()/1e3),S=o-f-n;t=Math.max(0,S)}if(!(t>0)){document.cookie=`${encodeURIComponent(s)}=; Max-Age=0; Path=${i}; SameSite=${a}`;return}const r=[`${encodeURIComponent(s)}=${encodeURIComponent(e)}`,`Max-Age=${Math.floor(t)}`,`Path=${i}`,`SameSite=${a}`];c&&location.protocol==="https:"&&r.push("Secure");const d=new Date(Date.now()+Math.floor(t)*1e3).toUTCString();r.push(`Expires=${d}`),document.cookie=r.join("; ")}function p(s){const e=document.cookie.match(new RegExp("(?:^|; )"+encodeURIComponent(s)+"=([^;]*)"));return e?decodeURIComponent(e[1]):null}function U(s,e="/"){document.cookie=`${encodeURIComponent(s)}=; Max-Age=0; Path=${e}; SameSite=Lax`}class x{conf;session;ready;shortCodeToken;canEditShortCode;constructor(){this.conf=new m,this.session={},this.shortCodeToken="",this.canEditShortCode=!1,this.ready=this.loadSession()}async Login(e){const t=await fetch(this.conf.EndpointUserLogin(),{method:"POST",body:e});if(!t.ok){console.error("Login Error:",await t.text());return}const o=this.decodeJwt(await t.text());if(o["user.id"]){this.session={},this.session.id=o.id,this.session["user.id"]=o["user.id"],this.session["user.name"]=o["user.name"],this.session["user.email"]=o["user.email"],this.session["logins.total"]=o["logins.total"],this.session["logins.last"]=o["logins.last"];const n=await u(o.id,JSON.stringify(this.session));localStorage.setItem("session",n),console.log("exp seconds: "+o.exp),E("sessionKey",o.id,{exp:Number(o.exp)}),console.log("session id: "+this.session.id)}}IsLoggedIn(){return!!(this.session&&this.session.id&&this.session.id.length>0)}LogOut(){console.log("invoking logout"),this.session={},localStorage.clear(),U("sessionKey")}UserName(){return this.session&&this.session["user.name"]?this.session["user.name"]:""}async Get(e,t){if(this.session&&this.ready)return this.session?.[e]?.[t]}async Set(e,t,o){this.session&&(this.session[e]??={},this.session[e][t]=o,this.storeSession())}async ShortenUrl(e){const t=await fetch(this.conf.ShortenUrlEndpoint(),{method:"POST",body:JSON.stringify({url:e})});if(!t.ok){let i=await t.text();throw{code:t.status,message:i}}const o=await t.text();this.shortCodeToken=o;const n=this.decodeJwt(o);return this.canEditShortCode=this.isOwnerToken(n),console.log("decoded:",JSON.stringify(n)),n.url??""}async SetShortCode(e){if(!this.shortCodeToken)throw{code:401,message:"missing shortcode owner token"};const t=await fetch(this.conf.SetShortCodeEndpoint(e),{method:"POST",body:this.shortCodeToken});if(!t.ok){let i=await t.text();throw{code:t.status,message:i}}const o=await t.text();this.shortCodeToken=o;const n=this.decodeJwt(o);return this.canEditShortCode=this.isOwnerToken(n),console.log("decoded:",JSON.stringify(n)),n.url??""}CanEditShortCode(){return this.canEditShortCode}isOwnerToken(e){return e?.["is.creator"]===!0||e?.["is.creator"]==="true"}decodeJwt(e){try{const o=e.split(".")[1].replace(/-/g,"+").replace(/_/g,"/"),n=decodeURIComponent(atob(o).split("").map(i=>"%"+("00"+i.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(n)}catch(t){return console.error("Invalid JWT:",t),null}}async storeSession(){const e=p("sessionKey");if(e)try{localStorage.setItem("session",await u(e,JSON.stringify(this.session)))}catch(t){console.error("could not store session: ",t)}}async loadSession(){console.log("loading session");const e=localStorage.getItem("session"),t=p("sessionKey");if(e&&t){console.log("session found");try{const o=await k(t,e);this.session=JSON.parse(o),console.log("user name:",this.session["user.name"])}catch(o){console.error("Decrypt failed:",o),this.session={}}}}}const T=new x;export{T as A};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.