From 6b09588fb9f4a9fed9f8de16d9a270b45ba3764d Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Thu, 29 Aug 2024 13:52:41 -0500 Subject: [PATCH 1/4] improvements to the login and register pages This update adds to the instance picker instances for the user to select from, along with some documentation for instance owners on how to add their own instance to the picker --- .dist/login.js | 125 ++++++++++++++++++++++++++++++----------- InstanceInfo.md | 35 ++++++++++++ webpage/instances.json | 14 +++++ webpage/login.html | 3 +- webpage/login.ts | 121 ++++++++++++++++++++++++++++----------- webpage/register.html | 3 +- 6 files changed, 232 insertions(+), 69 deletions(-) create mode 100644 InstanceInfo.md create mode 100644 webpage/instances.json diff --git a/.dist/login.js b/.dist/login.js index f287be6..5bd3f6e 100644 --- a/.dist/login.js +++ b/.dist/login.js @@ -154,7 +154,30 @@ function adduser(user) { const instancein = document.getElementById("instancein"); let timeout; let instanceinfo; +const stringURLMap = new Map(); +const stringURLsMap = new Map(); async function getapiurls(str) { + if (!URL.canParse(str)) { + const val = stringURLMap.get(str); + if (val) { + str = val; + } + else { + const val = stringURLsMap.get(str); + if (val) { + const responce = await fetch(val.api + val.api.endsWith("/") ? "" : "/" + "ping"); + if (responce.ok) { + if (val.login) { + return val; + } + else { + val.login = val.api; + return val; + } + } + } + } + } if (str[str.length - 1] !== "/") { str += "/"; } @@ -178,6 +201,19 @@ async function getapiurls(str) { }; } catch { + const val = stringURLsMap.get(str); + if (val) { + const responce = await fetch(val.api + val.api.endsWith("/") ? "" : "/" + "ping"); + if (responce.ok) { + if (val.login) { + return val; + } + else { + val.login = val.api; + return val; + } + } + } return false; } } @@ -185,16 +221,22 @@ async function checkInstance(e) { const verify = document.getElementById("verify"); try { verify.textContent = "Checking Instance"; - const instanceinfo = await setInstance(instancein.value); - localStorage.setItem("instanceinfo", JSON.stringify(instanceinfo)); - verify.textContent = "Instance is all good"; - if (checkInstance["alt"]) { - checkInstance["alt"](); + const instanceinfo = await getapiurls(instancein.value); + if (instanceinfo) { + instanceinfo.value = instancein.value; + localStorage.setItem("instanceinfo", JSON.stringify(instanceinfo)); + verify.textContent = "Instance is all good"; + if (checkInstance["alt"]) { + checkInstance["alt"](); + } + setTimeout(_ => { + console.log(verify.textContent); + verify.textContent = ""; + }, 3000); + } + else { + verify.textContent = "Invalid Instance, try again"; } - setTimeout(_ => { - console.log(verify.textContent); - verify.textContent = ""; - }, 3000); } catch (e) { console.log("catch"); @@ -210,7 +252,13 @@ if (instancein) { timeout = setTimeout(checkInstance, 1000); }); if (localStorage.getItem("instanceinfo")) { - instancein.value = JSON.parse(localStorage.getItem("instanceinfo")).wellknown; + const json = JSON.parse(localStorage.getItem("instanceinfo")); + if (json.value) { + instancein.value = json.value; + } + else { + instancein.value = json.wellknown; + } } else { checkInstance("https://spacebar.chat/"); @@ -316,29 +364,6 @@ async function login(username, password, captcha) { } ; } -async function setInstance(url) { - url = new URL(url); - async function attempt(aurl) { - const info = await fetch(`${aurl.toString()}${aurl.pathname.includes("api") ? "" : "api"}/policies/instance/domains`) - .then((x) => x.json()); - return { - api: info.apiEndpoint, - gateway: info.gateway, - cdn: info.cdn, - wellknown: url, - login: aurl.toString() - }; - } - try { - return await attempt(url); - } - catch (e) { - } - const wellKnown = await fetch(`${url.origin}/.well-known/spacebar`) - .then((x) => x.json()) - .then((x) => new URL(x.api)); - return await attempt(wellKnown); -} async function check(e) { e.preventDefault(); let h = await login(e.srcElement[1].value, e.srcElement[2].value, e.srcElement[3].value); @@ -387,3 +412,37 @@ if (switchurl) { export { checkInstance }; trimswitcher(); export { mobile, getBulkUsers, getBulkInfo, setTheme, Specialuser, getapiurls, adduser }; +const datalist = document.getElementById("instances"); +console.warn(datalist); +if (datalist) { + fetch("/instances.json").then(_ => _.json()).then((json) => { + console.warn(json); + if (instancein && instancein.value === "") { + instancein.value = json[0].name; + setTimeout(checkInstance, 10); + } + for (const instance of json) { + const option = document.createElement("option"); + option.value = instance.name; + if (instance.URL) { + stringURLMap.set(option.value, instance.URL); + if (instance.URLs) { + stringURLsMap.set(instance.URL, instance.URLs); + } + } + else if (instance.URLs) { + stringURLsMap.set(option.value, instance.URLs); + } + else { + option.disabled = true; + } + if (instance.description) { + option.label = instance.description; + } + else { + option.label = instance.name; + } + datalist.append(option); + } + }); +} diff --git a/InstanceInfo.md b/InstanceInfo.md new file mode 100644 index 0000000..4b285a7 --- /dev/null +++ b/InstanceInfo.md @@ -0,0 +1,35 @@ +# How to add your instance to Jank Client +inside of webpage you'll see a file called `instances.json` in that file you'll need to add your instance and its information in the following format if you want your instance to be a part of the drop down. +```json +{ + "name":, + "description"?:, + "descriptionLong"?:, + "src"?:, + "URL"?:, + "URLs"?:{ + "wellknown":, + "api":, + "cdn":, + "gateway":, + "login"?: + }, + "contactInfo"?:{ + "dicord"?:, + "github"?:, + "email"?:, + "spacebar":?:, + "matrix"?:, + "mastodon"?: + } +} +``` +anything with a `?` in-front of its `:` are optional, though you must either include `"URL"` or `"URLs"`, but you may include both, though the client will most likely ignore `"URLs"` in favor of `"URL"`, though it may use `"URLs"` as a fallback if `"URL"` does not resolve, do not rely on this behavior. +Some of these values may not be used right now, though they will likely be used in the future, so feel free to fill out what you like, though the more you fill out the more information we can give the users about your instance in the future. +# Questions +## Do I have to do this to let Jank Client connect to my server? +No, you may choose to not do this, this just makes it easier for people using Jank Client to find and use your instance as it's in the dropdown menu for instances, though the user may enter any instance they please. +## If my instance isn't spacebar is that allowed to be entered? +If it's spacebar compatable, yes it may be entered, though if there are too many incompatablities, it may not be included, or may need a warning of sorts. +## I'm hosting my own instance of spacebar and would like to change the defualt instance on my instance of Jank Client to my own instance. +Just change the first entry in the list to your own, and it should connect without issue. diff --git a/webpage/instances.json b/webpage/instances.json new file mode 100644 index 0000000..4150220 --- /dev/null +++ b/webpage/instances.json @@ -0,0 +1,14 @@ +[ + { + "name":"Spacebar Official", + "description":"The official instance of spacebar!", + "src":"https://cdn.old.server.spacebar.chat/icons/1006649183970562092/fb5218b5dfad5e1c7b452c17ddb1701e.png", + "URL":"https://spacebar.chat" + }, + { + "name":"Vanilla Games", + "description":"The spacebar instance for Vanilla games", + "src":"https://vanillaminigames.net/img/favicon.ico", + "URL":"https://vanillaminigames.net/" + } +] diff --git a/webpage/login.html b/webpage/login.html index 4d23cd9..9b0dd0a 100644 --- a/webpage/login.html +++ b/webpage/login.html @@ -15,7 +15,7 @@

-

+




@@ -31,5 +31,6 @@
Don't have an account? + diff --git a/webpage/login.ts b/webpage/login.ts index 807cbab..1f29885 100644 --- a/webpage/login.ts +++ b/webpage/login.ts @@ -153,7 +153,30 @@ function adduser(user){ const instancein=document.getElementById("instancein") as HTMLInputElement; let timeout; let instanceinfo; +const stringURLMap=new Map(); + +const stringURLsMap=new Map(); async function getapiurls(str:string):Promise<{api:string,cdn:string,gateway:string,wellknown:string,login:string}|false>{ + if(!URL.canParse(str)){ + const val=stringURLMap.get(str); + if(val){ + str=val; + }else{ + const val=stringURLsMap.get(str) + if(val){ + const responce=await fetch(val.api+val.api.endsWith("/")?"":"/"+"ping"); + if(responce.ok){ + if(val.login){ + return val as {wellknown:string,api:string,cdn:string,gateway:string,login:string}; + }else{ + val.login=val.api; + return val as {wellknown:string,api:string,cdn:string,gateway:string,login:string}; + } + + } + } + } + } if(str[str.length-1]!=="/"){ str+="/" } @@ -176,6 +199,19 @@ async function getapiurls(str:string):Promise<{api:string,cdn:string,gateway:str login:url.toString() }; }catch{ + const val=stringURLsMap.get(str) + if(val){ + const responce=await fetch(val.api+val.api.endsWith("/")?"":"/"+"ping"); + if(responce.ok){ + if(val.login){ + return val as {wellknown:string,api:string,cdn:string,gateway:string,login:string}; + }else{ + val.login=val.api; + return val as {wellknown:string,api:string,cdn:string,gateway:string,login:string}; + } + + } + } return false; } @@ -184,15 +220,19 @@ async function checkInstance(e:string){ const verify=document.getElementById("verify"); try{ verify.textContent="Checking Instance"; - const instanceinfo=await setInstance((instancein as HTMLInputElement).value); - localStorage.setItem("instanceinfo",JSON.stringify(instanceinfo)); - verify.textContent="Instance is all good" - if(checkInstance["alt"]){checkInstance["alt"]();} - setTimeout(_=>{ - console.log(verify.textContent) - verify.textContent=""; - },3000); - + const instanceinfo=await getapiurls((instancein as HTMLInputElement).value) as {wellknown:string,api:string,cdn:string,gateway:string,login:string, value:string}; + if(instanceinfo){ + instanceinfo.value=(instancein as HTMLInputElement).value; + localStorage.setItem("instanceinfo",JSON.stringify(instanceinfo)); + verify.textContent="Instance is all good" + if(checkInstance["alt"]){checkInstance["alt"]();} + setTimeout(_=>{ + console.log(verify.textContent) + verify.textContent=""; + },3000); + }else{ + verify.textContent="Invalid Instance, try again" + } }catch(e){ console.log("catch") verify.textContent="Invalid Instance, try again" @@ -207,7 +247,12 @@ if(instancein){ timeout=setTimeout(checkInstance,1000); }); if(localStorage.getItem("instanceinfo")){ - (instancein as HTMLInputElement).value=JSON.parse(localStorage.getItem("instanceinfo")).wellknown + const json=JSON.parse(localStorage.getItem("instanceinfo")); + if(json.value){ + (instancein as HTMLInputElement).value=json.value + }else{ + (instancein as HTMLInputElement).value=json.wellknown + } }else{ checkInstance("https://spacebar.chat/"); } @@ -306,30 +351,6 @@ async function login(username:string, password:string, captcha:string){ console.error('Error:', error); }; } -async function setInstance(url){ - url=new URL(url); - async function attempt(aurl){ - const info=await fetch(`${aurl.toString()}${aurl.pathname.includes("api") ? "" : "api"}/policies/instance/domains`) - .then((x) => x.json()); - return { - api: info.apiEndpoint, - gateway: info.gateway, - cdn: info.cdn, - wellknown: url, - login:aurl.toString() - } - } - try{ - return await attempt(url); - }catch(e){ - - } - const wellKnown = await fetch(`${url.origin}/.well-known/spacebar`) - .then((x) => x.json()) - .then((x) => new URL(x.api)); - return await attempt(wellKnown); -} - async function check(e){ @@ -380,3 +401,35 @@ if(switchurl){ export {checkInstance}; trimswitcher(); export {mobile, getBulkUsers,getBulkInfo,setTheme,Specialuser,getapiurls,adduser} + +const datalist=document.getElementById("instances"); +console.warn(datalist); +if(datalist){ + fetch("/instances.json").then(_=>_.json()).then((json:{name:string,description?:string,src?:string,URL?:string,URLs:{wellknown:string,api:string,cdn:string,gateway:string,login?:string}}[])=>{ + console.warn(json); + if(instancein&&instancein.value===""){ + instancein.value=json[0].name; + setTimeout(checkInstance,10); + } + for(const instance of json){ + const option=document.createElement("option"); + option.value=instance.name; + if(instance.URL){ + stringURLMap.set(option.value,instance.URL); + if(instance.URLs){ + stringURLsMap.set(instance.URL,instance.URLs); + } + }else if(instance.URLs){ + stringURLsMap.set(option.value,instance.URLs); + }else{ + option.disabled=true; + } + if(instance.description){ + option.label=instance.description; + }else{ + option.label=instance.name; + } + datalist.append(option); + } + }) +} diff --git a/webpage/register.html b/webpage/register.html index efed961..601a431 100644 --- a/webpage/register.html +++ b/webpage/register.html @@ -16,7 +16,7 @@

- +

@@ -55,5 +55,6 @@ Already have an account?
+ From 75bb7d0a34171e516e630b7d8fa5024eba6ee2ab Mon Sep 17 00:00:00 2001 From: MathMan05 <73901602+MathMan05@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:53:26 -0500 Subject: [PATCH 2/4] Update InstanceInfo.md --- InstanceInfo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InstanceInfo.md b/InstanceInfo.md index 4b285a7..8c61894 100644 --- a/InstanceInfo.md +++ b/InstanceInfo.md @@ -1,6 +1,6 @@ # How to add your instance to Jank Client inside of webpage you'll see a file called `instances.json` in that file you'll need to add your instance and its information in the following format if you want your instance to be a part of the drop down. -```json +``` { "name":, "description"?:, From 31fe28cdabc8461fc3e88c3ccfa42a4eda09c217 Mon Sep 17 00:00:00 2001 From: MathMan05 <73901602+MathMan05@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:54:50 -0500 Subject: [PATCH 3/4] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b144b68..daad1fc 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Both [Bun](https://bun.sh) and [Node.js](https://nodejs.org) are supported, and To access Jank Client after starting, simply go to http://localhost:8080/login and either register a new account, or log in with your email and password. If there are any issues please report them either here, or to me dirrectly on spacebar +## Adding instances to the dropdown +Please see [this](https://github.com/MathMan05/JankClient/blob/main/InstanceInfo.md) for how to add an instance to the dropdown picker ## RoadMap You can view the current roadmap on https://github.com/users/MathMan05/projects/1. From 76249cc6ecbdcac6590219dd80e8b1d6ffd3f5e6 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Thu, 29 Aug 2024 14:58:05 -0500 Subject: [PATCH 4/4] Remove instance that didn't want to be listed --- webpage/instances.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/webpage/instances.json b/webpage/instances.json index 4150220..578c366 100644 --- a/webpage/instances.json +++ b/webpage/instances.json @@ -4,11 +4,5 @@ "description":"The official instance of spacebar!", "src":"https://cdn.old.server.spacebar.chat/icons/1006649183970562092/fb5218b5dfad5e1c7b452c17ddb1701e.png", "URL":"https://spacebar.chat" - }, - { - "name":"Vanilla Games", - "description":"The spacebar instance for Vanilla games", - "src":"https://vanillaminigames.net/img/favicon.ico", - "URL":"https://vanillaminigames.net/" } ]