diff --git a/app/dist/assets/index-CfEoSnmR.js b/app/dist/assets/index-dPPSjzHg.js similarity index 83% rename from app/dist/assets/index-CfEoSnmR.js rename to app/dist/assets/index-dPPSjzHg.js index aecad86..8fe3719 100644 --- a/app/dist/assets/index-CfEoSnmR.js +++ b/app/dist/assets/index-dPPSjzHg.js @@ -1,5 +1,5 @@ var Yt=Object.defineProperty;var Kt=(t,e,n)=>e in t?Yt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var Ve=(t,e,n)=>(Kt(t,typeof e!="symbol"?e+"":e,n),n);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))r(o);new MutationObserver(o=>{for(const l of o)if(l.type==="childList")for(const c of l.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&r(c)}).observe(document,{childList:!0,subtree:!0});function n(o){const l={};return o.integrity&&(l.integrity=o.integrity),o.referrerPolicy&&(l.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?l.credentials="include":o.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function r(o){if(o.ep)return;o.ep=!0;const l=n(o);fetch(o.href,l)}})();function I(){}function Qt(t){return!!t&&(typeof t=="object"||typeof t=="function")&&typeof t.then=="function"}function Ot(t){return t()}function ft(){return Object.create(null)}function re(t){t.forEach(Ot)}function jt(t){return typeof t=="function"}function oe(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}let qe;function en(t,e){return t===e?!0:(qe||(qe=document.createElement("a")),qe.href=e,t===qe.href)}function tn(t){return Object.keys(t).length===0}function Ht(t,...e){if(t==null){for(const r of e)r(void 0);return I}const n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function K(t){let e;return Ht(t,n=>e=n)(),e}function F(t,e,n){t.$$.on_destroy.push(Ht(e,n))}function j(t,e,n){return t.set(n),e}function h(t,e){t.appendChild(e)}function L(t,e,n){t.insertBefore(e,n||null)}function S(t){t.parentNode&&t.parentNode.removeChild(t)}function He(t,e){for(let n=0;nt.removeEventListener(e,n,r)}function _(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function nn(t){return Array.from(t.childNodes)}function ae(t,e){e=""+e,t.data!==e&&(t.data=e)}function be(t,e){t.value=e??""}function pt(t,e,n){for(let r=0;r{const o=t.$$.callbacks[e];if(o){const l=rn(e,n,{cancelable:r});return o.slice().forEach(c=>{c.call(t,l)}),!l.defaultPrevented}return!0}}const Pe=[],z=[];let Re=[];const Ke=[],cn=Promise.resolve();let Qe=!1;function an(){Qe||(Qe=!0,cn.then(ot))}function Je(t){Re.push(t)}function Ie(t){Ke.push(t)}const Ze=new Set;let Ce=0;function ot(){if(Ce!==0)return;const t=Ne;do{try{for(;Cet.indexOf(r)===-1?e.push(r):n.push(r)),n.forEach(r=>r()),Re=e}const Be=new Set;let we;function ve(){we={r:0,c:[],p:we}}function Se(){we.r||re(we.c),we=we.p}function U(t,e){t&&t.i&&(Be.delete(t),t.i(e))}function B(t,e,n,r){if(t&&t.o){if(Be.has(t))return;Be.add(t),we.c.push(()=>{Be.delete(t),r&&(n&&t.d(1),r())}),t.o(e)}else r&&r()}function Ee(t,e){const n=e.token={};function r(o,l,c,i){if(e.token!==n)return;e.resolved=i;let u=e.ctx;c!==void 0&&(u=u.slice(),u[c]=i);const a=o&&(e.current=o)(u);let d=!1;e.block&&(e.blocks?e.blocks.forEach((f,p)=>{p!==l&&f&&(ve(),B(f,1,1,()=>{e.blocks[p]===f&&(e.blocks[p]=null)}),Se())}):e.block.d(1),a.c(),U(a,1),a.m(e.mount(),e.anchor),d=!0),e.block=a,e.blocks&&(e.blocks[l]=a),d&&ot()}if(Qt(t)){const o=Ae();if(t.then(l=>{he(o),r(e.then,1,e.value,l),he(null)},l=>{if(he(o),r(e.catch,2,e.error,l),he(null),!e.hasCatch)throw l}),e.current!==e.pending)return r(e.pending,0),!0}else{if(e.current!==e.then)return r(e.then,1,e.value,t),!0;e.resolved=t}}function lt(t,e,n){const r=e.slice(),{resolved:o}=t;t.current===t.then&&(r[t.value]=o),t.current===t.catch&&(r[t.error]=o),t.block.p(r,n)}function pe(t){return(t==null?void 0:t.length)!==void 0?t:Array.from(t)}function Oe(t,e,n){const r=t.$$.props[e];r!==void 0&&(t.$$.bound[r]=n,n(t.$$.ctx[r]))}function ne(t){t&&t.c()}function ee(t,e,n){const{fragment:r,after_update:o}=t.$$;r&&r.m(e,n),Je(()=>{const l=t.$$.on_mount.map(Ot).filter(jt);t.$$.on_destroy?t.$$.on_destroy.push(...l):re(l),t.$$.on_mount=[]}),o.forEach(Je)}function te(t,e){const n=t.$$;n.fragment!==null&&(dn(n.after_update),re(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function fn(t,e){t.$$.dirty[0]===-1&&(Pe.push(t),an(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{const g=k.length?k[0]:p;return a.ctx&&o(a.ctx[f],a.ctx[f]=g)&&(!a.skip_bound&&a.bound[f]&&a.bound[f](g),d&&fn(t,f)),p}):[],a.update(),d=!0,re(a.before_update),a.fragment=r?r(a.ctx):!1,e.target){if(e.hydrate){const f=nn(e.target);a.fragment&&a.fragment.l(f),f.forEach(S)}else a.fragment&&a.fragment.c();e.intro&&U(t.$$.fragment),ee(t,e.target,e.anchor),ot()}he(u)}class ce{constructor(){Ve(this,"$$");Ve(this,"$$set")}$destroy(){te(this,1),this.$destroy=I}$on(e,n){if(!jt(n))return I;const r=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return r.push(n),()=>{const o=r.indexOf(n);o!==-1&&r.splice(o,1)}}$set(e){this.$$set&&!tn(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}const pn="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(pn);const Te=[];function At(t,e){return{subscribe:W(t,e).subscribe}}function W(t,e=I){let n;const r=new Set;function o(i){if(oe(t,i)&&(t=i,n)){const u=!Te.length;for(const a of r)a[1](),Te.push(a,t);if(u){for(let a=0;a{r.delete(a),r.size===0&&n&&(n(),n=null)}}return{set:o,update:l,subscribe:c}}function Dt(t){if(t.ok)return t.value;throw t.error}var Q=(t=>(t[t.rs3=0]="rs3",t[t.osrs=1]="osrs",t))(Q||{}),ie=(t=>(t[t.osrs=0]="osrs",t[t.runeLite=1]="runeLite",t[t.hdos=2]="hdos",t[t.rs3=3]="rs3",t))(ie||{});const _n={use_dark_theme:!0,flatpak_rich_presence:!1,rs_config_uri:"",runelite_custom_jar:"",runelite_use_custom_jar:!1,selected_account:"",selected_characters:new Map,selected_game_accounts:new Map,selected_game_index:1,selected_client_index:1},Ut=At("https://bolt-internal"),hn=At("1fddee4e-b100-4f4e-b2b0-097f9088f9d2"),ct=W(),Fe=W(""),J=W({..._n}),ye=W(new Map),ge=W(!1),fe=W(),et=W(),Le=W([]),We=W({}),it=W([]),tt=W(""),qt=W(""),Bt=W(""),$t=W(""),Jt=W(""),nt=W(""),st=W(""),Y=W(!1),Ge=W(new Map),Z=W({game:Q.osrs,client:ie.runeLite}),Xe=W(!1);function bn(){se.use_dark_theme==!1&&document.documentElement.classList.remove("dark")}function gn(t,e){e&&t.win.close(),it.update(n=>(n.splice(ut.indexOf(t),1),n))}function Gt(){if(de&&de.win&&!de.win.closed)de.win.focus();else if(de&&de.win&&de.win.closed||de){const t=Ft(),e=wn();kn({origin:atob(V.origin),redirect:atob(V.redirect),authMethod:"",loginType:"",clientid:atob(V.clientid),flow:"launcher",pkceState:t,pkceCodeVerifier:e}).then(n=>{const r=window.open(n,"","width=480,height=720");We.set({state:t,verifier:e,win:r})})}}function mn(){const t=new URLSearchParams(window.location.search);Fe.set(t.get("platform")),tt.set(t.get("rs3_deb_installed_hash")),qt.set(t.get("rs3_exe_installed_hash")),Bt.set(t.get("rs3_app_installed_hash")),$t.set(t.get("osrs_exe_installed_hash")),Jt.set(t.get("osrs_app_installed_hash")),nt.set(t.get("runelite_installed_id")),st.set(t.get("hdos_installed_version"));const e=t.get("plugins");e!==null?(ge.set(!0),fe.set(JSON.parse(e))):ge.set(!1);const n=t.get("credentials");if(n)try{JSON.parse(n).forEach(l=>{ye.update(c=>(c.set(l.sub,l),c))})}catch(o){q(`Couldn't parse credentials file: ${o}`,!1)}const r=t.get("config");if(r)try{const o=JSON.parse(r);J.set(o),J.update(l=>(l.selected_game_accounts?(l.selected_characters=new Map(Object.entries(l.selected_game_accounts)),delete l.selected_game_accounts):l.selected_characters&&(l.selected_characters=new Map(Object.entries(l.selected_characters))),l))}catch(o){q(`Couldn't parse config file: ${o}`,!1)}}async function Xt(t,e,n){return new Promise(r=>{if(t.expiry-Date.now()<3e4){const o=new URLSearchParams({grant_type:"refresh_token",client_id:n,refresh_token:t.refresh_token}),l=new XMLHttpRequest;l.onreadystatechange=()=>{if(l.readyState==4)if(l.status==200){const c=zt(l.response),i=Dt(c);i?(t.access_token=i.access_token,t.expiry=i.expiry,t.id_token=i.id_token,t.login_provider=i.login_provider,t.refresh_token=i.refresh_token,i.session_id&&(t.session_id=i.session_id),t.sub=i.sub,r(null)):r(0)}else r(l.status)},l.onerror=()=>{r(0)},l.open("POST",e,!0),l.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),l.setRequestHeader("Accept","application/json"),l.send(o)}else r(null)})}function zt(t){const e=JSON.parse(t),n=e.id_token.split(".");if(n.length!==3){const l=`Malformed id_token: ${n.length} sections, expected 3`;return q(l,!1),{ok:!1,error:new Error(l)}}const r=JSON.parse(atob(n[0]));if(r.typ!=="JWT"){const l=`Bad id_token header: typ ${r.typ}, expected JWT`;return q(l,!1),{ok:!1,error:new Error(l)}}const o=JSON.parse(atob(n[1]));return{ok:!0,value:{access_token:e.access_token,id_token:e.id_token,refresh_token:e.refresh_token,sub:o.sub,login_provider:o.login_provider||null,expiry:Date.now()+e.expires_in*1e3,session_id:e.session_id}}}async function kn(t){const e=new TextEncoder().encode(t.pkceCodeVerifier),n=await crypto.subtle.digest("SHA-256",e);let r="";const o=new Uint8Array(n);for(let c=0;cMath.round(o*(n-0)/255+0)).map(o=>e[o]).join("")}async function Wt(t,e,n){return new Promise(r=>{const o=new XMLHttpRequest;o.onreadystatechange=()=>{o.readyState==4&&(o.status==200?n.then(l=>{if(typeof l!="number"){const c={id:l.id,userId:l.userId,displayName:l.displayName,suffix:l.suffix,characters:new Map};$(`Successfully added login for ${c.displayName}`),JSON.parse(o.response).forEach(i=>{c.characters.set(i.accountId,{accountId:i.accountId,displayName:i.displayName,userHash:i.userHash})}),Sn(c),r(!0)}else q(`Error getting account info: ${l}`,!1),r(!1)}):(q(`Error: from ${e}: ${o.status}: ${o.response}`,!1),r(!1)))},o.open("GET",e,!0),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Authorization","Bearer ".concat(t.session_id)),o.send()})}async function _t(t,e){return await yn(t,e)}async function yn(t,e){const n=Ft(),r=crypto.randomUUID(),o=atob(V.origin).concat("/oauth2/auth?").concat(new URLSearchParams({id_token_hint:e.id_token,nonce:btoa(r),prompt:"consent",redirect_uri:"http://localhost",response_type:"id_token code",state:n,client_id:K(hn),scope:"openid offline"}).toString()),l=vn(e);return t?(t.location.href=o,it.update(c=>(c.push({state:n,nonce:r,creds:e,win:t,account_info_promise:l}),c)),!1):e.session_id?await Wt(e,atob(V.auth_api).concat("/accounts"),l):(q("Rejecting stored credentials with missing session_id",!1),!1)}function vn(t){return new Promise(e=>{const n=`${atob(V.api)}/users/${t.sub}/displayName`,r=new XMLHttpRequest;r.onreadystatechange=()=>{r.readyState==4&&(r.status==200?e(JSON.parse(r.response)):e(r.status))},r.open("GET",n,!0),r.setRequestHeader("Authorization","Bearer ".concat(t.access_token)),r.send()})}function Sn(t){const e=()=>{Z.update(n=>{n.account=t;const[r]=t.characters.keys();return n.character=t.characters.get(r),ke.size>0&&(n.credentials=ke.get(t.userId)),n})};Ge.update(n=>(n.set(t.userId,t),n)),ze.account&&se.selected_account?t.userId==se.selected_account&&e():ze.account||e(),We.set({})}function Ln(t,e,n){return new Promise(r=>{const o=new XMLHttpRequest;o.open("POST",e,!0),o.onreadystatechange=()=>{o.readyState==4&&r(o.status)},o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),o.send(new URLSearchParams({token:t,client_id:n}))})}async function Me(){const t=new XMLHttpRequest;t.open("POST","/save-credentials",!0),t.setRequestHeader("Content-Type","application/json"),t.onreadystatechange=()=>{t.readyState==4&&$(`Save-credentials status: ${t.responseText.trim()}`)},Z.update(n=>{var r;return n.credentials=ke.get((r=ze.account)==null?void 0:r.userId),n});const e=[];ke.forEach(n=>{e.push(n)}),t.send(JSON.stringify(e))}function xn(t,e,n){Ue();const r=(i,u)=>{const a=new XMLHttpRequest,d={};i&&(d.hash=i),t&&(d.jx_session_id=t),e&&(d.jx_character_id=e),n&&(d.jx_display_name=n),se.rs_plugin_loader&&(d.plugin_loader="1"),se.rs_config_uri?d.config_uri=se.rs_config_uri:d.config_uri=atob(V.default_config_uri),a.open("POST","/launch-rs3-deb?".concat(new URLSearchParams(d).toString()),!0),a.onreadystatechange=()=>{a.readyState==4&&($(`Game launch status: '${a.responseText.trim()}'`),a.status==200&&i&&tt.set(i))},a.send(u)},o=new XMLHttpRequest,l=atob(V.content_url),c=l.concat("dists/trusty/non-free/binary-amd64/Packages");o.open("GET",c,!0),o.onreadystatechange=()=>{if(o.readyState==4&&o.status==200){const i=Object.fromEntries(o.response.split(` -`).map(u=>u.split(": ")));if(!i.Filename||!i.Size){q(`Could not parse package data from URL: ${c}`,!1),r();return}if(i.SHA256!==K(tt)){$("Downloading RS3 client...");const u=new XMLHttpRequest;u.open("GET",l.concat(i.Filename),!0),u.responseType="arraybuffer",u.onprogress=a=>{a.loaded&&Le.update(d=>(d[0].text=`Downloading RS3 client... ${(Math.round(1e3*a.loaded/a.total)/10).toFixed(1)}%`,d))},u.onreadystatechange=()=>{u.readyState==4&&u.status==200&&r(i.SHA256,u.response)},u.onerror=()=>{q(`Error downloading game client: from ${c}: non-http error`,!1),r()},u.send()}else $("Latest client is already installed"),r()}},o.onerror=()=>{q(`Error: from ${c}: non-http error`,!1),r()},o.send()}function Vt(t,e,n,r){Ue();const o=r?"/launch-runelite-jar-configure?":"/launch-runelite-jar?",l=(u,a,d)=>{const f=new XMLHttpRequest,p={};u&&(p.id=u),d&&(p.jar_path=d),t&&(p.jx_session_id=t),e&&(p.jx_character_id=e),n&&(p.jx_display_name=n),se.flatpak_rich_presence&&(p.flatpak_rich_presence=""),f.open(a?"POST":"GET",o.concat(new URLSearchParams(p).toString()),!0),f.onreadystatechange=()=>{f.readyState==4&&($(`Game launch status: '${f.responseText.trim()}'`),f.status==200&&u&&nt.set(u))},f.send(a)};if(se.runelite_use_custom_jar){l(null,null,se.runelite_custom_jar);return}const c=new XMLHttpRequest,i="https://api.github.com/repos/runelite/launcher/releases";c.open("GET",i,!0),c.onreadystatechange=()=>{if(c.readyState==4)if(c.status==200){const u=JSON.parse(c.responseText).map(a=>a.assets).flat().find(a=>a.name.toLowerCase()=="runelite.jar");if(u.id!=K(nt)){$("Downloading RuneLite...");const a=new XMLHttpRequest;a.open("GET",u.browser_download_url,!0),a.responseType="arraybuffer",a.onreadystatechange=()=>{a.readyState==4&&(a.status==200?l(u.id,a.response):q(`Error downloading from ${u.url}: ${a.status}: ${a.responseText}`,!1))},a.onprogress=d=>{d.loaded&&d.lengthComputable&&Le.update(f=>(f[0].text=`Downloading RuneLite... ${(Math.round(1e3*d.loaded/d.total)/10).toFixed(1)}%`,f))},a.send()}else $("Latest JAR is already installed"),l()}else q(`Error from ${i}: ${c.status}: ${c.responseText}`,!1)},c.send()}function Cn(t,e,n){return Vt(t,e,n,!1)}function Tn(t,e,n){return Vt(t,e,n,!0)}function Pn(t,e,n){Ue();const r=(c,i)=>{const u=new XMLHttpRequest,a={};c&&(a.version=c),t&&(a.jx_session_id=t),e&&(a.jx_character_id=e),n&&(a.jx_display_name=n),u.open("POST","/launch-hdos-jar?".concat(new URLSearchParams(a).toString()),!0),u.onreadystatechange=()=>{u.readyState==4&&($(`Game launch status: '${u.responseText.trim()}'`),u.status==200&&c&&st.set(c))},u.send(i)},o=new XMLHttpRequest,l="https://cdn.hdos.dev/client/getdown.txt";o.open("GET",l,!0),o.onreadystatechange=()=>{if(o.readyState==4)if(o.status==200){const c=o.responseText.match(/^launcher\.version *= *(.*?)$/m);if(c&&c.length>=2){const i=c[1];if(i!==K(st)){const u=`https://cdn.hdos.dev/launcher/v${i}/hdos-launcher.jar`;$("Downloading HDOS...");const a=new XMLHttpRequest;a.open("GET",u,!0),a.responseType="arraybuffer",a.onreadystatechange=()=>{if(a.readyState==4)if(a.status==200)r(i,a.response);else{const d=JSON.parse(o.responseText).map(f=>f.assets).flat().find(f=>f.name.toLowerCase()=="runelite.jar");q(`Error downloading from ${d.url}: ${a.status}: ${a.responseText}`,!1)}},a.onprogress=d=>{d.loaded&&d.lengthComputable&&Le.update(f=>(f[0].text=`Downloading HDOS... ${(Math.round(1e3*d.loaded/d.total)/10).toFixed(1)}%`,f))},a.send()}else $("Latest JAR is already installed"),r()}else $("Couldn't parse latest launcher version"),r()}else q(`Error from ${l}: ${o.status}: ${o.responseText}`,!1)},o.send()}let Ye=!1;function Ue(){var t;if(K(Y)&&!Ye){Ye=!0;const e=new XMLHttpRequest;e.open("POST","/save-config",!0),e.onreadystatechange=()=>{e.readyState==4&&($(`Save config status: '${e.responseText.trim()}'`),e.status==200&&Y.set(!1),Ye=!1)},e.setRequestHeader("Content-Type","application/json");const n={};(t=se.selected_characters)==null||t.forEach((l,c)=>{n[c]=l});const r={};Object.assign(r,se),r.selected_characters=n;const o=JSON.stringify(r,null,4);e.send(o)}}function Zt(){return new Promise((t,e)=>{const n=new XMLHttpRequest,r=K(Ut).concat("/list-game-clients");n.open("GET",r,!0),n.onreadystatechange=()=>{if(n.readyState==4)if(n.status==200&&n.getResponseHeader("content-type")==="application/json"){const o=JSON.parse(n.responseText);t(Object.keys(o).map(l=>({uid:l,identity:o[l].identity||null})))}else e(`error (${n.responseText})`)},n.send()})}function Rn(){const t=new XMLHttpRequest;t.open("POST","/save-plugin-config",!0),t.setRequestHeader("Content-Type","application/json"),t.onreadystatechange=()=>{t.readyState==4&&$(`Save-plugin-config status: ${t.responseText.trim()}`)},t.send(JSON.stringify(K(fe)))}async function ht(t,e,n,r,o){Ue();const l=`${e?"osrs":atob(V.provider)}-${t?"win":"mac"}`,c=t?e?$t:qt:e?Jt:Bt,i=async(O,C)=>{const b={};O&&(b.hash=O),n&&(b.jx_session_id=n),r&&(b.jx_character_id=r),o&&(b.jx_display_name=o);const T=await fetch(`/launch-${e?"osrs":"rs3"}-${t?"exe":"app"}?${new URLSearchParams(b).toString()}`,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:await C});T.text().then(D=>$(`Game launch status: '${D.trim()}'`)),T.status==200&&O&&c.set(O)},u=`${atob(V.direct6_url)}${l}/${l}.json`,a=await fetch(u,{method:"GET"}),d=await a.text();if(a.status!==200){q(`Error from ${u}: ${a.status}: ${d}`,!1);return}const f=JSON.parse(atob(d.split(".")[1])).environments.production;if(K(c)===f.id){$("Latest client is already installed"),i();return}$(`Downloading client version ${f.version}`);const p=`${atob(V.direct6_url)}${l}/catalog/${f.id}/catalog.json`,k=await fetch(p,{method:"GET"}),g=await k.text();if(k.status!==200){q(`Error from ${p}: ${k.status}: ${g}`,!1);return}const E=JSON.parse(atob(g.split(".")[1])),N=E.metafile.replace(/^http:/i,"https:"),y=await fetch(N,{method:"GET"}),v=await y.text();if(y.status!==200){q(`Error from ${N}: ${y.status}: ${v}`,!1);return}const w=JSON.parse(atob(v.split(".")[1])),x=w.pieces.digests.map(O=>{const C=atob(O).split("").map(T=>T.charCodeAt(0).toString(16).padStart(2,"0")).join(""),b=E.config.remote.baseUrl.replace(/^http:/i,"https:").concat(E.config.remote.pieceFormat.replace("{SubString:0,2,{TargetDigest}}",C.substring(0,2)).replace("{TargetDigest}",C));return fetch(b,{method:"GET"}).then(T=>T.blob().then(D=>{const A=new DecompressionStream("gzip");return new Response(D.slice(6).stream().pipeThrough(A)).blob()}))});let R=0,P=null;for(let O=0;O{const C=new Blob(O).slice(R,R+P);i(w.id,C.arrayBuffer())})}function bt(t,e,n){const r=t.slice();return r[22]=e[n],r}function gt(t){let e,n=t[22][1].displayName+"",r,o,l;return{c(){e=m("option"),r=G(n),_(e,"data-id",o=t[22][1].userId),_(e,"class","dark:bg-slate-900"),e.__value=l=t[22][1].displayName,be(e,e.__value)},m(c,i){L(c,e,i),h(e,r)},p(c,i){i&4&&n!==(n=c[22][1].displayName+"")&&ae(r,n),i&4&&o!==(o=c[22][1].userId)&&_(e,"data-id",o),i&4&&l!==(l=c[22][1].displayName)&&(e.__value=l,be(e,e.__value))},d(c){c&&S(e)}}}function En(t){let e,n,r,o,l,c,i,u,a,d=pe(t[2]),f=[];for(let p=0;pn(13,r=b)),F(t,ye,b=>n(14,o=b)),F(t,Ge,b=>n(2,l=b)),F(t,J,b=>n(15,c=b));let{showAccountDropdown:i}=e,{hoverAccountButton:u}=e;const a=atob(V.origin),d=atob(V.clientid),f=a.concat("/oauth2/token"),p=a.concat("/oauth2/revoke");let k=!1,g;function E(b){u||b.button===0&&i&&!k&&n(5,i=!1)}function N(){var D;if(g.options.length==0){$("Logout unsuccessful: no account selected");return}let b=r.credentials;r.account&&(l.delete((D=r.account)==null?void 0:D.userId),Ge.set(l));const T=g.selectedIndex;T>0?n(1,g.selectedIndex=T-1,g):T==0&&l.size>0?n(1,g.selectedIndex=T+1,g):(delete r.account,delete r.character,delete r.credentials),v(),b&&Xt(b,f,d).then(A=>{A===null?Ln(b.access_token,p,d).then(X=>{X===200?($("Successful logout"),y(b)):q(`Logout unsuccessful: status ${X}`,!1)}):A===400||A===401?($("Logout unsuccessful: credentials are invalid, so discarding them anyway"),b&&y(b)):q("Logout unsuccessful: unable to verify credentials due to a network error",!1)})}function y(b){o.delete(b.sub),Me()}function v(){var T;Y.set(!0);const b=g[g.selectedIndex].getAttribute("data-id");if(j(Z,r.account=l.get(b),r),j(J,c.selected_account=b,c),j(Z,r.credentials=o.get((T=r.account)==null?void 0:T.userId),r),r.account&&r.account.characters){const D=document.getElementById("character_select");D.selectedIndex=0;const[A]=r.account.characters.keys();j(Z,r.character=r.account.characters.get(A),r)}}addEventListener("mousedown",E),De(()=>{var T;let b=0;l.forEach(D=>{var A;D.displayName==((A=r.account)==null?void 0:A.displayName)&&n(1,g.selectedIndex=b,g),b++}),j(Z,r.credentials=o.get((T=r.account)==null?void 0:T.userId),r)}),rt(()=>{removeEventListener("mousedown",E)});function w(b){z[b?"unshift":"push"](()=>{g=b,n(1,g)})}const x=()=>{v()},R=()=>{Gt()},P=()=>{N()},O=()=>{n(0,k=!0)},C=()=>{n(0,k=!1)};return t.$$set=b=>{"showAccountDropdown"in b&&n(5,i=b.showAccountDropdown),"hoverAccountButton"in b&&n(6,u=b.hoverAccountButton)},[k,g,l,N,v,i,u,w,x,R,P,O,C]}class Nn extends ce{constructor(e){super(),le(this,e,Mn,En,oe,{showAccountDropdown:5,hoverAccountButton:6})}}function In(t){let e;return{c(){e=G("Log In")},m(n,r){L(n,e,r)},p:I,d(n){n&&S(e)}}}function On(t){var r;let e=((r=t[6].account)==null?void 0:r.displayName)+"",n;return{c(){n=G(e)},m(o,l){L(o,n,l)},p(o,l){var c;l&64&&e!==(e=((c=o[6].account)==null?void 0:c.displayName)+"")&&ae(n,e)},d(o){o&&S(n)}}}function mt(t){let e,n,r,o;function l(i){t[20](i)}let c={hoverAccountButton:t[2]};return t[1]!==void 0&&(c.showAccountDropdown=t[1]),n=new Nn({props:c}),z.push(()=>Oe(n,"showAccountDropdown",l)),{c(){e=m("div"),ne(n.$$.fragment),_(e,"class","absolute right-2 top-[72px]")},m(i,u){L(i,e,u),ee(n,e,null),o=!0},p(i,u){const a={};u&4&&(a.hoverAccountButton=i[2]),!r&&u&2&&(r=!0,a.showAccountDropdown=i[1],Ie(()=>r=!1)),n.$set(a)},i(i){o||(U(n.$$.fragment,i),o=!0)},o(i){B(n.$$.fragment,i),o=!1},d(i){i&&S(e),te(n)}}}function jn(t){let e,n,r,o,l,c,i,u,a,d,f,p,k,g,E,N;function y(R,P){return R[6].account?On:In}let v=y(t),w=v(t),x=t[1]&&mt(t);return{c(){e=m("div"),n=m("div"),r=m("button"),r.textContent="RS3",o=M(),l=m("button"),l.textContent="OSRS",c=M(),i=m("div"),u=m("button"),u.innerHTML='Change Theme',a=M(),d=m("button"),d.innerHTML='Settings',f=M(),p=m("button"),w.c(),k=M(),x&&x.c(),_(r,"class","mx-1 w-20 rounded-lg border-2 border-blue-500 p-2 duration-200 hover:opacity-75"),_(l,"class","mx-1 w-20 rounded-lg border-2 border-blue-500 bg-blue-500 p-2 text-black duration-200 hover:opacity-75"),_(n,"class","m-3 ml-9 font-bold"),_(u,"class","my-3 h-10 w-10 rounded-full bg-blue-500 p-2 duration-200 hover:rotate-45 hover:opacity-75"),_(d,"class","m-3 h-10 w-10 rounded-full bg-blue-500 p-2 duration-200 hover:rotate-45 hover:opacity-75"),_(p,"class","m-2 w-48 rounded-lg border-2 border-slate-300 bg-inherit p-2 text-center font-bold text-black duration-200 hover:opacity-75 dark:border-slate-800 dark:text-slate-50"),_(i,"class","ml-auto flex"),_(e,"class","fixed top-0 flex h-16 w-screen border-b-2 border-slate-300 bg-slate-100 duration-200 dark:border-slate-800 dark:bg-slate-900")},m(R,P){L(R,e,P),h(e,n),h(n,r),t[10](r),h(n,o),h(n,l),t[12](l),h(e,c),h(e,i),h(i,u),h(i,a),h(i,d),h(i,f),h(i,p),w.m(p,null),t[16](p),h(e,k),x&&x.m(e,null),g=!0,E||(N=[H(r,"click",t[11]),H(l,"click",t[13]),H(u,"click",t[14]),H(d,"click",t[15]),H(p,"mouseenter",t[17]),H(p,"mouseleave",t[18]),H(p,"click",t[19])],E=!0)},p(R,[P]){v===(v=y(R))&&w?w.p(R,P):(w.d(1),w=v(R),w&&(w.c(),w.m(p,null))),R[1]?x?(x.p(R,P),P&2&&U(x,1)):(x=mt(R),x.c(),U(x,1),x.m(e,null)):x&&(ve(),B(x,1,1,()=>{x=null}),Se())},i(R){g||(U(x),g=!0)},o(R){B(x),g=!1},d(R){R&&S(e),t[10](null),t[12](null),w.d(),t[16](null),x&&x.d(),E=!1,re(N)}}}function Hn(t,e,n){let r,o,l;F(t,J,T=>n(21,r=T)),F(t,Y,T=>n(22,o=T)),F(t,Z,T=>n(6,l=T));let{showSettings:c}=e,i=!1,u=!1,a,d,f;function p(){let T=document.documentElement;T.classList.contains("dark")?T.classList.remove("dark"):T.classList.add("dark"),j(J,r.use_dark_theme=!r.use_dark_theme,r),j(Y,o=!0,o)}function k(T){switch(T){case Q.osrs:j(Z,l.game=Q.osrs,l),j(Z,l.client=r.selected_client_index,l),j(J,r.selected_game_index=Q.osrs,r),j(Y,o=!0,o),d.classList.add("bg-blue-500","text-black"),a.classList.remove("bg-blue-500","text-black");break;case Q.rs3:j(Z,l.game=Q.rs3,l),j(J,r.selected_game_index=Q.rs3,r),j(Y,o=!0,o),d.classList.remove("bg-blue-500","text-black"),a.classList.add("bg-blue-500","text-black");break}}function g(){if(f.innerHTML=="Log In"){Gt();return}n(1,i=!i)}De(()=>{k(r.selected_game_index)});function E(T){z[T?"unshift":"push"](()=>{a=T,n(3,a)})}const N=()=>{k(Q.rs3)};function y(T){z[T?"unshift":"push"](()=>{d=T,n(4,d)})}const v=()=>{k(Q.osrs)},w=()=>p(),x=()=>{n(0,c=!0)};function R(T){z[T?"unshift":"push"](()=>{f=T,n(5,f)})}const P=()=>{n(2,u=!0)},O=()=>{n(2,u=!1)},C=()=>g();function b(T){i=T,n(1,i)}return t.$$set=T=>{"showSettings"in T&&n(0,c=T.showSettings)},[c,i,u,a,d,f,l,p,k,g,E,N,y,v,w,x,R,P,O,C,b]}class An extends ce{constructor(e){super(),le(this,e,Hn,jn,oe,{showSettings:0})}}function Dn(t){let e,n,r,o,l,c;return{c(){e=m("div"),n=m("div"),r=M(),o=m("div"),_(n,"class","absolute left-0 top-0 z-10 h-screen w-screen backdrop-blur-sm backdrop-filter"),_(o,"class","absolute left-0 top-0 z-10 h-screen w-screen bg-black opacity-75"),_(o,"role","none")},m(i,u){L(i,e,u),h(e,n),h(e,r),h(e,o),l||(c=H(o,"click",t[1]),l=!0)},p:I,i:I,o:I,d(i){i&&S(e),l=!1,c()}}}function Un(t){const e=ln();return[e,r=>{e("click",r)}]}class at extends ce{constructor(e){super(),le(this,e,Un,Dn,oe,{})}}function qn(t){let e,n,r,o,l,c,i,u,a,d,f,p;return n=new at({}),{c(){e=m("div"),ne(n.$$.fragment),r=M(),o=m("div"),l=m("p"),l.textContent=`${t[1]}`,c=M(),i=m("p"),i.textContent=`${t[2]}`,u=M(),a=m("button"),a.textContent="I Understand",_(l,"class","p-2"),_(i,"class","p-2"),_(a,"class","m-5 rounded-lg border-2 border-blue-500 p-2 duration-200 hover:opacity-75"),_(o,"class","absolute left-1/4 top-1/4 z-20 w-1/2 rounded-lg bg-slate-100 p-5 text-center shadow-lg dark:bg-slate-900"),_(e,"id","disclaimer")},m(k,g){L(k,e,g),ee(n,e,null),h(e,r),h(e,o),h(o,l),h(o,c),h(o,i),h(o,u),h(o,a),d=!0,f||(p=H(a,"click",t[3]),f=!0)},p:I,i(k){d||(U(n.$$.fragment,k),d=!0)},o(k){B(n.$$.fragment,k),d=!1},d(k){k&&S(e),te(n),f=!1,p()}}}function Bn(t,e,n){let r;F(t,Xe,i=>n(0,r=i));const o=atob("Qm9sdCBpcyBhbiB1bm9mZmljaWFsIHRoaXJkLXBhcnR5IGxhdW5jaGVyLiBJdCdzIGZyZWUgYW5kIG9wZW4tc291cmNlIHNvZnR3YXJlIGxpY2Vuc2VkIHVuZGVyIEFHUEwgMy4wLg=="),l=atob("SmFnZXggaXMgbm90IHJlc3BvbnNpYmxlIGZvciBhbnkgcHJvYmxlbXMgb3IgZGFtYWdlIGNhdXNlZCBieSB1c2luZyB0aGlzIHByb2R1Y3Qu");return[r,o,l,()=>{j(Xe,r=!1,r)}]}class $n extends ce{constructor(e){super(),le(this,e,Bn,qn,oe,{})}}function Jn(t){let e,n,r,o;return{c(){e=m("div"),n=m("button"),n.innerHTML=`
Browse app data +`).map(u=>u.split(": ")));if(!i.Filename||!i.Size){q(`Could not parse package data from URL: ${c}`,!1),r();return}if(i.SHA256!==K(tt)){$("Downloading RS3 client...");const u=new XMLHttpRequest;u.open("GET",l.concat(i.Filename),!0),u.responseType="arraybuffer",u.onprogress=a=>{a.loaded&&Le.update(d=>(d[0].text=`Downloading RS3 client... ${(Math.round(1e3*a.loaded/a.total)/10).toFixed(1)}%`,d))},u.onreadystatechange=()=>{u.readyState==4&&u.status==200&&r(i.SHA256,u.response)},u.onerror=()=>{q(`Error downloading game client: from ${c}: non-http error`,!1),r()},u.send()}else $("Latest client is already installed"),r()}},o.onerror=()=>{q(`Error: from ${c}: non-http error`,!1),r()},o.send()}function Vt(t,e,n,r){Ue();const o=r?"/launch-runelite-jar-configure?":"/launch-runelite-jar?",l=(u,a,d)=>{const f=new XMLHttpRequest,p={};u&&(p.id=u),d&&(p.jar_path=d),t&&(p.jx_session_id=t),e&&(p.jx_character_id=e),n&&(p.jx_display_name=n),se.flatpak_rich_presence&&(p.flatpak_rich_presence=""),f.open(a?"POST":"GET",o.concat(new URLSearchParams(p).toString()),!0),f.onreadystatechange=()=>{f.readyState==4&&($(`Game launch status: '${f.responseText.trim()}'`),f.status==200&&u&&nt.set(u))},f.send(a)};if(se.runelite_use_custom_jar){l(null,null,se.runelite_custom_jar);return}const c=new XMLHttpRequest,i="https://api.github.com/repos/runelite/launcher/releases";c.open("GET",i,!0),c.onreadystatechange=()=>{if(c.readyState==4)if(c.status==200){const u=JSON.parse(c.responseText).map(a=>a.assets).flat().find(a=>a.name.toLowerCase()=="runelite.jar");if(u.id!=K(nt)){$("Downloading RuneLite...");const a=new XMLHttpRequest;a.open("GET",u.browser_download_url,!0),a.responseType="arraybuffer",a.onreadystatechange=()=>{a.readyState==4&&(a.status==200?l(u.id,a.response):q(`Error downloading from ${u.url}: ${a.status}: ${a.responseText}`,!1))},a.onprogress=d=>{d.loaded&&d.lengthComputable&&Le.update(f=>(f[0].text=`Downloading RuneLite... ${(Math.round(1e3*d.loaded/d.total)/10).toFixed(1)}%`,f))},a.send()}else $("Latest JAR is already installed"),l()}else q(`Error from ${i}: ${c.status}: ${c.responseText}`,!1)},c.send()}function Cn(t,e,n){return Vt(t,e,n,!1)}function Tn(t,e,n){return Vt(t,e,n,!0)}function Pn(t,e,n){Ue();const r=(c,i)=>{const u=new XMLHttpRequest,a={};c&&(a.version=c),t&&(a.jx_session_id=t),e&&(a.jx_character_id=e),n&&(a.jx_display_name=n),u.open("POST","/launch-hdos-jar?".concat(new URLSearchParams(a).toString()),!0),u.onreadystatechange=()=>{u.readyState==4&&($(`Game launch status: '${u.responseText.trim()}'`),u.status==200&&c&&st.set(c))},u.send(i)},o=new XMLHttpRequest,l="https://cdn.hdos.dev/client/getdown.txt";o.open("GET",l,!0),o.onreadystatechange=()=>{if(o.readyState==4)if(o.status==200){const c=o.responseText.match(/^launcher\.version *= *(.*?)$/m);if(c&&c.length>=2){const i=c[1];if(i!==K(st)){const u=`https://cdn.hdos.dev/launcher/v${i}/hdos-launcher.jar`;$("Downloading HDOS...");const a=new XMLHttpRequest;a.open("GET",u,!0),a.responseType="arraybuffer",a.onreadystatechange=()=>{if(a.readyState==4)if(a.status==200)r(i,a.response);else{const d=JSON.parse(o.responseText).map(f=>f.assets).flat().find(f=>f.name.toLowerCase()=="runelite.jar");q(`Error downloading from ${d.url}: ${a.status}: ${a.responseText}`,!1)}},a.onprogress=d=>{d.loaded&&d.lengthComputable&&Le.update(f=>(f[0].text=`Downloading HDOS... ${(Math.round(1e3*d.loaded/d.total)/10).toFixed(1)}%`,f))},a.send()}else $("Latest JAR is already installed"),r()}else $("Couldn't parse latest launcher version"),r()}else q(`Error from ${l}: ${o.status}: ${o.responseText}`,!1)},o.send()}let Ye=!1;function Ue(){var t;if(K(Y)&&!Ye){Ye=!0;const e=new XMLHttpRequest;e.open("POST","/save-config",!0),e.onreadystatechange=()=>{e.readyState==4&&($(`Save config status: '${e.responseText.trim()}'`),e.status==200&&Y.set(!1),Ye=!1)},e.setRequestHeader("Content-Type","application/json");const n={};(t=se.selected_characters)==null||t.forEach((l,c)=>{n[c]=l});const r={};Object.assign(r,se),r.selected_characters=n;const o=JSON.stringify(r,null,4);e.send(o)}}function Zt(){return new Promise((t,e)=>{const n=new XMLHttpRequest,r=K(Ut).concat("/list-game-clients");n.open("GET",r,!0),n.onreadystatechange=()=>{if(n.readyState==4)if(n.status==200&&n.getResponseHeader("content-type")==="application/json"){const o=JSON.parse(n.responseText);t(Object.keys(o).map(l=>({uid:l,identity:o[l].identity||null})))}else e(`error (${n.responseText})`)},n.send()})}function Rn(){const t=new XMLHttpRequest;t.open("POST","/save-plugin-config",!0),t.setRequestHeader("Content-Type","application/json"),t.onreadystatechange=()=>{t.readyState==4&&$(`Save-plugin-config status: ${t.responseText.trim()}`)},t.send(JSON.stringify(K(fe)))}async function ht(t,e,n,r,o){Ue();const l=`${e?"osrs":atob(V.provider)}-${t?"win":"mac"}`,c=t?e?$t:qt:e?Jt:Bt,i=async(O,C)=>{const b={};O&&(b.hash=O),n&&(b.jx_session_id=n),r&&(b.jx_character_id=r),o&&(b.jx_display_name=o);const T=await fetch(`/launch-${e?"osrs":"rs3"}-${t?"exe":"app"}?${new URLSearchParams(b).toString()}`,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:C});T.text().then(D=>$(`Game launch status: '${D.trim()}'`)),T.status==200&&O&&c.set(O)},u=`${atob(V.direct6_url)}${l}/${l}.json`,a=await fetch(u,{method:"GET"}),d=await a.text();if(a.status!==200){q(`Error from ${u}: ${a.status}: ${d}`,!1);return}const f=JSON.parse(atob(d.split(".")[1])).environments.production;if(K(c)===f.id){$("Latest client is already installed"),i();return}$(`Downloading client version ${f.version}`);const p=`${atob(V.direct6_url)}${l}/catalog/${f.id}/catalog.json`,k=await fetch(p,{method:"GET"}),g=await k.text();if(k.status!==200){q(`Error from ${p}: ${k.status}: ${g}`,!1);return}const E=JSON.parse(atob(g.split(".")[1])),N=E.metafile.replace(/^http:/i,"https:"),y=await fetch(N,{method:"GET"}),v=await y.text();if(y.status!==200){q(`Error from ${N}: ${y.status}: ${v}`,!1);return}const w=JSON.parse(atob(v.split(".")[1])),x=w.pieces.digests.map(O=>{const C=atob(O).split("").map(T=>T.charCodeAt(0).toString(16).padStart(2,"0")).join(""),b=E.config.remote.baseUrl.replace(/^http:/i,"https:").concat(E.config.remote.pieceFormat.replace("{SubString:0,2,{TargetDigest}}",C.substring(0,2)).replace("{TargetDigest}",C));return fetch(b,{method:"GET"}).then(T=>T.blob().then(D=>{const A=new DecompressionStream("gzip");return new Response(D.slice(6).stream().pipeThrough(A)).blob()}))});let R=0,P=null;for(let O=0;O{const C=new Blob(O).slice(R,R+P);i(w.id,C)})}function bt(t,e,n){const r=t.slice();return r[22]=e[n],r}function gt(t){let e,n=t[22][1].displayName+"",r,o,l;return{c(){e=m("option"),r=G(n),_(e,"data-id",o=t[22][1].userId),_(e,"class","dark:bg-slate-900"),e.__value=l=t[22][1].displayName,be(e,e.__value)},m(c,i){L(c,e,i),h(e,r)},p(c,i){i&4&&n!==(n=c[22][1].displayName+"")&&ae(r,n),i&4&&o!==(o=c[22][1].userId)&&_(e,"data-id",o),i&4&&l!==(l=c[22][1].displayName)&&(e.__value=l,be(e,e.__value))},d(c){c&&S(e)}}}function En(t){let e,n,r,o,l,c,i,u,a,d=pe(t[2]),f=[];for(let p=0;pn(13,r=b)),F(t,ye,b=>n(14,o=b)),F(t,Ge,b=>n(2,l=b)),F(t,J,b=>n(15,c=b));let{showAccountDropdown:i}=e,{hoverAccountButton:u}=e;const a=atob(V.origin),d=atob(V.clientid),f=a.concat("/oauth2/token"),p=a.concat("/oauth2/revoke");let k=!1,g;function E(b){u||b.button===0&&i&&!k&&n(5,i=!1)}function N(){var D;if(g.options.length==0){$("Logout unsuccessful: no account selected");return}let b=r.credentials;r.account&&(l.delete((D=r.account)==null?void 0:D.userId),Ge.set(l));const T=g.selectedIndex;T>0?n(1,g.selectedIndex=T-1,g):T==0&&l.size>0?n(1,g.selectedIndex=T+1,g):(delete r.account,delete r.character,delete r.credentials),v(),b&&Xt(b,f,d).then(A=>{A===null?Ln(b.access_token,p,d).then(X=>{X===200?($("Successful logout"),y(b)):q(`Logout unsuccessful: status ${X}`,!1)}):A===400||A===401?($("Logout unsuccessful: credentials are invalid, so discarding them anyway"),b&&y(b)):q("Logout unsuccessful: unable to verify credentials due to a network error",!1)})}function y(b){o.delete(b.sub),Me()}function v(){var T;Y.set(!0);const b=g[g.selectedIndex].getAttribute("data-id");if(j(Z,r.account=l.get(b),r),j(J,c.selected_account=b,c),j(Z,r.credentials=o.get((T=r.account)==null?void 0:T.userId),r),r.account&&r.account.characters){const D=document.getElementById("character_select");D.selectedIndex=0;const[A]=r.account.characters.keys();j(Z,r.character=r.account.characters.get(A),r)}}addEventListener("mousedown",E),De(()=>{var T;let b=0;l.forEach(D=>{var A;D.displayName==((A=r.account)==null?void 0:A.displayName)&&n(1,g.selectedIndex=b,g),b++}),j(Z,r.credentials=o.get((T=r.account)==null?void 0:T.userId),r)}),rt(()=>{removeEventListener("mousedown",E)});function w(b){z[b?"unshift":"push"](()=>{g=b,n(1,g)})}const x=()=>{v()},R=()=>{Gt()},P=()=>{N()},O=()=>{n(0,k=!0)},C=()=>{n(0,k=!1)};return t.$$set=b=>{"showAccountDropdown"in b&&n(5,i=b.showAccountDropdown),"hoverAccountButton"in b&&n(6,u=b.hoverAccountButton)},[k,g,l,N,v,i,u,w,x,R,P,O,C]}class Nn extends ce{constructor(e){super(),le(this,e,Mn,En,oe,{showAccountDropdown:5,hoverAccountButton:6})}}function In(t){let e;return{c(){e=G("Log In")},m(n,r){L(n,e,r)},p:I,d(n){n&&S(e)}}}function On(t){var r;let e=((r=t[6].account)==null?void 0:r.displayName)+"",n;return{c(){n=G(e)},m(o,l){L(o,n,l)},p(o,l){var c;l&64&&e!==(e=((c=o[6].account)==null?void 0:c.displayName)+"")&&ae(n,e)},d(o){o&&S(n)}}}function mt(t){let e,n,r,o;function l(i){t[20](i)}let c={hoverAccountButton:t[2]};return t[1]!==void 0&&(c.showAccountDropdown=t[1]),n=new Nn({props:c}),z.push(()=>Oe(n,"showAccountDropdown",l)),{c(){e=m("div"),ne(n.$$.fragment),_(e,"class","absolute right-2 top-[72px]")},m(i,u){L(i,e,u),ee(n,e,null),o=!0},p(i,u){const a={};u&4&&(a.hoverAccountButton=i[2]),!r&&u&2&&(r=!0,a.showAccountDropdown=i[1],Ie(()=>r=!1)),n.$set(a)},i(i){o||(U(n.$$.fragment,i),o=!0)},o(i){B(n.$$.fragment,i),o=!1},d(i){i&&S(e),te(n)}}}function jn(t){let e,n,r,o,l,c,i,u,a,d,f,p,k,g,E,N;function y(R,P){return R[6].account?On:In}let v=y(t),w=v(t),x=t[1]&&mt(t);return{c(){e=m("div"),n=m("div"),r=m("button"),r.textContent="RS3",o=M(),l=m("button"),l.textContent="OSRS",c=M(),i=m("div"),u=m("button"),u.innerHTML='Change Theme',a=M(),d=m("button"),d.innerHTML='Settings',f=M(),p=m("button"),w.c(),k=M(),x&&x.c(),_(r,"class","mx-1 w-20 rounded-lg border-2 border-blue-500 p-2 duration-200 hover:opacity-75"),_(l,"class","mx-1 w-20 rounded-lg border-2 border-blue-500 bg-blue-500 p-2 text-black duration-200 hover:opacity-75"),_(n,"class","m-3 ml-9 font-bold"),_(u,"class","my-3 h-10 w-10 rounded-full bg-blue-500 p-2 duration-200 hover:rotate-45 hover:opacity-75"),_(d,"class","m-3 h-10 w-10 rounded-full bg-blue-500 p-2 duration-200 hover:rotate-45 hover:opacity-75"),_(p,"class","m-2 w-48 rounded-lg border-2 border-slate-300 bg-inherit p-2 text-center font-bold text-black duration-200 hover:opacity-75 dark:border-slate-800 dark:text-slate-50"),_(i,"class","ml-auto flex"),_(e,"class","fixed top-0 flex h-16 w-screen border-b-2 border-slate-300 bg-slate-100 duration-200 dark:border-slate-800 dark:bg-slate-900")},m(R,P){L(R,e,P),h(e,n),h(n,r),t[10](r),h(n,o),h(n,l),t[12](l),h(e,c),h(e,i),h(i,u),h(i,a),h(i,d),h(i,f),h(i,p),w.m(p,null),t[16](p),h(e,k),x&&x.m(e,null),g=!0,E||(N=[H(r,"click",t[11]),H(l,"click",t[13]),H(u,"click",t[14]),H(d,"click",t[15]),H(p,"mouseenter",t[17]),H(p,"mouseleave",t[18]),H(p,"click",t[19])],E=!0)},p(R,[P]){v===(v=y(R))&&w?w.p(R,P):(w.d(1),w=v(R),w&&(w.c(),w.m(p,null))),R[1]?x?(x.p(R,P),P&2&&U(x,1)):(x=mt(R),x.c(),U(x,1),x.m(e,null)):x&&(ve(),B(x,1,1,()=>{x=null}),Se())},i(R){g||(U(x),g=!0)},o(R){B(x),g=!1},d(R){R&&S(e),t[10](null),t[12](null),w.d(),t[16](null),x&&x.d(),E=!1,re(N)}}}function Hn(t,e,n){let r,o,l;F(t,J,T=>n(21,r=T)),F(t,Y,T=>n(22,o=T)),F(t,Z,T=>n(6,l=T));let{showSettings:c}=e,i=!1,u=!1,a,d,f;function p(){let T=document.documentElement;T.classList.contains("dark")?T.classList.remove("dark"):T.classList.add("dark"),j(J,r.use_dark_theme=!r.use_dark_theme,r),j(Y,o=!0,o)}function k(T){switch(T){case Q.osrs:j(Z,l.game=Q.osrs,l),j(Z,l.client=r.selected_client_index,l),j(J,r.selected_game_index=Q.osrs,r),j(Y,o=!0,o),d.classList.add("bg-blue-500","text-black"),a.classList.remove("bg-blue-500","text-black");break;case Q.rs3:j(Z,l.game=Q.rs3,l),j(J,r.selected_game_index=Q.rs3,r),j(Y,o=!0,o),d.classList.remove("bg-blue-500","text-black"),a.classList.add("bg-blue-500","text-black");break}}function g(){if(f.innerHTML=="Log In"){Gt();return}n(1,i=!i)}De(()=>{k(r.selected_game_index)});function E(T){z[T?"unshift":"push"](()=>{a=T,n(3,a)})}const N=()=>{k(Q.rs3)};function y(T){z[T?"unshift":"push"](()=>{d=T,n(4,d)})}const v=()=>{k(Q.osrs)},w=()=>p(),x=()=>{n(0,c=!0)};function R(T){z[T?"unshift":"push"](()=>{f=T,n(5,f)})}const P=()=>{n(2,u=!0)},O=()=>{n(2,u=!1)},C=()=>g();function b(T){i=T,n(1,i)}return t.$$set=T=>{"showSettings"in T&&n(0,c=T.showSettings)},[c,i,u,a,d,f,l,p,k,g,E,N,y,v,w,x,R,P,O,C,b]}class An extends ce{constructor(e){super(),le(this,e,Hn,jn,oe,{showSettings:0})}}function Dn(t){let e,n,r,o,l,c;return{c(){e=m("div"),n=m("div"),r=M(),o=m("div"),_(n,"class","absolute left-0 top-0 z-10 h-screen w-screen backdrop-blur-sm backdrop-filter"),_(o,"class","absolute left-0 top-0 z-10 h-screen w-screen bg-black opacity-75"),_(o,"role","none")},m(i,u){L(i,e,u),h(e,n),h(e,r),h(e,o),l||(c=H(o,"click",t[1]),l=!0)},p:I,i:I,o:I,d(i){i&&S(e),l=!1,c()}}}function Un(t){const e=ln();return[e,r=>{e("click",r)}]}class at extends ce{constructor(e){super(),le(this,e,Un,Dn,oe,{})}}function qn(t){let e,n,r,o,l,c,i,u,a,d,f,p;return n=new at({}),{c(){e=m("div"),ne(n.$$.fragment),r=M(),o=m("div"),l=m("p"),l.textContent=`${t[1]}`,c=M(),i=m("p"),i.textContent=`${t[2]}`,u=M(),a=m("button"),a.textContent="I Understand",_(l,"class","p-2"),_(i,"class","p-2"),_(a,"class","m-5 rounded-lg border-2 border-blue-500 p-2 duration-200 hover:opacity-75"),_(o,"class","absolute left-1/4 top-1/4 z-20 w-1/2 rounded-lg bg-slate-100 p-5 text-center shadow-lg dark:bg-slate-900"),_(e,"id","disclaimer")},m(k,g){L(k,e,g),ee(n,e,null),h(e,r),h(e,o),h(o,l),h(o,c),h(o,i),h(o,u),h(o,a),d=!0,f||(p=H(a,"click",t[3]),f=!0)},p:I,i(k){d||(U(n.$$.fragment,k),d=!0)},o(k){B(n.$$.fragment,k),d=!1},d(k){k&&S(e),te(n),f=!1,p()}}}function Bn(t,e,n){let r;F(t,Xe,i=>n(0,r=i));const o=atob("Qm9sdCBpcyBhbiB1bm9mZmljaWFsIHRoaXJkLXBhcnR5IGxhdW5jaGVyLiBJdCdzIGZyZWUgYW5kIG9wZW4tc291cmNlIHNvZnR3YXJlIGxpY2Vuc2VkIHVuZGVyIEFHUEwgMy4wLg=="),l=atob("SmFnZXggaXMgbm90IHJlc3BvbnNpYmxlIGZvciBhbnkgcHJvYmxlbXMgb3IgZGFtYWdlIGNhdXNlZCBieSB1c2luZyB0aGlzIHByb2R1Y3Qu");return[r,o,l,()=>{j(Xe,r=!1,r)}]}class $n extends ce{constructor(e){super(),le(this,e,Bn,qn,oe,{})}}function Jn(t){let e,n,r,o;return{c(){e=m("div"),n=m("button"),n.innerHTML=`
Browse app data Browse App Data
`,_(n,"id","data_dir_button"),_(n,"class","p-2 hover:opacity-75"),_(e,"id","general_options"),_(e,"class","col-span-3 p-5 pt-10")},m(l,c){L(l,e,c),h(e,n),r||(o=H(n,"click",t[1]),r=!0)},p:I,i:I,o:I,d(l){l&&S(e),r=!1,o()}}}function Gn(t){function e(){var r=new XMLHttpRequest;r.open("GET","/browse-data"),r.onreadystatechange=()=>{r.readyState==4&&$(`Browse status: '${r.responseText.trim()}'`)},r.send()}return[e,()=>{e()}]}class Xn extends ce{constructor(e){super(),le(this,e,Gn,Jn,oe,{})}}function zn(t){let e,n,r,o,l,c,i,u,a,d,f,p,k,g,E,N;return{c(){e=m("div"),n=m("button"),n.innerHTML=`
Configure RuneLite Configure RuneLite
`,r=M(),o=m("div"),l=m("label"),l.textContent="Use custom RuneLite JAR:",c=M(),i=m("input"),u=M(),a=m("div"),d=m("textarea"),f=M(),p=m("br"),k=M(),g=m("button"),g.textContent="Select File",_(n,"id","rl_configure"),_(n,"class","p-2 pb-5 hover:opacity-75"),_(l,"for","use_custom_jar"),_(i,"type","checkbox"),_(i,"name","use_custom_jar"),_(i,"id","use_custom_jar"),_(i,"class","ml-2"),_(o,"class","mx-auto border-t-2 border-slate-300 p-2 pt-5 dark:border-slate-800"),d.disabled=!0,_(d,"name","custom_jar_file"),_(d,"id","custom_jar_file"),_(d,"class","h-10 rounded border-2 border-slate-300 bg-slate-100 text-slate-950 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50"),g.disabled=!0,_(g,"id","custom_jar_file_button"),_(g,"class","mt-1 rounded-lg border-2 border-blue-500 p-1 duration-200 hover:opacity-75"),_(a,"id","custom_jar_div"),_(a,"class","mx-auto p-2 opacity-25"),_(e,"id","osrs_options"),_(e,"class","col-span-3 p-5 pt-10")},m(y,v){L(y,e,v),h(e,n),h(e,r),h(e,o),h(o,l),h(o,c),h(o,i),t[9](i),h(e,u),h(e,a),h(a,d),t[11](d),h(a,f),h(a,p),h(a,k),h(a,g),t[13](g),t[15](a),E||(N=[H(n,"click",t[8]),H(i,"change",t[10]),H(d,"change",t[12]),H(g,"click",t[14])],E=!0)},p:I,i:I,o:I,d(y){y&&S(e),t[9](null),t[11](null),t[13](null),t[15](null),E=!1,re(N)}}}function Fn(t,e,n){let r,o,l;F(t,J,P=>n(16,r=P)),F(t,Z,P=>n(17,o=P)),F(t,Y,P=>n(18,l=P));let c,i,u,a;function d(){c.classList.toggle("opacity-25"),n(1,i.disabled=!i.disabled,i),n(2,u.disabled=!u.disabled,u),j(J,r.runelite_use_custom_jar=a.checked,r),r.runelite_use_custom_jar?i.value&&j(J,r.runelite_custom_jar=i.value,r):(n(1,i.value="",i),j(J,r.runelite_custom_jar="",r),j(J,r.runelite_use_custom_jar=!1,r)),j(Y,l=!0,l)}function f(){j(J,r.runelite_custom_jar=i.value,r),j(Y,l=!0,l)}function p(){n(3,a.disabled=!0,a),n(2,u.disabled=!0,u);var P=new XMLHttpRequest;P.onreadystatechange=()=>{P.readyState==4&&(P.status==200&&(n(1,i.value=P.responseText,i),j(J,r.runelite_custom_jar=P.responseText,r),j(Y,l=!0,l)),n(2,u.disabled=!1,u),n(3,a.disabled=!1,a))},P.open("GET","/jar-file-picker",!0),P.send()}function k(){var P,O,C;if(!o.account||!o.character){$("Please log in to configure RuneLite");return}Tn((P=o.credentials)==null?void 0:P.session_id,(O=o.character)==null?void 0:O.accountId,(C=o.character)==null?void 0:C.displayName)}De(()=>{n(3,a.checked=r.runelite_use_custom_jar,a),a.checked&&r.runelite_custom_jar?(c.classList.remove("opacity-25"),n(1,i.disabled=!1,i),n(2,u.disabled=!1,u),n(1,i.value=r.runelite_custom_jar,i)):(n(3,a.checked=!1,a),j(J,r.runelite_use_custom_jar=!1,r))});const g=()=>k();function E(P){z[P?"unshift":"push"](()=>{a=P,n(3,a)})}const N=()=>{d()};function y(P){z[P?"unshift":"push"](()=>{i=P,n(1,i)})}const v=()=>{f()};function w(P){z[P?"unshift":"push"](()=>{u=P,n(2,u)})}const x=()=>{p()};function R(P){z[P?"unshift":"push"](()=>{c=P,n(0,c)})}return[c,i,u,a,d,f,p,k,g,E,N,y,v,w,x,R]}class Wn extends ce{constructor(e){super(),le(this,e,Fn,zn,oe,{})}}function Vn(t){let e,n,r,o,l,c;return{c(){e=m("div"),n=m("label"),n.textContent="Enable Bolt plugin loader:",r=M(),o=m("input"),_(n,"for","enable_plugins"),_(o,"type","checkbox"),_(o,"name","enable_plugins"),_(o,"id","enable_plugins"),_(o,"class","ml-2"),_(e,"class","mx-auto p-2")},m(i,u){L(i,e,u),h(e,n),h(e,r),h(e,o),o.checked=t[3].rs_plugin_loader,l||(c=[H(o,"change",t[6]),H(o,"change",t[7])],l=!0)},p(i,u){u&8&&(o.checked=i[3].rs_plugin_loader)},d(i){i&&S(e),l=!1,re(c)}}}function Zn(t){let e,n,r,o,l,c,i,u,a,d,f,p=ge&&Vn(t);return{c(){e=m("div"),p&&p.c(),n=M(),r=m("div"),o=m("label"),o.textContent="Use custom config URI:",l=M(),c=m("input"),i=M(),u=m("div"),a=m("textarea"),_(o,"for","use_custom_uri"),_(c,"type","checkbox"),_(c,"name","use_custom_uri"),_(c,"id","use_custom_uri"),_(c,"class","ml-2"),_(r,"class","mx-auto p-2"),a.disabled=!0,_(a,"name","config_uri_address"),_(a,"id","config_uri_address"),_(a,"rows","4"),_(a,"class","rounded border-2 border-slate-300 bg-slate-100 text-slate-950 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50"),a.value=" ",_(u,"id","config_uri_div"),_(u,"class","mx-auto p-2 opacity-25"),_(e,"id","rs3_options"),_(e,"class","col-span-3 p-5 pt-10")},m(k,g){L(k,e,g),p&&p.m(e,null),h(e,n),h(e,r),h(r,o),h(r,l),h(r,c),t[8](c),h(e,i),h(e,u),h(u,a),t[11](a),t[12](u),d||(f=[H(c,"change",t[9]),H(a,"change",t[10])],d=!0)},p(k,[g]){ge&&p.p(k,g)},i:I,o:I,d(k){k&&S(e),p&&p.d(),t[8](null),t[11](null),t[12](null),d=!1,re(f)}}}function Yn(t,e,n){let r,o,l;F(t,ct,v=>n(13,r=v)),F(t,J,v=>n(3,o=v)),F(t,Y,v=>n(14,l=v));let c,i,u;function a(){c.classList.toggle("opacity-25"),n(1,i.disabled=!i.disabled,i),j(Y,l=!0,l),u.checked||(n(1,i.value=atob(r.default_config_uri),i),j(J,o.rs_config_uri="",o))}function d(){j(J,o.rs_config_uri=i.value,o),j(Y,l=!0,l)}De(()=>{o.rs_config_uri?(n(1,i.value=o.rs_config_uri,i),n(2,u.checked=!0,u),a()):n(1,i.value=atob(r.default_config_uri),i)});function f(){o.rs_plugin_loader=this.checked,J.set(o)}const p=()=>Y.set(!0);function k(v){z[v?"unshift":"push"](()=>{u=v,n(2,u)})}const g=()=>{a()},E=()=>{d()};function N(v){z[v?"unshift":"push"](()=>{i=v,n(1,i)})}function y(v){z[v?"unshift":"push"](()=>{c=v,n(0,c)})}return[c,i,u,o,a,d,f,p,k,g,E,N,y]}class Kn extends ce{constructor(e){super(),le(this,e,Yn,Zn,oe,{})}}function Qn(t){let e,n;return e=new Kn({}),{c(){ne(e.$$.fragment)},m(r,o){ee(e,r,o),n=!0},i(r){n||(U(e.$$.fragment,r),n=!0)},o(r){B(e.$$.fragment,r),n=!1},d(r){te(e,r)}}}function es(t){let e,n;return e=new Wn({}),{c(){ne(e.$$.fragment)},m(r,o){ee(e,r,o),n=!0},i(r){n||(U(e.$$.fragment,r),n=!0)},o(r){B(e.$$.fragment,r),n=!1},d(r){te(e,r)}}}function ts(t){let e,n;return e=new Xn({}),{c(){ne(e.$$.fragment)},m(r,o){ee(e,r,o),n=!0},i(r){n||(U(e.$$.fragment,r),n=!0)},o(r){B(e.$$.fragment,r),n=!1},d(r){te(e,r)}}}function ns(t){let e,n,r,o,l,c,i,u,a,d,f,p,k,g,E,N,y,v,w,x,R,P,O,C;n=new at({}),n.$on("click",t[7]);const b=[ts,es,Qn],T=[];function D(A,X){return A[1]==A[5].general?0:A[1]==A[5].osrs?1:A[1]==A[5].rs3?2:-1}return~(x=D(t))&&(R=T[x]=b[x](t)),{c(){e=m("div"),ne(n.$$.fragment),r=M(),o=m("div"),l=m("button"),l.innerHTML='Close',c=M(),i=m("div"),u=m("div"),a=m("button"),d=G("General"),f=m("br"),p=M(),k=m("button"),g=G("OSRS"),E=m("br"),N=M(),y=m("button"),v=G("RS3"),w=M(),R&&R.c(),_(l,"class","absolute right-3 top-3 rounded-full bg-rose-500 p-[2px] shadow-lg duration-200 hover:rotate-90 hover:opacity-75"),_(a,"id","general_button"),_(a,"class",me),_(k,"id","osrs_button"),_(k,"class",$e),_(y,"id","rs3_button"),_(y,"class",me),_(u,"class","relative h-full border-r-2 border-slate-300 pt-10 dark:border-slate-800"),_(i,"class","grid h-full grid-cols-4"),_(o,"class","absolute left-[13%] top-[13%] z-20 h-3/4 w-3/4 rounded-lg bg-slate-100 text-center shadow-lg dark:bg-slate-900"),_(e,"id","settings")},m(A,X){L(A,e,X),ee(n,e,null),h(e,r),h(e,o),h(o,l),h(o,c),h(o,i),h(i,u),h(u,a),h(a,d),t[9](a),h(u,f),h(u,p),h(u,k),h(k,g),t[11](k),h(u,E),h(u,N),h(u,y),h(y,v),t[13](y),h(i,w),~x&&T[x].m(i,null),P=!0,O||(C=[H(l,"click",t[8]),H(a,"click",t[10]),H(k,"click",t[12]),H(y,"click",t[14])],O=!0)},p(A,[X]){let xe=x;x=D(A),x!==xe&&(R&&(ve(),B(T[xe],1,1,()=>{T[xe]=null}),Se()),~x?(R=T[x],R||(R=T[x]=b[x](A),R.c()),U(R,1),R.m(i,null)):R=null)},i(A){P||(U(n.$$.fragment,A),U(R),P=!0)},o(A){B(n.$$.fragment,A),B(R),P=!1},d(A){A&&S(e),te(n),t[9](null),t[11](null),t[13](null),~x&&T[x].d(),O=!1,re(C)}}}let $e="border-2 border-blue-500 bg-blue-500 hover:opacity-75 font-bold text-black duration-200 rounded-lg p-1 mx-auto my-1 w-3/4",me="border-2 border-blue-500 hover:opacity-75 duration-200 rounded-lg p-1 mx-auto my-1 w-3/4";function ss(t,e,n){let{showSettings:r}=e;var o=(w=>(w[w.general=0]="general",w[w.osrs=1]="osrs",w[w.rs3=2]="rs3",w))(o||{});let l=1,c,i,u;function a(w){switch(w){case 0:n(1,l=0),n(2,c.classList.value=$e,c),n(3,i.classList.value=me,i),n(4,u.classList.value=me,u);break;case 1:n(1,l=1),n(2,c.classList.value=me,c),n(3,i.classList.value=$e,i),n(4,u.classList.value=me,u);break;case 2:n(1,l=2),n(2,c.classList.value=me,c),n(3,i.classList.value=me,i),n(4,u.classList.value=$e,u);break}}function d(w){w.key==="Escape"&&n(0,r=!1)}addEventListener("keydown",d),rt(()=>{removeEventListener("keydown",d)});const f=()=>{n(0,r=!1)},p=()=>{n(0,r=!1)};function k(w){z[w?"unshift":"push"](()=>{c=w,n(2,c)})}const g=()=>{a(o.general)};function E(w){z[w?"unshift":"push"](()=>{i=w,n(3,i)})}const N=()=>{a(o.osrs)};function y(w){z[w?"unshift":"push"](()=>{u=w,n(4,u)})}const v=()=>{a(o.rs3)};return t.$$set=w=>{"showSettings"in w&&n(0,r=w.showSettings)},[r,l,c,i,u,o,a,f,p,k,g,E,N,y,v]}class rs extends ce{constructor(e){super(),le(this,e,ss,ns,oe,{showSettings:0})}}function kt(t,e,n){const r=t.slice();return r[1]=e[n],r}function os(t){var u;let e,n=((u=t[1].time)==null?void 0:u.toLocaleTimeString())+"",r,o,l=t[1].text+"",c,i;return{c(){e=m("li"),r=G(n),o=G(` - `),c=G(l),i=M()},m(a,d){L(a,e,d),h(e,r),h(e,o),h(e,c),h(e,i)},p(a,d){var f;d&1&&n!==(n=((f=a[1].time)==null?void 0:f.toLocaleTimeString())+"")&&ae(r,n),d&1&&l!==(l=a[1].text+"")&&ae(c,l)},d(a){a&&S(e)}}}function ls(t){var u;let e,n=((u=t[1].time)==null?void 0:u.toLocaleTimeString())+"",r,o,l=t[1].text+"",c,i;return{c(){e=m("li"),r=G(n),o=G(` diff --git a/app/dist/index.html b/app/dist/index.html index f273030..42bd0c6 100644 --- a/app/dist/index.html +++ b/app/dist/index.html @@ -4,7 +4,7 @@ Bolt Launcher - + ) => { + const launch = async (hash?: string, exe?: Blob) => { const params: Record = {}; if (hash) params.hash = hash; if (jx_session_id) params.jx_session_id = jx_session_id; @@ -320,7 +320,7 @@ export async function launchOfficialClient( { method: 'POST', headers: { 'Content-Type': 'application/octet-stream' }, - body: await exe + body: exe } ); response.text().then((text) => logger.info(`Game launch status: '${text.trim()}'`)); @@ -416,6 +416,6 @@ export async function launchOfficialClient( // stitch all the data together, slice the exe out of it, and launch the game Promise.all(chunk_promises).then((x) => { const exeFile = new Blob(x).slice(exeOffset, exeOffset + exeSize); - launch(metafile.id, exeFile.arrayBuffer()); + launch(metafile.id, exeFile); }); } diff --git a/src/browser/resource_handler.cxx b/src/browser/resource_handler.cxx index cfecc09..94d0d95 100644 --- a/src/browser/resource_handler.cxx +++ b/src/browser/resource_handler.cxx @@ -1,21 +1,4 @@ #include "resource_handler.hxx" -#include "include/cef_urlrequest.h" -#include "include/internal/cef_types.h" - -// returns content-length or -1 if it's malformed or nonexistent -// CEF interprets -1 as "unknown length" -static int64_t GetContentLength(CefRefPtr response) { - std::string content_length = response->GetHeaderByName("Content-Length").ToString(); - if (content_length.size() == 0) { - return -1; - } - int64_t length = 0; - for (auto it = content_length.begin(); it != content_length.end(); it++) { - if (*it < '0' || *it > '9') return -1; - length = (length * 10) + ((int64_t)(*it) - '0'); - } - return length; -} bool Browser::ResourceHandler::Open(CefRefPtr, bool& handle_request, CefRefPtr) { handle_request = true; @@ -82,103 +65,3 @@ void Browser::ResourceHandler::finish() { this->file_manager = nullptr; } } - -Browser::DefaultURLHandler::DefaultURLHandler(CefRefPtr request): urlrequest_complete(false), headers_checked(false), urlrequest_callback(nullptr), cursor(0) { - this->url_request = CefURLRequest::Create(request, this, nullptr); -} - -CefResourceRequestHandler::ReturnValue Browser::DefaultURLHandler::OnBeforeResourceLoad(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, CefRefPtr callback) { - // use CefResourceRequestHandler::OnBeforeResourceLoad to stall asynchronously on the IO thread - // until the request completes, if it hasn't already - if (urlrequest_complete) { - return RV_CONTINUE; - } else { - this->urlrequest_callback = callback; - return RV_CONTINUE_ASYNC; - } -} - -CefRefPtr Browser::DefaultURLHandler::GetResourceHandler(CefRefPtr browser, CefRefPtr frame, CefRefPtr request) { - return this; -} - -bool Browser::DefaultURLHandler::Open(CefRefPtr request, bool& handle_request, CefRefPtr callback) { - handle_request = true; - return true; -} - -void Browser::DefaultURLHandler::GetResponseHeaders(CefRefPtr response, int64_t& response_length, CefString& redirectUrl) { - CefRefPtr url_response = this->url_request->GetResponse(); - CefResponse::HeaderMap headers; - url_response->GetHeaderMap(headers); - response->SetHeaderMap(headers); - response->SetStatus(url_response->GetStatus()); - response->SetStatusText(url_response->GetStatusText()); - response->SetMimeType(url_response->GetMimeType()); - response->SetCharset(url_response->GetCharset()); - response->SetHeaderByName("Access-Control-Allow-Origin", "*", true); - response_length = GetContentLength(url_response); -} - -bool Browser::DefaultURLHandler::Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr callback) { - if (this->cursor == this->data.size()) { - // "To indicate response completion set |bytes_read| to 0 and return false." - bytes_read = 0; - return false; - } - if (this->cursor + bytes_to_read <= this->data.size()) { - // requested read is entirely in bounds - bytes_read = bytes_to_read; - memcpy(data_out, &this->data[this->cursor], bytes_read); - this->cursor += bytes_to_read; - } else { - // read only to end of string - bytes_read = this->data.size() - this->cursor; - memcpy(data_out, &this->data[this->cursor], bytes_read); - this->cursor = this->data.size(); - } - return true; -} - -bool Browser::DefaultURLHandler::Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr callback) { - if (this->cursor + bytes_to_skip <= this->data.size()) { - // skip in bounds - bytes_skipped = bytes_to_skip; - this->cursor += bytes_to_skip; - } else { - // skip to end of string - bytes_skipped = this->data.size() - this->cursor; - this->cursor = this->data.size(); - } - return true; -} - -void Browser::DefaultURLHandler::Cancel() { - this->cursor = this->data.size(); -} - -void Browser::DefaultURLHandler::OnRequestComplete(CefRefPtr request) { - this->urlrequest_complete = true; - if (this->urlrequest_callback) { - this->urlrequest_callback->Continue(); - } -} - -void Browser::DefaultURLHandler::OnUploadProgress(CefRefPtr request, int64_t current, int64_t total) {} -void Browser::DefaultURLHandler::OnDownloadProgress(CefRefPtr request, int64_t current, int64_t total) {} - -void Browser::DefaultURLHandler::OnDownloadData(CefRefPtr request, const void* data, size_t data_length) { - CefRefPtr response = request->GetResponse(); - if (!this->headers_checked && response) { - const int64_t content_length = GetContentLength(response); - if (content_length != -1) this->data.reserve(content_length); - this->headers_checked = true; - } - size_t write_offset = this->data.size(); - this->data.resize(write_offset + data_length); - memcpy(this->data.data() + write_offset, data, data_length); -} - -bool Browser::DefaultURLHandler::GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr callback) { - return false; -} diff --git a/src/browser/resource_handler.hxx b/src/browser/resource_handler.hxx index 89c6508..5a39c4b 100644 --- a/src/browser/resource_handler.hxx +++ b/src/browser/resource_handler.hxx @@ -5,7 +5,6 @@ #include "include/cef_base.h" #include "include/cef_resource_request_handler.h" -#include "include/cef_urlrequest.h" #include namespace Browser { @@ -56,38 +55,5 @@ namespace Browser { DISALLOW_COPY_AND_ASSIGN(ResourceHandler); }; - /// Struct for bridging a CefURLRequestClient to a CefResourceHandler - /// https://github.com/chromiumembedded/cef/blob/5735/include/cef_resource_request_handler.h - /// https://github.com/chromiumembedded/cef/blob/5735/include/cef_resource_handler.h - /// https://github.com/chromiumembedded/cef/blob/5735/include/cef_urlrequest.h#L137 - struct DefaultURLHandler: public CefResourceRequestHandler, CefResourceHandler, CefURLRequestClient { - DefaultURLHandler(CefRefPtr); - - CefResourceRequestHandler::ReturnValue OnBeforeResourceLoad(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, CefRefPtr callback) override; - CefRefPtr GetResourceHandler(CefRefPtr browser, CefRefPtr frame, CefRefPtr request) override; - - bool Open(CefRefPtr request, bool& handle_request, CefRefPtr callback) override; - void GetResponseHeaders(CefRefPtr response, int64_t& response_length, CefString& redirectUrl) override; - bool Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr callback) override; - bool Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr callback) override; - void Cancel() override; - - void OnRequestComplete(CefRefPtr request) override; - void OnUploadProgress(CefRefPtr request, int64_t current, int64_t total) override; - void OnDownloadProgress(CefRefPtr request, int64_t current, int64_t total) override; - void OnDownloadData(CefRefPtr request, const void* data, size_t data_length) override; - bool GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr callback) override; - - private: - CefRefPtr url_request; - CefRefPtr urlrequest_callback; - bool urlrequest_complete; - bool headers_checked; - std::vector data; - size_t cursor; - IMPLEMENT_REFCOUNTING(DefaultURLHandler); - DISALLOW_COPY_AND_ASSIGN(DefaultURLHandler); - }; - #endif } diff --git a/src/browser/window_launcher.cxx b/src/browser/window_launcher.cxx index 6d30706..05a2203 100644 --- a/src/browser/window_launcher.cxx +++ b/src/browser/window_launcher.cxx @@ -454,18 +454,7 @@ CefRefPtr Browser::Launcher::GetResourceRequestHandle } } - if (!browser->IsSame(this->browser) || !frame->IsMain()) { - return nullptr; - } - - // default way to handle web requests from the main window is to make a CefURLRequest that's not subject to CORS safety - disable_default_handling = true; - CefRefPtr new_request = CefRequest::Create(); - CefRequest::HeaderMap headers; - request->GetHeaderMap(headers); // doesn't include Referer header - headers.erase("Origin"); - new_request->Set(request->GetURL(), request->GetMethod(), request->GetPostData(), headers); - return new DefaultURLHandler(new_request); + return nullptr; } void Browser::Launcher::OnBrowserDestroyed(CefRefPtr view, CefRefPtr browser) { @@ -555,26 +544,6 @@ void Browser::Launcher::Refresh() const { this->browser->GetMainFrame()->LoadURL(this->BuildURL()); } -void Browser::Launcher::ParseQuery(std::string_view query, std::function callback) { - size_t pos = 0; - while (true) { - const size_t next_and = query.find('&', pos); - const size_t next_eq = query.find('=', pos); - if (next_eq == std::string_view::npos) break; - else if (next_and != std::string_view::npos && next_eq > next_and) { - pos = next_and + 1; - continue; - } - const bool is_last = next_and == std::string_view::npos; - const auto end = is_last ? query.end() : query.begin() + next_and; - const std::string_view key(query.begin() + pos, query.begin() + next_eq); - const std::string_view val(query.begin() + next_eq + 1, end); - callback(key, val); - if (is_last) break; - pos = next_and + 1; - } -} - CefRefPtr SaveFileFromPost(CefRefPtr request, const std::filesystem::path::value_type* path) { CefRefPtr post_data = request->GetPostData(); if (post_data->GetElementCount() != 1) { diff --git a/src/browser/window_launcher.hxx b/src/browser/window_launcher.hxx index 65f3717..f16a98a 100644 --- a/src/browser/window_launcher.hxx +++ b/src/browser/window_launcher.hxx @@ -4,10 +4,7 @@ #include "../browser.hxx" #include "../file_manager.hxx" -#include "include/cef_parser.h" - #include -#include namespace Browser { struct Launcher: public Window { @@ -40,9 +37,6 @@ namespace Browser { /// inserting their contents into the query params CefString BuildURL() const; - /// Goes through all the key-value pairs in the given query string and calls the callback for each one. - void ParseQuery(std::string_view query, std::function callback); - /* Functions called by GetResourceRequestHandler. The result will be returned immediately and must not be null. The request and URL query string are provided for parsing. @@ -82,23 +76,4 @@ namespace Browser { }; } -#if defined(_WIN32) -#define PQTOSTRING ToWString -#else -#define PQTOSTRING ToString -#endif - -#define PQCHECK(KEY) \ -if (key == #KEY) { \ - has_##KEY = true; \ - KEY = CefURIDecode(std::string(val), true, (cef_uri_unescape_rule_t)(UU_SPACES | UU_PATH_SEPARATORS | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | UU_REPLACE_PLUS_WITH_SPACE)).PQTOSTRING(); \ - return; \ -} - -#define PQBOOL(KEY) \ -if (key == #KEY) { \ - KEY = (val.size() > 0 && val != "0"); \ - return; \ -} - #endif diff --git a/src/browser/window_launcher_posix.cxx b/src/browser/window_launcher_posix.cxx index 4d425bb..26e1348 100644 --- a/src/browser/window_launcher_posix.cxx +++ b/src/browser/window_launcher_posix.cxx @@ -1,11 +1,14 @@ #include "window_launcher.hxx" #include "resource_handler.hxx" +#include "include/cef_parser.h" + #include #include #include #include #include +#include #include // see #34 for why this function exists and why it can't be run between fork-exec or just run `env`. @@ -38,6 +41,28 @@ bool FindJava(const char* java_home, std::string& out) { return false; } +void ParseQuery(std::string_view query, std::function callback) { + size_t pos = 0; + while (true) { + const size_t next_and = query.find('&', pos); + const size_t next_eq = query.find('=', pos); + if (next_eq == std::string_view::npos) break; + else if (next_and != std::string_view::npos && next_eq > next_and) { + pos = next_and + 1; + continue; + } + const bool is_last = next_and == std::string_view::npos; + const auto end = is_last ? query.end() : query.begin() + next_and; + const std::string_view key(query.begin() + pos, query.begin() + next_eq); + const std::string_view val(query.begin() + next_eq + 1, end); + callback(key, val); + if (is_last) break; + pos = next_and + 1; + } +} +const cef_uri_unescape_rule_t pqrule = (cef_uri_unescape_rule_t)(UU_SPACES | UU_PATH_SEPARATORS | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | UU_REPLACE_PLUS_WITH_SPACE); +#define PQCHECK(KEY) if (key == #KEY) { has_##KEY = true; KEY = CefURIDecode(std::string(val), true, pqrule).ToString(); return; } + CefRefPtr Browser::Launcher::LaunchRs3Deb(CefRefPtr request, std::string_view query) { /* strings that I don't want to be searchable, which also need to be mutable for passing to env functions */ // PULSE_PROP_OVERRIDE= @@ -77,14 +102,18 @@ CefRefPtr Browser::Launcher::LaunchRs3Deb(CefRefPtrParseQuery(query, [&](const std::string_view& key, const std::string_view& val) { + ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) { PQCHECK(hash) PQCHECK(config_uri) PQCHECK(jx_session_id) PQCHECK(jx_character_id) PQCHECK(jx_display_name) + #if defined(BOLT_PLUGINS) - PQBOOL(plugin_loader) + // no reason to URIDecode this + if (key == "plugin_loader" && val == "1") { + plugin_loader = true; + } #endif }); @@ -315,7 +344,7 @@ CefRefPtr Browser::Launcher::LaunchRuneliteJar(CefRef bool has_jx_character_id = false; std::string jx_display_name; bool has_jx_display_name = false; - this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) { + ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) { PQCHECK(rl_path) PQCHECK(id) PQCHECK(jx_session_id) @@ -472,7 +501,7 @@ CefRefPtr Browser::Launcher::LaunchHdosJar(CefRefPtr< bool has_jx_character_id = false; std::string jx_display_name; bool has_jx_display_name = false; - this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) { + ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) { PQCHECK(version) PQCHECK(jx_session_id) PQCHECK(jx_character_id) diff --git a/src/browser/window_launcher_win.cxx b/src/browser/window_launcher_win.cxx index 47bdffe..66bd903 100644 --- a/src/browser/window_launcher_win.cxx +++ b/src/browser/window_launcher_win.cxx @@ -1,7 +1,6 @@ #include "window_launcher.hxx" #include "resource_handler.hxx" -#include #include CefRefPtr Browser::Launcher::LaunchRs3Deb(CefRefPtr request, std::string_view query) { @@ -10,144 +9,9 @@ CefRefPtr Browser::Launcher::LaunchRs3Deb(CefRefPtr Browser::Launcher::LaunchRs3Exe(CefRefPtr request, std::string_view query) { - const CefRefPtr post_data = request->GetPostData(); - - // parse query - std::wstring hash; - bool has_hash = false; - std::wstring config_uri; - bool has_config_uri = false; - std::wstring jx_session_id; - bool has_jx_session_id = false; - std::wstring jx_character_id; - bool has_jx_character_id = false; - std::wstring jx_display_name; - bool has_jx_display_name = false; -#if defined(BOLT_PLUGINS) - bool plugin_loader = false; -#endif - this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) { - PQCHECK(hash) - PQCHECK(config_uri) - PQCHECK(jx_session_id) - PQCHECK(jx_character_id) - PQCHECK(jx_display_name) -#if defined(BOLT_PLUGINS) - PQBOOL(plugin_loader) -#endif - }); - - // if there was a "hash" in the query string, we need to save the new game exe and the new hash - if (has_hash) { - if (post_data == nullptr || post_data->GetElementCount() != 1) { - // hash param must be accompanied by POST data containing the file it's a hash of, - // so hash but no POST is a bad request - const char* data = "Bad Request"; - return new ResourceHandler(reinterpret_cast(data), strlen(data), 400, "text/plain"); - } - std::ofstream file(this->rs3_exe_path, std::ios::out | std::ios::binary); - if (file.fail()) { - const char* data = "Failed to save executable; if the game is already running, close it and try again\n"; - return new Browser::ResourceHandler(reinterpret_cast(data), strlen(data), 500, "text/plain"); - } - CefPostData::ElementVector vec; - post_data->GetElements(vec); - size_t exe_size = vec[0]->GetBytesCount(); - unsigned char* exe = new unsigned char[exe_size]; - vec[0]->GetBytes(exe_size, exe); - file.write((const char*)exe, exe_size); - file.close(); - delete[] exe; - } - - // create the command line for the new process - std::wstring command_line = std::wstring(L"\"") + this->rs3_exe_path.wstring() + L"\""; - if (has_config_uri) { - command_line += L" --configURI \""; - command_line += config_uri; - command_line += L"\""; - } - - // create the environment block for the new process - std::wstring session_key = L"JX_SESSION_ID="; - std::wstring character_key = L"JX_CHARACTER_ID="; - std::wstring name_key = L"JX_DISPLAY_NAME="; - LPWCH env = GetEnvironmentStringsW(); - size_t env_size = 0; - while (env[env_size] != '\0') { - while (env[env_size] != '\0') env_size += 1; - env_size += 1; - } - const size_t current_process_env_size = env_size; - if (has_jx_session_id) env_size += session_key.size() + jx_session_id.size() + 1; - if (has_jx_character_id) env_size += character_key.size() + jx_character_id.size() + 1; - if (has_jx_display_name) env_size += name_key.size() + jx_display_name.size() + 1; - wchar_t* new_env = new wchar_t[env_size + 1]; - memcpy(&new_env[0], env, current_process_env_size * sizeof(*env)); - FreeEnvironmentStringsW(env); - wchar_t* cursor = &new_env[current_process_env_size]; - if (has_jx_session_id) { - memcpy(cursor, &session_key[0], session_key.size() * sizeof(session_key[0])); - cursor += session_key.size(); - memcpy(cursor, &jx_session_id[0], jx_session_id.size() * sizeof(jx_session_id[0])); - cursor += jx_session_id.size(); - *cursor = '\0'; - cursor += 1; - } - if (has_jx_character_id) { - memcpy(cursor, &character_key[0], character_key.size() * sizeof(character_key[0])); - cursor += character_key.size(); - memcpy(cursor, &jx_character_id[0], jx_character_id.size() * sizeof(jx_character_id[0])); - cursor += jx_character_id.size(); - *cursor = '\0'; - cursor += 1; - } - if (has_jx_display_name) { - memcpy(cursor, &name_key[0], name_key.size() * sizeof(name_key[0])); - cursor += name_key.size(); - memcpy(cursor, &jx_display_name[0], jx_display_name.size() * sizeof(jx_display_name[0])); - cursor += jx_display_name.size(); - *cursor = '\0'; - cursor += 1; - } - *cursor = '\0'; - - PROCESS_INFORMATION pi; - STARTUPINFOW si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - if (!CreateProcessW( - NULL, - &command_line[0], - NULL, - NULL, - false, - CREATE_UNICODE_ENVIRONMENT, // CREATE_SUSPENDED goes here - new_env, - NULL, - &si, - &pi - )) { - delete[] new_env; - const DWORD error = GetLastError(); - const std::string error_message = "CreateProcess failed with error " + std::to_string(error) + "\n"; - return new ResourceHandler(error_message, 500, "text/plain"); - } - delete[] new_env; - - if (has_hash) { - std::wofstream file(this->rs3_exe_hash_path, std::ios::out | std::ios::binary); - if (file.fail()) { - const char* data = "OK, but unable to save hash file\n"; - return new Browser::ResourceHandler(reinterpret_cast(data), strlen(data), 200, "text/plain"); - } - file << hash; - file.close(); - } - - const char* data = "OK\n"; - return new ResourceHandler(reinterpret_cast(data), strlen(data), 200, "text/plain"); + // TODO + const char* data = ".exe is not supported on this platform\n"; + return new ResourceHandler(reinterpret_cast(data), strlen(data), 400, "text/plain"); } CefRefPtr Browser::Launcher::LaunchRs3App(CefRefPtr request, std::string_view query) { diff --git a/src/main.cxx b/src/main.cxx index 95c5971..baa18b2 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -135,8 +135,31 @@ void BoltFailToObtainLockfile(std::filesystem::path tempdir) { #if defined(__linux__) int main(int argc, char* argv[]) { - CefMainArgs main_args(argc, argv); + // Provide CEF with command-line arguments + // Add a flag to disable web security, because a certain company's API endpoints don't have correct + // access control settings; remove this setting if they ever get their stuff together + // Also add a flag to disable GPUCache being saved on disk because it just breaks sometimes? + const char* arg1 = "--disable-web-security"; + const char* arg2 = "--disable-gpu-shader-disk-cache"; + const size_t arg1_len = strlen(arg1); + const size_t arg2_len = strlen(arg2); + char* arg1_ = new char[arg1_len + 1]; + char* arg2_ = new char[arg2_len + 1]; + memcpy(arg1_, arg1, arg1_len); + memcpy(arg2_, arg2, arg2_len); + arg1_[arg1_len] = '\0'; + arg2_[arg2_len] = '\0'; + char** argv_ = new char*[argc + 2]; + memcpy(argv_, argv, argc * sizeof(char*)); + argv_[argc] = arg1_; + argv_[argc + 1] = arg2_; + + CefMainArgs main_args(argc + 2, argv_); int ret = BoltRunAnyProcess(main_args); + + delete[] argv_; + delete[] arg2_; + delete[] arg1_; return ret; } @@ -237,9 +260,15 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t* lpCmdLine, i fmt::print("Exiting with error: CommandLineToArgvW failed\n"); return 1; } + const wchar_t* const arg = L"--disable-web-security"; const wchar_t* subp_arg = L"--type="; + bool has_arg = false; bool is_subprocess = false; for(size_t i = 0; i < argc; i += 1) { + // check if arg is --disable-web-security + if (wcsstr(argv[i], arg)) { + has_arg = true; + } // check if arg begins with --type= if (wcsncmp(argv[i], subp_arg, wcslen(subp_arg)) == 0) { is_subprocess = true; @@ -252,13 +281,24 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t* lpCmdLine, i int ret = BoltRunAnyProcess(CefMainArgs(hInstance)); CefShutdown(); return ret; - } else { + } else if (has_arg) { // CefApp struct - this implements handlers used by multiple processes Browser::App cef_app_; CefRefPtr cef_app = &cef_app_; int ret = BoltRunBrowserProcess(CefMainArgs(hInstance), cef_app); CefShutdown(); return ret; + } else { + wchar_t module_name[1024]; + GetModuleFileNameW(NULL, module_name, 1024); + std::wstring command_line(lpCmdLine); + command_line += std::wstring(L" "); + command_line += std::wstring(arg); + PROCESS_INFORMATION process_info; + STARTUPINFOW startup_info; + GetStartupInfoW(&startup_info); + CreateProcessW(module_name, command_line.data(), NULL, NULL, 0, 0, NULL, NULL, &startup_info, &process_info); + return 0; } }