some reorginization

This commit is contained in:
MathMan05 2024-11-30 19:04:00 -06:00
parent e06b28742c
commit d94c20b275
17 changed files with 586 additions and 503 deletions

View file

@ -1,5 +1,3 @@
import{ getBulkInfo }from"./login.js";
class AVoice{
audioCtx: AudioContext;
info: { wave: string | Function; freq: number };
@ -72,10 +70,6 @@ class AVoice{
return(_t: number, _freq: number)=>{
return Math.random() * 2 - 1;
};
case"noise":
return(_t: number, _freq: number)=>{
return 0;
};
}
return new Function();
}
@ -183,14 +177,5 @@ class AVoice{
static get sounds(){
return["three", "zip", "square", "beep"];
}
static setNotificationSound(sound: string){
const userinfos = getBulkInfo();
userinfos.preferences.notisound = sound;
localStorage.setItem("userinfos", JSON.stringify(userinfos));
}
static getNotificationSound(){
const userinfos = getBulkInfo();
return userinfos.preferences.notisound;
}
}
export{ AVoice as AVoice };

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jank Audio</title>
<meta content="Jank Sound" property="og:title">
<meta content="A sound editor for jank clients sound format .jasf" 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">
<link href="/themes.css" rel="stylesheet" id="lightcss">
<style>body.no-theme{background:#16191b;}@media(prefers-color-scheme:light){body.no-theme{background:#9397bd;}}</style>
</head>
<body class="no-theme" style="overflow-y: scroll;">
<h1>Place holder text</h1>
</body>
<script src="/page.js" type="module"></script>
</html>

View file

View file

@ -1,6 +1,6 @@
"use strict";
import{ Message }from"./message.js";
import{ AVoice }from"./audio.js";
import{ AVoice }from"./audio/audio.js";
import{ Contextmenu }from"./contextmenu.js";
import{ Guild }from"./guild.js";
import{ Localuser }from"./localuser.js";
@ -1403,7 +1403,7 @@ class Channel extends SnowFlake{
);
}
notify(message: Message, deep = 0){
AVoice.noises(AVoice.getNotificationSound());
AVoice.noises(this.localuser.getNotificationSound());
if(!("Notification" in window)){
}else if(Notification.permission === "granted"){
let noticontent: string | undefined | null = message.content.textContent;

View file

@ -1,4 +1,4 @@
import{ iOS }from"./login.js";
import{ iOS }from"./utils/utils.js";
class Contextmenu<x, y>{
static currentmenu: HTMLElement | "";
name: string;

View file

@ -1,7 +1,7 @@
import{ Message }from"./message.js";
import{ MarkDown }from"./markdown.js";
import{ embedjson, invitejson }from"./jsontypes.js";
import{ getapiurls, getInstances }from"./login.js";
import{ getapiurls, getInstances }from"./utils/utils.js";
import{ Guild }from"./guild.js";
import { I18n } from "./i18n.js";
import { ImagesDisplay } from "./disimg.js";

View file

@ -2,6 +2,7 @@ import{ Contextmenu }from"./contextmenu.js";
import{ Guild }from"./guild.js";
import { emojijson } from "./jsontypes.js";
import{ Localuser }from"./localuser.js";
import { BinRead } from "./utils/binaryUtils.js";
//I need to recompile the emoji format for translation
class Emoji{
@ -64,51 +65,24 @@ class Emoji{
}
}
static decodeEmojiList(buffer: ArrayBuffer){
const view = new DataView(buffer, 0);
let i = 0;
function read16(){
const int = view.getUint16(i);
i += 2;
return int;
}
function read8(){
const int = view.getUint8(i);
i += 1;
return int;
}
function readString8(){
return readStringNo(read8());
}
function readString16(){
return readStringNo(read16());
}
function readStringNo(length: number){
const array = new Uint8Array(length);
for(let i = 0; i < length; i++){
array[i] = read8();
}
//console.log(array);
return new TextDecoder("utf8").decode(array.buffer as ArrayBuffer);
}
const build: { name: string; emojis: { name: string; emoji: string }[] }[] =
[];
let cats = read16();
const reader=new BinRead(buffer)
const build: { name: string; emojis: { name: string; emoji: string }[] }[] = [];
let cats = reader.read16();
for(; cats !== 0; cats--){
const name = readString16();
const name = reader.readString16();
const emojis: {
name: string;
skin_tone_support: boolean;
emoji: string;
}[] = [];
let emojinumber = read16();
let emojinumber = reader.read16();
for(; emojinumber !== 0; emojinumber--){
//console.log(emojis);
const name = readString8();
const len = read8();
const name = reader.readString8();
const len = reader.read8();
const skin_tone_support = len > 127;
const emoji = readStringNo(len - Number(skin_tone_support) * 128);
const emoji = reader.readStringNo(len - Number(skin_tone_support) * 128);
emojis.push({
name,
skin_tone_support,

View file

@ -1,5 +1,5 @@
import { I18n } from "./i18n.js";
import{ mobile }from"./login.js";
import{ mobile }from"./utils/utils.js";
console.log(mobile);
const serverbox = document.getElementById("instancebox") as HTMLDivElement;

View file

@ -1,6 +1,7 @@
import{ Localuser }from"./localuser.js";
import{ Contextmenu }from"./contextmenu.js";
import{ mobile, getBulkUsers, setTheme, Specialuser }from"./login.js";
import{ mobile }from"./utils/utils.js";
import { getBulkUsers, setTheme, Specialuser } from "./utils/utils.js";
import{ MarkDown }from"./markdown.js";
import{ Message }from"./message.js";
import{File}from"./file.js";

View file

@ -1,5 +1,6 @@
import { I18n } from "./i18n.js";
import{ getBulkUsers, Specialuser, getapiurls }from"./login.js";
import{ getapiurls }from"./utils/utils.js";
import { getBulkUsers, Specialuser } from "./utils/utils.js";
(async ()=>{
const users = getBulkUsers();

View file

@ -1,9 +1,10 @@
import{ Guild }from"./guild.js";
import{ Channel }from"./channel.js";
import{ Direct }from"./direct.js";
import{ AVoice }from"./audio.js";
import{ AVoice }from"./audio/audio.js";
import{ User }from"./user.js";
import{ getapiurls, getBulkInfo, setTheme, Specialuser, SW }from"./login.js";
import{ getapiurls, SW }from"./utils/utils.js";
import { getBulkInfo, setTheme, Specialuser } from "./utils/utils.js";
import{channeljson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js";
import{ Member }from"./member.js";
import{ Dialog, Form, FormError, Options, Settings }from"./settings.js";
@ -1237,10 +1238,10 @@ class Localuser{
.addSelect(
I18n.getTranslation("localuser.notisound"),
_=>{
AVoice.setNotificationSound(sounds[_]);
this.setNotificationSound(sounds[_]);
},
sounds,
{ defaultIndex: sounds.indexOf(AVoice.getNotificationSound()) }
{ defaultIndex: sounds.indexOf(this.getNotificationSound()) }
)
.watchForChange(_=>{
AVoice.noises(sounds[_]);
@ -2121,5 +2122,14 @@ class Localuser{
dialog.options.addText(I18n.getTranslation("instanceStats.members",json.counts.members));
dialog.show();
}
setNotificationSound(sound: string){
const userinfos = getBulkInfo();
userinfos.preferences.notisound = sound;
localStorage.setItem("userinfos", JSON.stringify(userinfos));
}
getNotificationSound(){
const userinfos = getBulkInfo();
return userinfos.preferences.notisound;
}
}
export{ Localuser };

View file

@ -1,95 +1,12 @@
import { getBulkInfo, Specialuser } from "./utils/utils.js";
import { I18n } from "./i18n.js";
import { Dialog, FormError } from "./settings.js";
import { checkInstance } from "./utils/utils.js";
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const iOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
let instances:
| {
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;
};
}[]
| null;
const datalist = document.getElementById("instances");
console.warn(datalist);
const instancefetch=fetch("/instances.json")
.then(res=>res.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;
}
}[]
)=>{
instances = json;
if(datalist){
console.warn(json);
if(instancein && instancein.value === ""){
instancein.value = json[0].name;
}
for(const instance of json){
if(instance.display === false){
continue;
}
const option = document.createElement("option");
option.disabled = !instance.online;
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);
}
checkInstance("");
}
}
);
setTheme();
await I18n.done
function setTheme(){
let name = localStorage.getItem("theme");
if(!name){
localStorage.setItem("theme", "Dark");
name = "Dark";
}
document.body.className = name + "-theme";
}
await I18n.done;
(async ()=>{
@ -108,13 +25,7 @@ function setTheme(){
}
})()
function getBulkUsers(){
const json = getBulkInfo();
for(const thing in json.users){
json.users[thing] = new Specialuser(json.users[thing]);
}
return json;
}
function trimswitcher(){
const json = getBulkInfo();
const map = new Map();
@ -148,133 +59,8 @@ function trimswitcher(){
console.log(json);
}
function getBulkInfo(){
return JSON.parse(localStorage.getItem("userinfos") as string);
}
function setDefaults(){
let userinfos = getBulkInfo();
if(!userinfos){
localStorage.setItem(
"userinfos",
JSON.stringify({
currentuser: null,
users: {},
preferences: {
theme: "Dark",
notifications: false,
notisound: "three",
},
})
);
userinfos = getBulkInfo();
}
if(userinfos.users === undefined){
userinfos.users = {};
}
if(userinfos.accent_color === undefined){
userinfos.accent_color = "#3096f7";
}
document.documentElement.style.setProperty(
"--accent-color",
userinfos.accent_color
);
if(userinfos.preferences === undefined){
userinfos.preferences = {
theme: "Dark",
notifications: false,
notisound: "three",
};
}
if(userinfos.preferences && userinfos.preferences.notisound === undefined){
console.warn("uhoh")
userinfos.preferences.notisound = "three";
}
localStorage.setItem("userinfos", JSON.stringify(userinfos));
}
setDefaults();
class Specialuser{
serverurls: {
api: string;
cdn: string;
gateway: string;
wellknown: string;
login: string;
};
email: string;
token: string;
loggedin;
json;
constructor(json: any){
if(json instanceof Specialuser){
console.error("specialuser can't construct from another specialuser");
}
this.serverurls = json.serverurls;
let apistring = new URL(json.serverurls.api).toString();
apistring = apistring.replace(/\/(v\d+\/?)?$/, "") + "/v9";
this.serverurls.api = apistring;
this.serverurls.cdn = new URL(json.serverurls.cdn)
.toString()
.replace(/\/$/, "");
this.serverurls.gateway = new URL(json.serverurls.gateway)
.toString()
.replace(/\/$/, "");
this.serverurls.wellknown = new URL(json.serverurls.wellknown)
.toString()
.replace(/\/$/, "");
this.serverurls.login = new URL(json.serverurls.login)
.toString()
.replace(/\/$/, "");
this.email = json.email;
this.token = json.token;
this.loggedin = json.loggedin;
this.json = json;
this.json.localuserStore ??= {};
if(!this.serverurls || !this.email || !this.token){
console.error(
"There are fundamentally missing pieces of info missing from this user"
);
}
}
set pfpsrc(e){
this.json.pfpsrc = e;
this.updateLocal();
}
get pfpsrc(){
return this.json.pfpsrc;
}
set username(e){
this.json.username = e;
this.updateLocal();
}
get username(){
return this.json.username;
}
set localuserStore(e){
this.json.localuserStore = e;
this.updateLocal();
}
get localuserStore(){
return this.json.localuserStore;
}
set id(e){
this.json.id = e;
this.updateLocal();
}
get id(){
return this.json.id;
}
get uid(){
return this.email + this.serverurls.wellknown;
}
toJSON(){
return this.json;
}
updateLocal(){
const info = getBulkInfo();
info.users[this.uid] = this.toJSON();
localStorage.setItem("userinfos", JSON.stringify(info));
}
}
function adduser(user: typeof Specialuser.prototype.json){
user = new Specialuser(user);
const info = getBulkInfo();
@ -286,167 +72,8 @@ function adduser(user: typeof Specialuser.prototype.json){
const instancein = document.getElementById("instancein") as HTMLInputElement;
let timeout: ReturnType<typeof setTimeout> | string | number | undefined | null = null;
// let instanceinfo;
const stringURLMap = new Map<string, string>();
const stringURLsMap = new Map<
string,
{
wellknown: string;
api: string;
cdn: string;
gateway: string;
login?: string;
}
>();
async function getapiurls(str: string): Promise<
{
api: string;
cdn: string;
gateway: string;
wellknown: string;
login: string;
}
| false
>{
function appendApi(str:string){
return str.includes("api")?"" : (str.endsWith("/")? "api" : "/api");
}
if(!URL.canParse(str)){
const val = stringURLMap.get(str);
if(stringURLMap.size===0){
await new Promise<void>(res=>{
setInterval(()=>{
if(stringURLMap.size!==0){
res();
}
},100);
});
}
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.at(-1) !== "/"){
str += "/";
}
let api: string;
try{
const info = await fetch(`${str}.well-known/spacebar`).then(x=>x.json()
);
api = info.api;
}catch{
api=str;
}
if(!URL.canParse(api)){
return false;
}
const url = new URL(api);
try{
const info = await fetch(
`${api}${
url.pathname.includes("api") ? "" : "api"
}/policies/instance/domains`
).then(x=>x.json());
const apiurl = new URL(info.apiEndpoint);
return{
api: info.apiEndpoint+appendApi(apiurl.pathname),
gateway: info.gateway,
cdn: info.cdn,
wellknown: str,
login: info.apiEndpoint+appendApi(apiurl.pathname),
};
}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;
}
}
async function checkInstance(instance?: string){
await instancefetch;
const verify = document.getElementById("verify");
try{
verify!.textContent = I18n.getTranslation("login.checking");
const instanceValue = instance || (instancein as HTMLInputElement).value;
const instanceinfo = (await getapiurls(instanceValue)) as {
wellknown: string;
api: string;
cdn: string;
gateway: string;
login: string;
value: string;
};
if(instanceinfo){
instanceinfo.value = instanceValue;
localStorage.setItem("instanceinfo", JSON.stringify(instanceinfo));
verify!.textContent = I18n.getTranslation("login.allGood");
// @ts-ignore
if(checkInstance.alt){
// @ts-ignore
checkInstance.alt();
}
setTimeout((_: any)=>{
console.log(verify!.textContent);
verify!.textContent = "";
}, 3000);
}else{
verify!.textContent = I18n.getTranslation("login.invalid");
}
}catch{
console.log("catch");
verify!.textContent = I18n.getTranslation("login.invalid");
}
}
if(instancein){
console.log(instancein);
@ -456,7 +83,7 @@ if(instancein){
if(timeout !== null && typeof timeout !== "string"){
clearTimeout(timeout);
}
timeout = setTimeout(()=>checkInstance(), 1000);
timeout = setTimeout(()=>checkInstance((instancein as HTMLInputElement).value), 1000);
});
if(localStorage.getItem("instanceinfo")){
const json = JSON.parse(localStorage.getItem("instanceinfo")!);
@ -597,51 +224,6 @@ if(document.getElementById("form")){
if(!localStorage.getItem("SWMode")){
localStorage.setItem("SWMode","true");
}
class SW{
static worker:undefined|ServiceWorker;
static setMode(mode:"false"|"offlineOnly"|"true"){
localStorage.setItem("SWMode",mode);
if(this.worker){
this.worker.postMessage({data:mode,code:"setMode"});
}
}
static checkUpdate(){
if(this.worker){
this.worker.postMessage({code:"CheckUpdate"});
}
}
static forceClear(){
if(this.worker){
this.worker.postMessage({code:"ForceClear"});
}
}
}
export {SW};
if ("serviceWorker" in navigator){
navigator.serviceWorker.register("/service.js", {
scope: "/",
}).then((registration) => {
let serviceWorker:ServiceWorker|undefined;
if (registration.installing) {
serviceWorker = registration.installing;
console.log("installing");
} else if (registration.waiting) {
serviceWorker = registration.waiting;
console.log("waiting");
} else if (registration.active) {
serviceWorker = registration.active;
console.log("active");
}
SW.worker=serviceWorker;
SW.setMode(localStorage.getItem("SWMode") as "false"|"offlineOnly"|"true");
if (serviceWorker) {
console.log(serviceWorker.state);
serviceWorker.addEventListener("statechange", (_) => {
console.log(serviceWorker.state);
});
}
})
}
const switchurl = document.getElementById("switch") as HTMLAreaElement;
if(switchurl){
@ -653,22 +235,13 @@ if(switchurl){
checkInstance("");
}
}
export{ checkInstance };
trimswitcher();
export{
mobile,
iOS,
getBulkUsers,
getBulkInfo,
setTheme,
Specialuser,
getapiurls,
adduser,
};
export function getInstances(){
return instances;
}

View file

@ -10,7 +10,7 @@ import{ File }from"./file.js";
import{ SnowFlake }from"./snowflake.js";
import{ memberjson, messagejson }from"./jsontypes.js";
import{ Emoji }from"./emoji.js";
import{ mobile }from"./login.js";
import{ mobile }from"./utils/utils.js";
import { I18n } from "./i18n.js";
import { Hover } from "./hover.js";
import { Dialog } from "./settings.js";

View file

@ -1,5 +1,6 @@
import { I18n } from "../i18n.js";
import{ getBulkUsers, Specialuser, getapiurls }from"../login.js";
import{ getapiurls }from"../utils/utils.js";
import { getBulkUsers, Specialuser } from "../utils/utils.js";
import { Permissions } from "../permissions.js";
type botjsonfetch={
guilds:{

View file

@ -1,5 +1,6 @@
import { I18n } from "./i18n.js";
import{ checkInstance, adduser }from"./login.js";
import{ checkInstance }from"./utils/utils.js";
import {adduser} from"./login.js";
import { MarkDown } from "./markdown.js";
await I18n.done
const registerElement = document.getElementById("register");

View file

@ -0,0 +1,79 @@
class BinRead{
private i = 0;
private view:DataView;
constructor(buffer:ArrayBuffer){
this.view=new DataView(buffer, 0)
}
read16(){
const int = this.view.getUint16(this.i);
this.i += 2;
return int;
}
read8(){
const int = this.view.getUint8(this.i);
this.i += 1;
return int;
}
readString8(){
return this.readStringNo(this.read8());
}
readString16(){
return this.readStringNo(this.read16());
}
readStringNo(length: number){
const array = new Uint8Array(length);
for(let i = 0; i < length; i++){
array[i] = this.read8();
}
//console.log(array);
return new TextDecoder("utf8").decode(array.buffer as ArrayBuffer);
}
}
class BinWrite{
private view: DataView;
private buffer:ArrayBuffer;
private i=0;
constructor(maxSize:number=2**26){
this.buffer=new ArrayBuffer(maxSize);
this.view=new DataView(this.buffer, 0);
}
write16(numb:number){
this.view.setUint16(this.i,numb);
this.i+=2;
}
write8(numb:number){
this.view.setUint8(this.i,numb);
this.i+=1;
}
writeString8(str:string){
const encode=new TextEncoder().encode(str);
this.write8(encode.length);
for(const thing of encode){
this.write8(thing);
}
}
writeString16(str:string){
const encode=new TextEncoder().encode(str);
this.write16(encode.length);
for(const thing of encode){
this.write8(thing);
}
}
writeStringNo(str:string){
const encode=new TextEncoder().encode(str);
for(const thing of encode){
this.write8(thing);
}
}
getBuffer(){
const buf=new ArrayBuffer(this.i);
const ar1=new Uint8Array(buf);
const ar2=new Uint8Array(this.buffer);
for(let i in ar1){
ar1[+i]=ar2[+i];
}
return buf;
}
}
export {BinRead,BinWrite}

436
src/webpage/utils/utils.ts Normal file
View file

@ -0,0 +1,436 @@
import { I18n } from "../i18n.js";
setTheme();
export function setTheme() {
let name = localStorage.getItem("theme");
if (!name) {
localStorage.setItem("theme", "Dark");
name = "Dark";
}
document.body.className = name + "-theme";
}
export function getBulkUsers() {
const json = getBulkInfo();
for (const thing in json.users) {
json.users[thing] = new Specialuser(json.users[thing]);
}
return json;
}
export function getBulkInfo() {
return JSON.parse(localStorage.getItem("userinfos") as string);
}
export function setDefaults() {
let userinfos = getBulkInfo();
if (!userinfos) {
localStorage.setItem(
"userinfos",
JSON.stringify({
currentuser: null,
users: {},
preferences: {
theme: "Dark",
notifications: false,
notisound: "three",
},
})
);
userinfos = getBulkInfo();
}
if (userinfos.users === undefined) {
userinfos.users = {};
}
if (userinfos.accent_color === undefined) {
userinfos.accent_color = "#3096f7";
}
document.documentElement.style.setProperty(
"--accent-color",
userinfos.accent_color
);
if (userinfos.preferences === undefined) {
userinfos.preferences = {
theme: "Dark",
notifications: false,
notisound: "three",
};
}
if (userinfos.preferences && userinfos.preferences.notisound === undefined) {
console.warn("uhoh");
userinfos.preferences.notisound = "three";
}
localStorage.setItem("userinfos", JSON.stringify(userinfos));
}
setDefaults();
export class Specialuser {
serverurls: {
api: string;
cdn: string;
gateway: string;
wellknown: string;
login: string;
};
email: string;
token: string;
loggedin;
json;
constructor(json: any) {
if (json instanceof Specialuser) {
console.error("specialuser can't construct from another specialuser");
}
this.serverurls = json.serverurls;
let apistring = new URL(json.serverurls.api).toString();
apistring = apistring.replace(/\/(v\d+\/?)?$/, "") + "/v9";
this.serverurls.api = apistring;
this.serverurls.cdn = new URL(json.serverurls.cdn)
.toString()
.replace(/\/$/, "");
this.serverurls.gateway = new URL(json.serverurls.gateway)
.toString()
.replace(/\/$/, "");
this.serverurls.wellknown = new URL(json.serverurls.wellknown)
.toString()
.replace(/\/$/, "");
this.serverurls.login = new URL(json.serverurls.login)
.toString()
.replace(/\/$/, "");
this.email = json.email;
this.token = json.token;
this.loggedin = json.loggedin;
this.json = json;
this.json.localuserStore ??= {};
if (!this.serverurls || !this.email || !this.token) {
console.error(
"There are fundamentally missing pieces of info missing from this user"
);
}
}
set pfpsrc(e) {
this.json.pfpsrc = e;
this.updateLocal();
}
get pfpsrc() {
return this.json.pfpsrc;
}
set username(e) {
this.json.username = e;
this.updateLocal();
}
get username() {
return this.json.username;
}
set localuserStore(e) {
this.json.localuserStore = e;
this.updateLocal();
}
get localuserStore() {
return this.json.localuserStore;
}
set id(e) {
this.json.id = e;
this.updateLocal();
}
get id() {
return this.json.id;
}
get uid() {
return this.email + this.serverurls.wellknown;
}
toJSON() {
return this.json;
}
updateLocal() {
const info = getBulkInfo();
info.users[this.uid] = this.toJSON();
localStorage.setItem("userinfos", JSON.stringify(info));
}
}
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const iOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
export{
mobile,
iOS,
}
let instances:
| {
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;
};
}[]
| null;
const datalist = document.getElementById("instances");
console.warn(datalist);
const instancefetch=fetch("/instances.json")
.then(res=>res.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;
}
}[]
)=>{
instances = json;
if(datalist){
console.warn(json);
const instancein = document.getElementById("instancein") as HTMLInputElement;
if(instancein && instancein.value === ""){
instancein.value = json[0].name;
}
for(const instance of json){
if(instance.display === false){
continue;
}
const option = document.createElement("option");
option.disabled = !instance.online;
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);
}
checkInstance("");
}
}
);
const stringURLMap = new Map<string, string>();
const stringURLsMap = new Map<
string,
{
wellknown: string;
api: string;
cdn: string;
gateway: string;
login?: string;
}
>();
export async function getapiurls(str: string): Promise<
{
api: string;
cdn: string;
gateway: string;
wellknown: string;
login: string;
}
| false
>{
function appendApi(str:string){
return str.includes("api")?"" : (str.endsWith("/")? "api" : "/api");
}
if(!URL.canParse(str)){
const val = stringURLMap.get(str);
if(stringURLMap.size===0){
await new Promise<void>(res=>{
setInterval(()=>{
if(stringURLMap.size!==0){
res();
}
},100);
});
}
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.at(-1) !== "/"){
str += "/";
}
let api: string;
try{
const info = await fetch(`${str}.well-known/spacebar`).then(x=>x.json()
);
api = info.api;
}catch{
api=str;
}
if(!URL.canParse(api)){
return false;
}
const url = new URL(api);
try{
const info = await fetch(
`${api}${
url.pathname.includes("api") ? "" : "api"
}/policies/instance/domains`
).then(x=>x.json());
const apiurl = new URL(info.apiEndpoint);
return{
api: info.apiEndpoint+appendApi(apiurl.pathname),
gateway: info.gateway,
cdn: info.cdn,
wellknown: str,
login: info.apiEndpoint+appendApi(apiurl.pathname),
};
}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;
}
}
export async function checkInstance(instance: string){
await instancefetch;
const verify = document.getElementById("verify");
try{
verify!.textContent = I18n.getTranslation("login.checking");
const instanceValue = instance;
const instanceinfo = (await getapiurls(instanceValue)) as {
wellknown: string;
api: string;
cdn: string;
gateway: string;
login: string;
value: string;
};
if(instanceinfo){
instanceinfo.value = instanceValue;
localStorage.setItem("instanceinfo", JSON.stringify(instanceinfo));
verify!.textContent = I18n.getTranslation("login.allGood");
// @ts-ignore
if(checkInstance.alt){
// @ts-ignore
checkInstance.alt();
}
setTimeout((_: any)=>{
console.log(verify!.textContent);
verify!.textContent = "";
}, 3000);
}else{
verify!.textContent = I18n.getTranslation("login.invalid");
}
}catch{
console.log("catch");
verify!.textContent = I18n.getTranslation("login.invalid");
}
}
export function getInstances(){
return instances;
}
export class SW{
static worker:undefined|ServiceWorker;
static setMode(mode:"false"|"offlineOnly"|"true"){
localStorage.setItem("SWMode",mode);
if(this.worker){
this.worker.postMessage({data:mode,code:"setMode"});
}
}
static checkUpdate(){
if(this.worker){
this.worker.postMessage({code:"CheckUpdate"});
}
}
static forceClear(){
if(this.worker){
this.worker.postMessage({code:"ForceClear"});
}
}
}
if ("serviceWorker" in navigator){
navigator.serviceWorker.register("/service.js", {
scope: "/",
}).then((registration) => {
let serviceWorker:ServiceWorker|undefined;
if (registration.installing) {
serviceWorker = registration.installing;
console.log("installing");
} else if (registration.waiting) {
serviceWorker = registration.waiting;
console.log("waiting");
} else if (registration.active) {
serviceWorker = registration.active;
console.log("active");
}
SW.worker=serviceWorker;
SW.setMode(localStorage.getItem("SWMode") as "false"|"offlineOnly"|"true");
if (serviceWorker) {
console.log(serviceWorker.state);
serviceWorker.addEventListener("statechange", (_) => {
console.log(serviceWorker.state);
});
}
})
}