added a home screen to jank client
This commit is contained in:
parent
04e3ac9955
commit
f2480130c1
8 changed files with 407 additions and 10 deletions
62
.dist/home.js
Normal file
62
.dist/home.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { mobile } from "./login.js";
|
||||
console.log(mobile);
|
||||
const serverbox = document.getElementById("instancebox");
|
||||
fetch("/instances.json").then(_ => _.json()).then((json) => {
|
||||
console.warn(json);
|
||||
for (const instance of json) {
|
||||
if (instance.display === false) {
|
||||
continue;
|
||||
}
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("flexltr", "instance");
|
||||
if (instance.image) {
|
||||
const img = document.createElement("img");
|
||||
img.src = instance.image;
|
||||
div.append(img);
|
||||
}
|
||||
const statbox = document.createElement("div");
|
||||
statbox.classList.add("flexttb");
|
||||
{
|
||||
const textbox = document.createElement("div");
|
||||
textbox.classList.add("flexttb", "instatancetextbox");
|
||||
const title = document.createElement("h2");
|
||||
title.innerText = instance.name;
|
||||
if (instance.online !== undefined) {
|
||||
const status = document.createElement("span");
|
||||
status.innerText = instance.online ? "Online" : "Offline";
|
||||
status.classList.add("instanceStatus");
|
||||
title.append(status);
|
||||
}
|
||||
textbox.append(title);
|
||||
if (instance.description || instance.descriptionLong) {
|
||||
const p = document.createElement("p");
|
||||
if (instance.descriptionLong) {
|
||||
p.innerText = instance.descriptionLong;
|
||||
}
|
||||
else {
|
||||
p.innerText = instance.description;
|
||||
}
|
||||
textbox.append(p);
|
||||
}
|
||||
statbox.append(textbox);
|
||||
}
|
||||
{
|
||||
const stats = document.createElement("div");
|
||||
stats.classList.add("flexltr");
|
||||
const span = document.createElement("span");
|
||||
span.innerText = `Uptime: All time: ${Math.floor(instance.uptime.alltime * 100)}% This week: ${Math.floor(instance.uptime.weektime * 100)}% Today: ${Math.floor(instance.uptime.daytime * 100)}%`;
|
||||
stats.append(span);
|
||||
statbox.append(stats);
|
||||
}
|
||||
div.append(statbox);
|
||||
div.onclick = _ => {
|
||||
if (instance.online) {
|
||||
window.location.href = "/register.html?instance=" + encodeURI(instance.name);
|
||||
}
|
||||
else {
|
||||
alert("Instance is offline, can't connect");
|
||||
}
|
||||
};
|
||||
serverbox.append(div);
|
||||
}
|
||||
});
|
|
@ -419,7 +419,6 @@ if (datalist) {
|
|||
console.warn(json);
|
||||
if (instancein && instancein.value === "") {
|
||||
instancein.value = json[0].name;
|
||||
setTimeout(checkInstance, 10);
|
||||
}
|
||||
for (const instance of json) {
|
||||
if (instance.display === false) {
|
||||
|
@ -447,5 +446,6 @@ if (datalist) {
|
|||
}
|
||||
datalist.append(option);
|
||||
}
|
||||
checkInstance("");
|
||||
});
|
||||
}
|
||||
|
|
16
index.js
16
index.js
|
@ -4,7 +4,8 @@ const compression = require('compression')
|
|||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const app = express();
|
||||
const instances=require("./webpage/instances.json")
|
||||
const instances=require("./webpage/instances.json");
|
||||
const stats=require("./stats.js");
|
||||
const instancenames=new Map();
|
||||
for(const instance of instances){
|
||||
instancenames.set(instance.name,instance);
|
||||
|
@ -12,7 +13,6 @@ for(const instance of instances){
|
|||
app.use(compression())
|
||||
fetch("https://raw.githubusercontent.com/spacebarchat/spacebarchat/master/instances/instances.json").then(_=>_.json()).then(json=>{
|
||||
for(const instance of json){
|
||||
console.log(instance);
|
||||
if(!instancenames.has(instance.name)){
|
||||
instances.push(instance);
|
||||
}else{
|
||||
|
@ -24,6 +24,7 @@ fetch("https://raw.githubusercontent.com/spacebarchat/spacebarchat/master/instan
|
|||
}
|
||||
}
|
||||
}
|
||||
stats.observe(instances)
|
||||
})
|
||||
|
||||
app.use("/getupdates",(req, res) => {
|
||||
|
@ -145,6 +146,10 @@ async function inviteres(req,res){
|
|||
app.use('/services/oembed', (req, res) => {
|
||||
inviteres(req, res);
|
||||
})
|
||||
app.use("/uptime",(req,res)=>{
|
||||
const uptime=stats.uptime[req.query.name];
|
||||
res.send(uptime);
|
||||
})
|
||||
app.use('/', async (req, res) => {
|
||||
const scheme = req.secure ? 'https' : 'http';
|
||||
const host=`${scheme}://${req.get("Host")}`;
|
||||
|
@ -156,13 +161,14 @@ app.use('/', async (req, res) => {
|
|||
}else{
|
||||
console.log(req);
|
||||
}
|
||||
|
||||
if(req.path==="/"){
|
||||
res.sendFile(`./webpage/home.html`, {root: __dirname});
|
||||
}
|
||||
if(debugging&&req.path.startsWith("/service.js")){
|
||||
res.send("dud");
|
||||
return;
|
||||
}
|
||||
if(req.path.startsWith("/instances.json")){
|
||||
console.log("grabbed")
|
||||
res.send(JSON.stringify(instances));
|
||||
return;
|
||||
}
|
||||
|
@ -189,3 +195,5 @@ app.use('/', async (req, res) => {
|
|||
const PORT = process.env.PORT || +process.argv[1] || 8080;
|
||||
app.listen(PORT, () => {});
|
||||
console.log("this ran :P");
|
||||
|
||||
exports.getapiurls=getapiurls;
|
||||
|
|
142
stats.js
Normal file
142
stats.js
Normal file
|
@ -0,0 +1,142 @@
|
|||
const index = require('./index.js');
|
||||
const fs=require("fs");
|
||||
let uptimeObject={};
|
||||
if(fs.existsSync("./uptime.json")){
|
||||
try{
|
||||
uptimeObject=JSON.parse(fs.readFileSync('./uptime.json', 'utf8'));
|
||||
}catch{
|
||||
uptimeObject={};
|
||||
}
|
||||
}
|
||||
|
||||
async function observe(instances){
|
||||
const active=new Set();
|
||||
async function resolveinstance(instance){
|
||||
calcStats(instance);
|
||||
let api;
|
||||
if(instance.urls){
|
||||
api=instance.urls.api;
|
||||
}else if(instance.url){
|
||||
const urls=await index.getapiurls(instance.url);
|
||||
if(urls){
|
||||
api=urls.api;
|
||||
}
|
||||
}
|
||||
if(!api||api===""){
|
||||
|
||||
setSatus(instance,false);
|
||||
console.warn(instance.name+" does not resolve api URL");
|
||||
setTimeout(_=>{resolveinstance(instance)},1000*60*30,);
|
||||
return
|
||||
}
|
||||
active.add(instance.name);
|
||||
api+=api.endsWith("/")?"":"/"
|
||||
function check(){
|
||||
fetch(api+"ping").then(_=>{
|
||||
setSatus(instance,_.ok);
|
||||
})
|
||||
}
|
||||
setTimeout(
|
||||
_=>{
|
||||
check();
|
||||
setInterval(_=>{
|
||||
check();
|
||||
},1000*60*30)
|
||||
},Math.random()*1000*60*10
|
||||
)
|
||||
}
|
||||
const promlist=[];
|
||||
for(const instance of instances){
|
||||
promlist.push(resolveinstance(instance));
|
||||
}
|
||||
await Promise.allSettled(promlist);
|
||||
for(const key of Object.keys(uptimeObject)){
|
||||
if(!active.has(key)){
|
||||
setSatus(key,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
function calcStats(instance){
|
||||
let obj=uptimeObject[instance.name];
|
||||
if(!obj) return;
|
||||
const day=Date.now()-1000*60*60*24;
|
||||
const week=Date.now()-1000*60*60*24*7;
|
||||
let alltime=-1;
|
||||
let totalTimePassed=0;
|
||||
let laststamp=0;
|
||||
let daytime=-1;
|
||||
let weektime=-1;
|
||||
let online=false;
|
||||
for(const thing of obj){
|
||||
const stamp=thing.time;
|
||||
if(alltime===-1){
|
||||
laststamp=stamp;
|
||||
alltime=0;
|
||||
}
|
||||
const timepassed=stamp-laststamp;
|
||||
totalTimePassed+=timepassed;
|
||||
alltime+=online*timepassed;
|
||||
if(stamp>week){
|
||||
if(weektime===-1){
|
||||
weektime=online*(stamp-week);
|
||||
}else{
|
||||
weektime+=online*timepassed;
|
||||
}
|
||||
if(stamp>day){
|
||||
if(daytime===-1){
|
||||
daytime=online*(stamp-day);
|
||||
}else{
|
||||
daytime+=online*timepassed;
|
||||
}
|
||||
}
|
||||
}
|
||||
online=thing.online;
|
||||
}
|
||||
instance.online=online;
|
||||
const timepassed=Date.now()-laststamp;
|
||||
totalTimePassed+=timepassed;
|
||||
daytime+=online*timepassed;
|
||||
weektime+=online*timepassed;
|
||||
alltime+=online*timepassed;
|
||||
alltime/=totalTimePassed;
|
||||
if(timepassed>1000*60*60*24){
|
||||
daytime/=1000*60*60*24;
|
||||
if(timepassed>1000*60*60*24*7){
|
||||
weektime/=1000*60*60*24*7;
|
||||
}else{
|
||||
weektime=alltime;
|
||||
}
|
||||
}else{
|
||||
weektime=alltime
|
||||
daytime=alltime;
|
||||
}
|
||||
instance.uptime={daytime,weektime,alltime}
|
||||
}
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {boolean} status
|
||||
*/
|
||||
function setSatus(instance,status){
|
||||
const name=instance.name;
|
||||
let obj=uptimeObject[name];
|
||||
let needSetting=false;
|
||||
if(!obj){
|
||||
obj=[];
|
||||
uptimeObject[name]=obj;
|
||||
needSetting=true;
|
||||
}else{
|
||||
if(obj[obj.length-1].online!==status){
|
||||
needSetting=true;
|
||||
}
|
||||
}
|
||||
if(needSetting){
|
||||
obj.push({time:Date.now(),online:status});
|
||||
updatejson();
|
||||
}
|
||||
calcStats(instance);
|
||||
}
|
||||
function updatejson(){
|
||||
fs.writeFile('./uptime.json',JSON.stringify(uptimeObject),_=>{});
|
||||
}
|
||||
exports.observe=observe;
|
||||
exports.uptime=uptimeObject;
|
48
webpage/home.html
Normal file
48
webpage/home.html
Normal file
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Jank Client</title>
|
||||
<meta content="Jank Client" property="og:title" />
|
||||
<meta content="A spacebar client that has DMs, replying and more" property="og:description" />
|
||||
<meta content="/logo.webp" property="og:image" />
|
||||
<meta content="#4b458c" data-react-helmet="true" name="theme-color" />
|
||||
<link href="/style.css" rel="stylesheet" type="text/css" />
|
||||
<link href="/themes.css" rel="stylesheet" type="text/css" id="lightcss"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="titleDiv">
|
||||
<img src="/logo.svg" width="40">
|
||||
<h1 id="pageTitle">Jank Client</h1>
|
||||
<a href="https://sb-jankclient.vanillaminigames.net/invite/USgYJo?instance=https%3A%2F%2Fspacebar.chat" class="TitleButtons"><h1>Spacebar Guild</h1></a>
|
||||
<a href="https://github.com/MathMan05/JankClient" class="TitleButtons"><h1>Github</h1></a>
|
||||
</div>
|
||||
<div class="flexttb">
|
||||
|
||||
<div class="flexttb pagehead"><h1>Welcome to Jank Client</h1></div>
|
||||
<div class="pagebox">
|
||||
<p>Jank Client is a spacebar compatible client seeking to be as good as it can be with many features including:</p>
|
||||
<ul>
|
||||
<li>Direct Messaging</li>
|
||||
<li>Reactions support</li>
|
||||
<li>Invites</li>
|
||||
<li>Account switching</li>
|
||||
<li>User settings</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pagebox">
|
||||
<h2>Spacebar compatible Instances:</h2>
|
||||
<div id="instancebox">
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagebox">
|
||||
<h2>Contribute to Jank Client</h2>
|
||||
<p>We always appreciate some help, wether that be in the form of bug reports, or code, or even just pointing out some typos.</p><br>
|
||||
</a><a href="https://github.com/MathMan05/JankClient" class="TitleButtons"><h1>Github</h1></a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/home.js" type="module" ></script>
|
||||
</html>
|
64
webpage/home.ts
Normal file
64
webpage/home.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import {mobile} from "./login.js";
|
||||
console.log(mobile);
|
||||
const serverbox=document.getElementById("instancebox") as HTMLDivElement;
|
||||
|
||||
fetch("/instances.json").then(_=>_.json()).then((json:{name:string,description?:string,descriptionLong?:string,image?:string,url?:string,display?:boolean,online?:boolean,
|
||||
uptime:{alltime:number,daytime:number,weektime:number},
|
||||
urls:{wellknown:string,api:string,cdn:string,gateway:string,login?:string}}[])=>{
|
||||
console.warn(json);
|
||||
for(const instance of json){
|
||||
if(instance.display===false){
|
||||
continue;
|
||||
}
|
||||
const div=document.createElement("div");
|
||||
div.classList.add("flexltr","instance");
|
||||
if(instance.image){
|
||||
const img=document.createElement("img");
|
||||
img.src=instance.image;
|
||||
div.append(img);
|
||||
}
|
||||
const statbox=document.createElement("div");
|
||||
statbox.classList.add("flexttb");
|
||||
|
||||
{
|
||||
const textbox=document.createElement("div");
|
||||
textbox.classList.add("flexttb","instatancetextbox");
|
||||
const title=document.createElement("h2");
|
||||
title.innerText=instance.name;
|
||||
if(instance.online!==undefined){
|
||||
const status=document.createElement("span");
|
||||
status.innerText=instance.online?"Online":"Offline";
|
||||
status.classList.add("instanceStatus");
|
||||
title.append(status);
|
||||
}
|
||||
textbox.append(title);
|
||||
if(instance.description||instance.descriptionLong){
|
||||
const p=document.createElement("p");
|
||||
if(instance.descriptionLong){
|
||||
p.innerText=instance.descriptionLong;
|
||||
}else{
|
||||
p.innerText=instance.description;
|
||||
}
|
||||
textbox.append(p);
|
||||
}
|
||||
statbox.append(textbox)
|
||||
}
|
||||
{
|
||||
const stats=document.createElement("div");
|
||||
stats.classList.add("flexltr");
|
||||
const span=document.createElement("span");
|
||||
span.innerText=`Uptime: All time: ${Math.floor(instance.uptime.alltime*100)}% This week: ${Math.floor(instance.uptime.weektime*100)}% Today: ${Math.floor(instance.uptime.daytime*100)}%`
|
||||
stats.append(span);
|
||||
statbox.append(stats);
|
||||
}
|
||||
div.append(statbox);
|
||||
div.onclick=_=>{
|
||||
if(instance.online){
|
||||
window.location.href="/register.html?instance="+encodeURI(instance.name);
|
||||
}else{
|
||||
alert("Instance is offline, can't connect");
|
||||
}
|
||||
}
|
||||
serverbox.append(div);
|
||||
}
|
||||
})
|
|
@ -409,7 +409,6 @@ if(datalist){
|
|||
console.warn(json);
|
||||
if(instancein&&instancein.value===""){
|
||||
instancein.value=json[0].name;
|
||||
setTimeout(checkInstance,10);
|
||||
}
|
||||
for(const instance of json){
|
||||
if(instance.display===false){
|
||||
|
@ -434,5 +433,6 @@ if(datalist){
|
|||
}
|
||||
datalist.append(option);
|
||||
}
|
||||
checkInstance("");
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1257,6 +1257,7 @@ span {
|
|||
/* padding-bottom: .1in; */
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.settingbuttons{
|
||||
padding-top:.075in;
|
||||
|
@ -1958,12 +1959,12 @@ form div{
|
|||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: .03in .15in;
|
||||
padding: .03in .1in;
|
||||
background: var(--profile-bg);
|
||||
border-bottom: solid var(--black);
|
||||
position: absolute;
|
||||
justify-content: center;
|
||||
}
|
||||
#TitleButtons{
|
||||
.TitleButtons{
|
||||
color:var(--primary-text);
|
||||
margin-left: .03in;
|
||||
padding: .05in;
|
||||
|
@ -1971,10 +1972,82 @@ form div{
|
|||
border:solid .03in var(--black);
|
||||
box-shadow: 0 0 .07in var(--shadow);
|
||||
transition: box-shadow .3s;
|
||||
display: block;
|
||||
width: fit-content;
|
||||
}
|
||||
#TitleButtons:hover{
|
||||
.TitleButtons:hover{
|
||||
box-shadow: 0 0 .01in var(--shadow);
|
||||
}
|
||||
#pageTitle{
|
||||
margin-right:.1in;
|
||||
}
|
||||
.pagehead{
|
||||
background: var(--channel-hover);
|
||||
height:1in;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: solid var(--black);
|
||||
justify-content: center;
|
||||
font-size: .25in;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.pagebox{
|
||||
padding: .06in;
|
||||
background: var(--channel-hover);
|
||||
margin: .1in;
|
||||
min-height:2in;
|
||||
border-radius:.1in;
|
||||
box-sizing: border-box;
|
||||
border: solid .04in black;
|
||||
border-left: solid .05in darkblue;
|
||||
box-shadow: .03in .04in .1in var(--black);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
#instancebox{
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: fit-content;
|
||||
}
|
||||
.instance{
|
||||
img{
|
||||
width:.6in;
|
||||
height:.6in;
|
||||
margin-right:.1in;
|
||||
border-radius:.2in;
|
||||
border:solid .03in var(--black);
|
||||
}
|
||||
h2{
|
||||
font-size:.25in;
|
||||
}
|
||||
flex-grow:0;
|
||||
width:4.8in;
|
||||
height: 1.6in;
|
||||
background:var(--button-bg);
|
||||
border-radius:.1in;
|
||||
padding:.06in;
|
||||
margin:.05in;
|
||||
border:solid .04in var(--black);
|
||||
box-shadow:0 0 .1in var(--shadow);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
cursor:pointer;
|
||||
user-select:none;
|
||||
}
|
||||
.instatancetextbox{
|
||||
background:var(--message-bg-hover);
|
||||
border-radius:.1in;
|
||||
padding:0.03in .05in;
|
||||
border:solid .03in var(--black);
|
||||
height: 1.2in;
|
||||
display:flex;
|
||||
justify-content: center;
|
||||
width:3.9in;
|
||||
margin-bottom:.1in;
|
||||
}
|
||||
.instanceStatus{
|
||||
font-size:.125in;
|
||||
font-weight:100;
|
||||
margin-left:.05in;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue