From 4509605cc70d28272469eed455cd527932aff2a4 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Thu, 28 Nov 2024 21:26:06 -0600 Subject: [PATCH 0001/1178] spacing changes --- src/webpage/index.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/webpage/index.html b/src/webpage/index.html index 13f62766..1cf492ec 100644 --- a/src/webpage/index.html +++ b/src/webpage/index.html @@ -1,6 +1,5 @@ - @@ -16,8 +15,6 @@ - -
From 38ca7ea280229ec637f91baa9aec8e2e50213785 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 29 Nov 2024 16:18:59 -0600 Subject: [PATCH 0002/1178] fix minor message combine bug --- src/webpage/message.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/webpage/message.ts b/src/webpage/message.ts index 843a0cbd..7d619330 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -368,9 +368,7 @@ class Message extends SnowFlake{ let next: Message | undefined = this; while(next?.author === this.author){ next.generateMessage(); - next = this.channel.messages.get( - this.channel.idToNext.get(next.id) as string - ); + next = this.channel.messages.get(this.channel.idToNext.get(next.id) as string); } if(this.channel.infinite.scollDiv && scroll){ this.channel.infinite.scollDiv.scrollTop = scroll; @@ -460,10 +458,11 @@ class Message extends SnowFlake{ div.appendChild(replyline); } div.appendChild(build); - if({ 0: true, 19: true }[this.type] || this.attachments.length !== 0){ + const messageTypes=new Set([0,19]) + if(messageTypes.has(this.type) || this.attachments.length !== 0){ const pfpRow = document.createElement("div"); let pfpparent, current; - if(premessage != null){ + if(premessage !== null){ pfpparent ??= premessage; // @ts-ignore // TODO: type this @@ -473,7 +472,7 @@ class Message extends SnowFlake{ const newt = new Date(this.timestamp).getTime() / 1000; current = newt - old > 600; } - const combine = premessage?.author != this.author || current || this.message_reference; + const combine = premessage?.author != this.author || current || this.message_reference || !messageTypes.has(premessage.type); if(combine){ const pfp = this.author.buildpfp(); this.author.bind(pfp, this.guild, false); From 0227320876570fb55aa85925dfa27b0e614de215 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 29 Nov 2024 21:40:20 -0600 Subject: [PATCH 0003/1178] change snowflake --- src/webpage/snowflake.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/webpage/snowflake.ts b/src/webpage/snowflake.ts index e6a46035..e32c9add 100644 --- a/src/webpage/snowflake.ts +++ b/src/webpage/snowflake.ts @@ -10,10 +10,7 @@ abstract class SnowFlake{ try{ return Number((BigInt(str) >> 22n) + 1420070400000n); }catch{ - console.error( - `The ID is corrupted, it's ${str} when it should be some number.` - ); - return 0; + throw new Error(`The ID is corrupted, it's ${str} when it should be some number.`); } } } From a402177e89d82ad4472173a7c37e3e2d168308e8 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 29 Nov 2024 22:26:39 -0600 Subject: [PATCH 0004/1178] bug fix --- src/webpage/message.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpage/message.ts b/src/webpage/message.ts index 7d619330..7a9a7add 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -462,7 +462,7 @@ class Message extends SnowFlake{ if(messageTypes.has(this.type) || this.attachments.length !== 0){ const pfpRow = document.createElement("div"); let pfpparent, current; - if(premessage !== null){ + if(premessage !== undefined){ pfpparent ??= premessage; // @ts-ignore // TODO: type this From 01ebde20f97866dee3a378ff49178f5046fd23e1 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 30 Nov 2024 16:44:53 -0600 Subject: [PATCH 0005/1178] fix member list bug --- src/webpage/localuser.ts | 18 ++++++++++-------- src/webpage/member.ts | 6 +++++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index e61e01fd..d27d44b0 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -652,20 +652,22 @@ class Localuser{ async memberListUpdate(list:memberlistupdatejson|void){ const div=document.getElementById("sideDiv") as HTMLDivElement; div.innerHTML=""; - if(!list) return; - const counts=new Map(); const guild=this.lookingguild; if(!guild) return; const channel=this.channelfocus; if(!channel) return; - for(const thing of list.d.ops[0].items){ - if("member" in thing){ - await Member.new(thing.member,guild); - }else{ - counts.set(thing.group.id,thing.group.count); + if(list){ + const counts=new Map(); + for(const thing of list.d.ops[0].items){ + if("member" in thing){ + await Member.new(thing.member,guild); + }else{ + counts.set(thing.group.id,thing.group.count); + } } } + const elms:Map=new Map([]); for(const role of guild.roles){ if(role.hoist){ @@ -678,7 +680,7 @@ class Localuser{ members.forEach((member)=>{ if(!channel.hasPermission("VIEW_CHANNEL",member)){ members.delete(member); - console.log(member) + console.log(member,"can't see") return; } }) diff --git a/src/webpage/member.ts b/src/webpage/member.ts index 7fed07c0..2afb7882 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -162,7 +162,11 @@ class Member extends SnowFlake{ } }); user.members.set(guild, promise); - return await promise; + const member=await promise; + if(member){ + guild.members.add(member); + } + return member; } if(maybe instanceof Promise){ return await maybe; From e06b28742c084259875773dcaa1be3b6ea064344 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 30 Nov 2024 17:10:34 -0600 Subject: [PATCH 0006/1178] conditionally show add friend in context menu --- src/webpage/user.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/webpage/user.ts b/src/webpage/user.ts index 621793f9..003fe4a7 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -163,6 +163,8 @@ class User extends SnowFlake{ ); this.contextmenu.addbutton(()=>I18n.getTranslation("user.friendReq"), function(this: User){ this.changeRelationship(1); + },null,function(){ + return this.relationshipType===0; }); this.contextmenu.addbutton( ()=>I18n.getTranslation("user.kick"), From d94c20b275e4a3e82e6935d82e166e678d1160fb Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 30 Nov 2024 19:04:00 -0600 Subject: [PATCH 0007/1178] some reorginization --- src/webpage/{ => audio}/audio.ts | 15 - src/webpage/audio/index.html | 22 ++ src/webpage/audio/page.ts | 0 src/webpage/channel.ts | 4 +- src/webpage/contextmenu.ts | 2 +- src/webpage/embed.ts | 2 +- src/webpage/emoji.ts | 44 +-- src/webpage/home.ts | 2 +- src/webpage/index.ts | 3 +- src/webpage/invite.ts | 3 +- src/webpage/localuser.ts | 18 +- src/webpage/login.ts | 451 +------------------------------ src/webpage/message.ts | 2 +- src/webpage/oauth2/auth.ts | 3 +- src/webpage/register.ts | 3 +- src/webpage/utils/binaryUtils.ts | 79 ++++++ src/webpage/utils/utils.ts | 436 ++++++++++++++++++++++++++++++ 17 files changed, 586 insertions(+), 503 deletions(-) rename src/webpage/{ => audio}/audio.ts (90%) create mode 100644 src/webpage/audio/index.html create mode 100644 src/webpage/audio/page.ts create mode 100644 src/webpage/utils/binaryUtils.ts create mode 100644 src/webpage/utils/utils.ts diff --git a/src/webpage/audio.ts b/src/webpage/audio/audio.ts similarity index 90% rename from src/webpage/audio.ts rename to src/webpage/audio/audio.ts index 13b90cef..cdc412fe 100644 --- a/src/webpage/audio.ts +++ b/src/webpage/audio/audio.ts @@ -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 }; diff --git a/src/webpage/audio/index.html b/src/webpage/audio/index.html new file mode 100644 index 00000000..429291ea --- /dev/null +++ b/src/webpage/audio/index.html @@ -0,0 +1,22 @@ + + + + + + + Jank Audio + + + + + + + + + + +

Place holder text

+ + + + diff --git a/src/webpage/audio/page.ts b/src/webpage/audio/page.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 9493308c..42717deb 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -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; diff --git a/src/webpage/contextmenu.ts b/src/webpage/contextmenu.ts index 8d6eac38..794fd88e 100644 --- a/src/webpage/contextmenu.ts +++ b/src/webpage/contextmenu.ts @@ -1,4 +1,4 @@ -import{ iOS }from"./login.js"; +import{ iOS }from"./utils/utils.js"; class Contextmenu{ static currentmenu: HTMLElement | ""; name: string; diff --git a/src/webpage/embed.ts b/src/webpage/embed.ts index e84105d2..73bad4a2 100644 --- a/src/webpage/embed.ts +++ b/src/webpage/embed.ts @@ -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"; diff --git a/src/webpage/emoji.ts b/src/webpage/emoji.ts index 03b1d429..b6e04e82 100644 --- a/src/webpage/emoji.ts +++ b/src/webpage/emoji.ts @@ -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, diff --git a/src/webpage/home.ts b/src/webpage/home.ts index a04772b4..20cac876 100644 --- a/src/webpage/home.ts +++ b/src/webpage/home.ts @@ -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; diff --git a/src/webpage/index.ts b/src/webpage/index.ts index 6499fcbc..b7fa3bb1 100644 --- a/src/webpage/index.ts +++ b/src/webpage/index.ts @@ -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"; diff --git a/src/webpage/invite.ts b/src/webpage/invite.ts index 15ebecaa..fcc053b4 100644 --- a/src/webpage/invite.ts +++ b/src/webpage/invite.ts @@ -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(); diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index d27d44b0..b7b4087c 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -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 }; diff --git a/src/webpage/login.ts b/src/webpage/login.ts index a85a36af..099b67eb 100644 --- a/src/webpage/login.ts +++ b/src/webpage/login.ts @@ -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 | string | number | undefined | null = null; // let instanceinfo; -const stringURLMap = new Map(); -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(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; -} + diff --git a/src/webpage/message.ts b/src/webpage/message.ts index 7a9a7add..d13cc3ce 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -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"; diff --git a/src/webpage/oauth2/auth.ts b/src/webpage/oauth2/auth.ts index 2345f157..a7a5d411 100644 --- a/src/webpage/oauth2/auth.ts +++ b/src/webpage/oauth2/auth.ts @@ -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:{ diff --git a/src/webpage/register.ts b/src/webpage/register.ts index 7a9555cb..bdba6ed8 100644 --- a/src/webpage/register.ts +++ b/src/webpage/register.ts @@ -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"); diff --git a/src/webpage/utils/binaryUtils.ts b/src/webpage/utils/binaryUtils.ts new file mode 100644 index 00000000..322f192f --- /dev/null +++ b/src/webpage/utils/binaryUtils.ts @@ -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} diff --git a/src/webpage/utils/utils.ts b/src/webpage/utils/utils.ts new file mode 100644 index 00000000..abeb73f1 --- /dev/null +++ b/src/webpage/utils/utils.ts @@ -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(); + +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(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); + }); + } + }) +} From c16db7155578924f23216cf9d568045f283d5078 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 30 Nov 2024 19:14:12 -0600 Subject: [PATCH 0008/1178] edits to the page --- src/webpage/audio/index.html | 5 +++-- src/webpage/audio/page.ts | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/webpage/audio/index.html b/src/webpage/audio/index.html index 429291ea..0d92d352 100644 --- a/src/webpage/audio/index.html +++ b/src/webpage/audio/index.html @@ -15,8 +15,9 @@ -

Place holder text

+

This will eventually be something

+

I want to let the sound system of jank not be so hard coded, but I still need to work on everything a bit before that can happen. Thanks for your patience

- + diff --git a/src/webpage/audio/page.ts b/src/webpage/audio/page.ts index e69de29b..a37af3fc 100644 --- a/src/webpage/audio/page.ts +++ b/src/webpage/audio/page.ts @@ -0,0 +1,3 @@ +import { setTheme } from "../utils/utils.js"; + +setTheme(); From 7c46e70304a4b3b83a5cf762d6c479ddba6c28b6 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 30 Nov 2024 19:26:43 -0600 Subject: [PATCH 0009/1178] little more text --- src/webpage/audio/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/webpage/audio/index.html b/src/webpage/audio/index.html index 0d92d352..75cb8e48 100644 --- a/src/webpage/audio/index.html +++ b/src/webpage/audio/index.html @@ -16,7 +16,9 @@

This will eventually be something

-

I want to let the sound system of jank not be so hard coded, but I still need to work on everything a bit before that can happen. Thanks for your patience

+

I want to let the sound system of jank not be so hard coded, but I still need to work on everything a bit before that can happen. Thanks for your patience.

+

why does this tool need to exist?

+

For size reasons jank does not use normal sound files, so I need to make this whole format to be more adaptable

From 6788c54ad695e6b84a72a3e863bb5793a25417ab Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 30 Nov 2024 22:47:50 -0600 Subject: [PATCH 0010/1178] reorginization and new sound format --- gulpfile.cjs | 1 + src/webpage/audio/audio.md | 37 +++++ src/webpage/audio/audio.ts | 213 +++++--------------------- src/webpage/audio/index.html | 1 + src/webpage/audio/page.ts | 154 +++++++++++++++++++ src/webpage/audio/play.ts | 48 ++++++ src/webpage/audio/sounds.jasf | Bin 0 -> 263 bytes src/webpage/audio/track.ts | 46 ++++++ src/webpage/audio/voice.ts | 246 +++++++++++++++++++++++++++++++ src/webpage/channel.ts | 9 +- src/webpage/localuser.ts | 17 ++- src/webpage/utils/binaryUtils.ts | 9 ++ 12 files changed, 595 insertions(+), 186 deletions(-) create mode 100644 src/webpage/audio/audio.md create mode 100644 src/webpage/audio/play.ts create mode 100644 src/webpage/audio/sounds.jasf create mode 100644 src/webpage/audio/track.ts create mode 100644 src/webpage/audio/voice.ts diff --git a/gulpfile.cjs b/gulpfile.cjs index f317e6fb..681c6556 100644 --- a/gulpfile.cjs +++ b/gulpfile.cjs @@ -113,6 +113,7 @@ return gulp "src/**/*.webp", "src/**/*.gif", "src/**/*.svg", + "src/**/*.jasf", ],{encoding:false}) .pipe(plumber()) // Prevent pipe breaking caused by errors .pipe(gulp.dest("dist")); diff --git a/src/webpage/audio/audio.md b/src/webpage/audio/audio.md new file mode 100644 index 00000000..10ba3bdb --- /dev/null +++ b/src/webpage/audio/audio.md @@ -0,0 +1,37 @@ +# Jank Audio format +This is a markdown file that will try to describe the jank client audio format in sufficient detail so people will know how this weird custom format works into the future. +This is a byte-aligned format, which uses the sequence jasf in asci as a magic number at the start. + +the next 8 bits will decide how many voices this file has/will provide, if the value is 255 you'll instead have a 16 bit number that follows for how many voices there are, this *should* be unused, but I wouldn't be totally surprised if it did get used. + +then it'll parse for that many voices, which will be formatted like the following: +name:String8; +length:f32; **if this is 0, this is not an custom sound and is instead refering to something else which will be explained later™** + +Given a non-zero length, this will parse the sounds as following: +|instruction | description | +| ---------- | ----------- | +| 000 | read float32 and use as value | +| 001 | read time(it'll always be a value between 0 and 1) | +| 002 | read frequency in hz | +| 003 | the constant PI | +| 004 | Math.sin() on the following sequence | +| 005 | multiplies the next two expressions | +| 006 | adds the next two expressions | +| 007 | divides the first expression by the second | +| 008 | subtracts the second expression by the first | +| 009 | first expression to the power of the second | +| 010 | first expression to the modulo of the second | +| 011 | absolute power of the next expression | +| 012 | round the next expression | +| 013 | Math.cos() on the next expression | +> note +> this is likely to expand in the future as more things are needed, but this is just how it is right now. + +Once you've read all of the sounds in the file, you can move on to parsing the tracks. +This starts out by reading a u16 to find out how many tracks there are, then you'll go on to try and parse that many. + +each track will then read a u16 to find out how long it is, then it'll read bytes as the following. +it'll first read the index(which is either a u8 or u16 depending on if the amount of voices was u8 or u16), which is the index of the voice 1-indexed, then if it's not 0 it'll parse two float32s in this order, the volume then the pitch of the sound, if it was 0 it'll instead read one 32f as a delay in the track. if it's a default sound it'll also read a third 32f for length + +then finally you'll parse the audios which are the complete tracks. you'll first parse a u16 to get how many audios there are, then for each audio you'll first parse a string8 for the name, then a u16 for the length then according to the length you'll go on to parse a u16 to get the track (1-indexed again) where if it's 0 you'll instead add a delay according to the next f32, how many ever times according to the length. diff --git a/src/webpage/audio/audio.ts b/src/webpage/audio/audio.ts index cdc412fe..d69a8c98 100644 --- a/src/webpage/audio/audio.ts +++ b/src/webpage/audio/audio.ts @@ -1,181 +1,34 @@ -class AVoice{ - audioCtx: AudioContext; - info: { wave: string | Function; freq: number }; - playing: boolean; - myArrayBuffer: AudioBuffer; - gainNode: GainNode; - buffer: Float32Array; - source: AudioBufferSourceNode; - constructor(wave: string | Function, freq: number, volume = 1){ - this.audioCtx = new window.AudioContext(); - this.info = { wave, freq }; - this.playing = false; - this.myArrayBuffer = this.audioCtx.createBuffer( - 1, - this.audioCtx.sampleRate, - this.audioCtx.sampleRate - ); - this.gainNode = this.audioCtx.createGain(); - this.gainNode.gain.value = volume; - this.gainNode.connect(this.audioCtx.destination); - this.buffer = this.myArrayBuffer.getChannelData(0); - this.source = this.audioCtx.createBufferSource(); - this.source.buffer = this.myArrayBuffer; - this.source.loop = true; - this.source.start(); - this.updateWave(); - } - get wave(): string | Function{ - return this.info.wave; - } - get freq(): number{ - return this.info.freq; - } - set wave(wave: string | Function){ - this.info.wave = wave; - this.updateWave(); - } - set freq(freq: number){ - this.info.freq = freq; - this.updateWave(); - } - updateWave(): void{ - const func = this.waveFunction(); - for(let i = 0; i < this.buffer.length; i++){ - this.buffer[i] = func(i / this.audioCtx.sampleRate, this.freq); - } - } - waveFunction(): Function{ - if(typeof this.wave === "function"){ - return this.wave; - } - switch(this.wave){ - case"sin": - return(t: number, freq: number)=>{ - return Math.sin(t * Math.PI * 2 * freq); - }; - case"triangle": - return(t: number, freq: number)=>{ - return Math.abs(((4 * t * freq) % 4) - 2) - 1; - }; - case"sawtooth": - return(t: number, freq: number)=>{ - return((t * freq) % 1) * 2 - 1; - }; - case"square": - return(t: number, freq: number)=>{ - return(t * freq) % 2 < 1 ? 1 : -1; - }; - case"white": - return(_t: number, _freq: number)=>{ - return Math.random() * 2 - 1; - }; - } - return new Function(); - } - play(): void{ - if(this.playing){ - return; - } - this.source.connect(this.gainNode); - this.playing = true; - } - stop(): void{ - if(this.playing){ - this.source.disconnect(); - this.playing = false; - } - } - static noises(noise: string): void{ - switch(noise){ - case"three": { - const voicy = new AVoice("sin", 800); - voicy.play(); - setTimeout(_=>{ - voicy.freq = 1000; - }, 50); - setTimeout(_=>{ - voicy.freq = 1300; - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case"zip": { - const voicy = new AVoice((t: number, freq: number)=>{ - return Math.sin((t + 2) ** Math.cos(t * 4) * Math.PI * 2 * freq); - }, 700); - voicy.play(); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case"square": { - const voicy = new AVoice("square", 600, 0.4); - voicy.play(); - setTimeout(_=>{ - voicy.freq = 800; - }, 50); - setTimeout(_=>{ - voicy.freq = 1000; - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case"beep": { - const voicy = new AVoice("sin", 800); - voicy.play(); - setTimeout(_=>{ - voicy.stop(); - }, 50); - setTimeout(_=>{ - voicy.play(); - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case "join":{ - const voicy = new AVoice("triangle", 600,.1); - voicy.play(); - setTimeout(_=>{ - voicy.freq=800; - }, 75); - setTimeout(_=>{ - voicy.freq=1000; - }, 150); - setTimeout(_=>{ - voicy.stop(); - }, 200); - break; - } - case "leave":{ - const voicy = new AVoice("triangle", 850,.5); - voicy.play(); - setTimeout(_=>{ - voicy.freq=700; - }, 100); - setTimeout(_=>{ - voicy.stop(); - voicy.freq=400; - }, 180); - setTimeout(_=>{ - voicy.play(); - }, 200); - setTimeout(_=>{ - voicy.stop(); - }, 250); - break; - } - } - } - static get sounds(){ - return["three", "zip", "square", "beep"]; - } +import { BinRead } from "../utils/binaryUtils.js"; +import { Track } from "./track.js"; + +export class Audio{ + name:string; + tracks:(Track|number)[]; + constructor(name:string,tracks:(Track|number)[]){ + this.tracks=tracks; + this.name=name; + } + static parse(read:BinRead,trackarr:Track[]):Audio{ + const name=read.readString8(); + const length=read.read16(); + const tracks:(Track|number)[]=[] + for(let i=0;isetTimeout(res,thing)); + } + } + } } -export{ AVoice as AVoice }; diff --git a/src/webpage/audio/index.html b/src/webpage/audio/index.html index 75cb8e48..1d71d8f2 100644 --- a/src/webpage/audio/index.html +++ b/src/webpage/audio/index.html @@ -19,6 +19,7 @@

This will eventually be something

I want to let the sound system of jank not be so hard coded, but I still need to work on everything a bit before that can happen. Thanks for your patience.

why does this tool need to exist?

For size reasons jank does not use normal sound files, so I need to make this whole format to be more adaptable

+ diff --git a/src/webpage/audio/page.ts b/src/webpage/audio/page.ts index a37af3fc..ccc5d45a 100644 --- a/src/webpage/audio/page.ts +++ b/src/webpage/audio/page.ts @@ -1,3 +1,157 @@ +import { BinWrite } from "../utils/binaryUtils.js"; import { setTheme } from "../utils/utils.js"; +import { Play } from "./play.js"; setTheme(); +const w=new BinWrite(2**12); +w.writeStringNo("jasf"); +w.write8(4); + +w.writeString8("sin"); +w.write32Float(0); +w.writeString8("triangle"); +w.write32Float(0); +w.writeString8("square"); +w.write32Float(0); + +w.writeString8("custom"); +w.write32Float(150); +//return Math.sin(((t + 2) ** Math.cos(t * 4)) * Math.PI * 2 * freq); +//Math.sin((((t+2)**Math.cos((t*4)))*((Math.PI*2)*f))) +w.write8(4);//sin +w.write8(5)//times +{ + w.write8(9);//Power + + { + w.write8(6);//adding + w.write8(1);//t + w.write8(0);w.write32Float(2);//2 + } + w.write8(13);//cos + w.write8(5);// times + w.write8(1);//t + w.write8(0);w.write32Float(4);//4 +} +{ + w.write8(5)//times + w.write8(5)//times + w.write8(3);//PI + w.write8(0);w.write32Float(2);//2 + w.write8(2);//freq +} + +w.write16(4);//3 tracks + +w.write16(1);//zip +w.write8(4); +w.write32Float(1) +w.write32Float(700) + +w.write16(3);//beep +{ + w.write8(1); + w.write32Float(1) + w.write32Float(700); + w.write32Float(50); + + w.write8(0); + w.write32Float(100); + + w.write8(1); + w.write32Float(1) + w.write32Float(700); + w.write32Float(50); +} + +w.write16(5);//three +{ + w.write8(1); + w.write32Float(1) + w.write32Float(800); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(1); + w.write32Float(1) + w.write32Float(1000); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(1); + w.write32Float(1) + w.write32Float(1300); + w.write32Float(50); +} + +w.write16(5);//square +{ + w.write8(3); + w.write32Float(1) + w.write32Float(600); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(3); + w.write32Float(1) + w.write32Float(800); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(3); + w.write32Float(1) + w.write32Float(1000); + w.write32Float(50); +} +w.write16(4);//2 audio + +w.writeString8("zip"); +w.write16(1); +w.write16(1); + +w.writeString8("beep"); +w.write16(1); +w.write16(2); + +w.writeString8("three"); +w.write16(1); +w.write16(3); + +w.writeString8("square"); +w.write16(1); +w.write16(4); +const buff=w.getBuffer(); +const play=Play.parseBin(buff); +/* +const zip=play.audios.get("square"); +if(zip){ + setInterval(()=>{ + zip.play() + },1000) + ; + console.log(play.voices[3][0].info.wave) +}; +*/ +console.log(play,buff); + +const download=document.getElementById("download"); +if(download){ + download.onclick=()=>{ + const blob = new Blob([buff], { type: "binary" }); + const downloadUrl = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = downloadUrl; + a.download = "sounds.jasf"; + document.body.appendChild(a); + a.click(); + URL.revokeObjectURL(downloadUrl); + } +} diff --git a/src/webpage/audio/play.ts b/src/webpage/audio/play.ts new file mode 100644 index 00000000..8ae81f96 --- /dev/null +++ b/src/webpage/audio/play.ts @@ -0,0 +1,48 @@ +import { BinRead } from "../utils/binaryUtils.js"; +import { Track } from "./track.js"; +import { AVoice } from "./voice.js"; +import { Audio } from "./audio.js"; +export class Play{ + voices:[AVoice,string][] + tracks:Track[] + audios:Map; + constructor(voices:[AVoice,string][],tracks:Track[],audios:Map){ + this.voices=voices; + this.tracks=tracks; + this.audios=audios; + } + static parseBin(buffer:ArrayBuffer){ + const read=new BinRead(buffer); + if(read.readStringNo(4)!=="jasf") throw new Error("this is not a jasf file"); + let voices=read.read8(); + let six=false; + if(voices===255){ + voices=read.read16(); + six=true; + } + const voiceArr:[AVoice,string][]=[]; + for(let i=0;i(); + for(let i=0;ir5N^CXdtRN-bv%%b zzJZ)c3chZR7dMzPKH55{+_y2^uIo8KJS`1YlFwM~9$>bkFF-J~6tY=JY)zKcR&4bG yehI6UPzOXP>Hf&G*BQ2Br>yaLqU5_oNiHGV`8$kkwsUR}1*cPRPL$0*G@v)Q`Y9#= literal 0 HcmV?d00001 diff --git a/src/webpage/audio/track.ts b/src/webpage/audio/track.ts new file mode 100644 index 00000000..dac4af31 --- /dev/null +++ b/src/webpage/audio/track.ts @@ -0,0 +1,46 @@ +import { BinRead } from "../utils/binaryUtils.js"; +import { AVoice } from "./voice.js"; + +export class Track{ + seq:(AVoice|number)[]; + constructor(playing:(AVoice|number)[]){ + this.seq=playing; + } + static parse(read:BinRead,play:[AVoice,string][],six:boolean):Track{ + const length=read.read16(); + const play2:(AVoice|number)[]=[]; + for(let i=0;isetTimeout(res,thing)); + } + } + } +} diff --git a/src/webpage/audio/voice.ts b/src/webpage/audio/voice.ts new file mode 100644 index 00000000..703fa126 --- /dev/null +++ b/src/webpage/audio/voice.ts @@ -0,0 +1,246 @@ +import { BinRead } from "../utils/binaryUtils.js"; + +class AVoice{ + audioCtx: AudioContext; + info: { wave: string | Function; freq: number }; + playing: boolean; + myArrayBuffer: AudioBuffer; + gainNode: GainNode; + buffer: Float32Array; + source: AudioBufferSourceNode; + length=1; + constructor(wave: string | Function, freq: number, volume = 1,length=1000){ + this.length=length; + this.audioCtx = new window.AudioContext(); + this.info = { wave, freq }; + this.playing = false; + this.myArrayBuffer = this.audioCtx.createBuffer( + 1, + this.audioCtx.sampleRate*length/1000, + this.audioCtx.sampleRate + ); + this.gainNode = this.audioCtx.createGain(); + this.gainNode.gain.value = volume; + this.gainNode.connect(this.audioCtx.destination); + this.buffer = this.myArrayBuffer.getChannelData(0); + this.source = this.audioCtx.createBufferSource(); + this.source.buffer = this.myArrayBuffer; + this.source.loop = true; + this.source.start(); + this.updateWave(); + } + clone(volume:number,freq:number,length=this.length){ + return new AVoice(this.wave,freq,volume,length); + } + get wave(): string | Function{ + return this.info.wave; + } + get freq(): number{ + return this.info.freq; + } + set wave(wave: string | Function){ + this.info.wave = wave; + this.updateWave(); + } + set freq(freq: number){ + this.info.freq = freq; + this.updateWave(); + } + updateWave(): void{ + const func = this.waveFunction(); + for(let i = 0; i < this.buffer.length; i++){ + this.buffer[i] = func(i / this.audioCtx.sampleRate, this.freq); + } + } + waveFunction(): Function{ + if(typeof this.wave === "function"){ + return this.wave; + } + switch(this.wave){ + case"sin": + return(t: number, freq: number)=>{ + return Math.sin(t * Math.PI * 2 * freq); + }; + case"triangle": + return(t: number, freq: number)=>{ + return Math.abs(((4 * t * freq) % 4) - 2) - 1; + }; + case"sawtooth": + return(t: number, freq: number)=>{ + return((t * freq) % 1) * 2 - 1; + }; + case"square": + return(t: number, freq: number)=>{ + return(t * freq) % 2 < 1 ? 1 : -1; + }; + case"white": + return(_t: number, _freq: number)=>{ + return Math.random() * 2 - 1; + }; + } + return new Function(); + } + play(): void{ + if(this.playing){ + return; + } + this.source.connect(this.gainNode); + this.playing = true; + } + playL(){ + this.play(); + setTimeout(()=>{ + this.stop(); + },this.length); + } + stop(): void{ + if(this.playing){ + this.source.disconnect(); + this.playing = false; + } + } + static noises(noise: string): void{ + switch(noise){ + case"three": { + const voicy = new AVoice("sin", 800); + voicy.play(); + setTimeout(_=>{ + voicy.freq = 1000; + }, 50); + setTimeout(_=>{ + voicy.freq = 1300; + }, 100); + setTimeout(_=>{ + voicy.stop(); + }, 150); + break; + } + case"zip": { + const voicy = new AVoice((t: number, freq: number)=>{ + return Math.sin((t + 2) ** Math.cos(t * 4) * Math.PI * 2 * freq); + }, 700); + voicy.play(); + setTimeout(_=>{ + voicy.stop(); + }, 150); + break; + } + case"square": { + const voicy = new AVoice("square", 600, 0.4); + voicy.play(); + setTimeout(_=>{ + voicy.freq = 800; + }, 50); + setTimeout(_=>{ + voicy.freq = 1000; + }, 100); + setTimeout(_=>{ + voicy.stop(); + }, 150); + break; + } + case"beep": { + const voicy = new AVoice("sin", 800); + voicy.play(); + setTimeout(_=>{ + voicy.stop(); + }, 50); + setTimeout(_=>{ + voicy.play(); + }, 100); + setTimeout(_=>{ + voicy.stop(); + }, 150); + break; + } + case "join":{ + const voicy = new AVoice("triangle", 600,.1); + voicy.play(); + setTimeout(_=>{ + voicy.freq=800; + }, 75); + setTimeout(_=>{ + voicy.freq=1000; + }, 150); + setTimeout(_=>{ + voicy.stop(); + }, 200); + break; + } + case "leave":{ + const voicy = new AVoice("triangle", 850,.5); + voicy.play(); + setTimeout(_=>{ + voicy.freq=700; + }, 100); + setTimeout(_=>{ + voicy.stop(); + voicy.freq=400; + }, 180); + setTimeout(_=>{ + voicy.play(); + }, 200); + setTimeout(_=>{ + voicy.stop(); + }, 250); + break; + } + } + } + static get sounds(){ + return["three", "zip", "square", "beep"]; + } + static getVoice(read:BinRead):[AVoice,string]{ + const name = read.readString8(); + let length=read.readFloat32(); + let special:Function|string + if(length!==0){ + special=this.parseExpression(read); + }else{ + special=name; + length=1; + } + return [new AVoice(special,0,0,length),name] + } + static parseExpression(read:BinRead):Function{ + return new Function("t","f",`return ${this.PEHelper(read)};`); + } + static PEHelper(read:BinRead):string{ + let state=read.read8(); + switch(state){ + case 0: + return ""+read.readFloat32(); + case 1: + return "t"; + case 2: + return "f"; + case 3: + return `Math.PI` + case 4: + return `Math.sin(${this.PEHelper(read)})`; + case 5: + return `(${this.PEHelper(read)}*${this.PEHelper(read)})`; + case 6: + return `(${this.PEHelper(read)}+${this.PEHelper(read)})`; + case 7: + return `(${this.PEHelper(read)}/${this.PEHelper(read)})`; + case 8: + return `(${this.PEHelper(read)}-${this.PEHelper(read)})`; + case 9: + return `(${this.PEHelper(read)}**${this.PEHelper(read)})`; + case 10: + return `(${this.PEHelper(read)}%${this.PEHelper(read)})`; + case 11: + return `Math.abs(${this.PEHelper(read)})`; + case 12: + return `Math.round(${this.PEHelper(read)})`; + case 13: + return `Math.cos(${this.PEHelper(read)})`; + default: + throw new Error("unexpected case found!"); + + } + } +} + +export{ AVoice as AVoice }; diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 42717deb..feba9584 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -1,6 +1,6 @@ "use strict"; import{ Message }from"./message.js"; -import{ AVoice }from"./audio/audio.js"; +import{ AVoice }from"./audio/voice.js"; import{ Contextmenu }from"./contextmenu.js"; import{ Guild }from"./guild.js"; import{ Localuser }from"./localuser.js"; @@ -1403,7 +1403,12 @@ class Channel extends SnowFlake{ ); } notify(message: Message, deep = 0){ - AVoice.noises(this.localuser.getNotificationSound()); + if(this.localuser.play){ + const voice=this.localuser.play.audios.get(this.localuser.getNotificationSound()); + if(voice){ + voice.play(); + } + } if(!("Notification" in window)){ }else if(Notification.permission === "granted"){ let noticontent: string | undefined | null = message.content.textContent; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index b7b4087c..8d6cf4c7 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -1,7 +1,7 @@ import{ Guild }from"./guild.js"; import{ Channel }from"./channel.js"; import{ Direct }from"./direct.js"; -import{ AVoice }from"./audio/audio.js"; +import{ AVoice }from"./audio/voice.js"; import{ User }from"./user.js"; import{ getapiurls, SW }from"./utils/utils.js"; import { getBulkInfo, setTheme, Specialuser } from "./utils/utils.js"; @@ -14,6 +14,7 @@ import { Role } from "./role.js"; import { VoiceFactory } from "./voice.js"; import { I18n, langmap } from "./i18n.js"; import { Emoji } from "./emoji.js"; +import { Play } from "./audio/play.js"; const wsCodesRetry = new Set([4000,4001,4002, 4003, 4005, 4007, 4008, 4009]); @@ -40,6 +41,7 @@ class Localuser{ channelids: Map = new Map(); readonly userMap: Map = new Map(); voiceFactory?:VoiceFactory; + play?:Play; instancePing = { name: "Unknown", }; @@ -51,6 +53,9 @@ class Localuser{ this.userinfo.localuserStore = e; } constructor(userinfo: Specialuser | -1){ + Play.playURL("/audio/sounds.jasf").then((_)=>{ + this.play=_; + }) if(userinfo === -1){ return; } @@ -1234,8 +1239,7 @@ class Localuser{ } { const sounds = AVoice.sounds; - tas - .addSelect( + tas.addSelect( I18n.getTranslation("localuser.notisound"), _=>{ this.setNotificationSound(sounds[_]); @@ -1244,7 +1248,12 @@ class Localuser{ { defaultIndex: sounds.indexOf(this.getNotificationSound()) } ) .watchForChange(_=>{ - AVoice.noises(sounds[_]); + if(this.play){ + const voice=this.play.audios.get(sounds[_]) + if(voice){ + voice.play(); + } + } }); } diff --git a/src/webpage/utils/binaryUtils.ts b/src/webpage/utils/binaryUtils.ts index 322f192f..f2c7c3cb 100644 --- a/src/webpage/utils/binaryUtils.ts +++ b/src/webpage/utils/binaryUtils.ts @@ -20,6 +20,11 @@ class BinRead{ readString16(){ return this.readStringNo(this.read16()); } + readFloat32(){ + const float = this.view.getFloat32(this.i); + this.i += 4; + return float; + } readStringNo(length: number){ const array = new Uint8Array(length); for(let i = 0; i < length; i++){ @@ -38,6 +43,10 @@ class BinWrite{ this.buffer=new ArrayBuffer(maxSize); this.view=new DataView(this.buffer, 0); } + write32Float(numb:number){ + this.view.setFloat32(this.i,numb); + this.i+=4; + } write16(numb:number){ this.view.setUint16(this.i,numb); this.i+=2; From 8ff8ecd59dff761604dd1b6c88a63e353dfb4479 Mon Sep 17 00:00:00 2001 From: MathMan05 <73901602+MathMan05@users.noreply.github.com> Date: Sat, 30 Nov 2024 22:48:42 -0600 Subject: [PATCH 0011/1178] Update audio.md --- src/webpage/audio/audio.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpage/audio/audio.md b/src/webpage/audio/audio.md index 10ba3bdb..afbac10a 100644 --- a/src/webpage/audio/audio.md +++ b/src/webpage/audio/audio.md @@ -12,7 +12,7 @@ Given a non-zero length, this will parse the sounds as following: |instruction | description | | ---------- | ----------- | | 000 | read float32 and use as value | -| 001 | read time(it'll always be a value between 0 and 1) | +| 001 | read time(it'll be the time in seconds) | | 002 | read frequency in hz | | 003 | the constant PI | | 004 | Math.sin() on the following sequence | From 06940fe41f0a78988e92052cd17b7ddd46cf8668 Mon Sep 17 00:00:00 2001 From: MathMan05 <73901602+MathMan05@users.noreply.github.com> Date: Sat, 30 Nov 2024 22:49:10 -0600 Subject: [PATCH 0012/1178] Update audio.md --- src/webpage/audio/audio.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/webpage/audio/audio.md b/src/webpage/audio/audio.md index afbac10a..e97adb83 100644 --- a/src/webpage/audio/audio.md +++ b/src/webpage/audio/audio.md @@ -26,6 +26,7 @@ Given a non-zero length, this will parse the sounds as following: | 012 | round the next expression | | 013 | Math.cos() on the next expression | > note + > this is likely to expand in the future as more things are needed, but this is just how it is right now. Once you've read all of the sounds in the file, you can move on to parsing the tracks. From a22c2f10c09dacd28e7671b443fe35f2f04879db Mon Sep 17 00:00:00 2001 From: MathMan05 <73901602+MathMan05@users.noreply.github.com> Date: Sat, 30 Nov 2024 22:49:22 -0600 Subject: [PATCH 0013/1178] Update audio.md --- src/webpage/audio/audio.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webpage/audio/audio.md b/src/webpage/audio/audio.md index e97adb83..a14e732e 100644 --- a/src/webpage/audio/audio.md +++ b/src/webpage/audio/audio.md @@ -25,8 +25,8 @@ Given a non-zero length, this will parse the sounds as following: | 011 | absolute power of the next expression | | 012 | round the next expression | | 013 | Math.cos() on the next expression | -> note - +> note: +> > this is likely to expand in the future as more things are needed, but this is just how it is right now. Once you've read all of the sounds in the file, you can move on to parsing the tracks. From cc96fd559917e218fc9e2f3f72eddfebfda410fd Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 2 Dec 2024 13:19:56 +0100 Subject: [PATCH 0014/1178] Localisation updates from https://translatewiki.net. --- translations/de.json | 15 +++++++++++++-- translations/ko.json | 19 ++++++++++++++----- translations/ru.json | 31 +++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/translations/de.json b/translations/de.json index 80aa4c34..2e0d71cc 100644 --- a/translations/de.json +++ b/translations/de.json @@ -2,7 +2,8 @@ "@metadata": { "authors": [ "Booky", - "Brettchenweber" + "Brettchenweber", + "SomeRandomDeveloper" ] }, "readableName": "Deutsch", @@ -110,7 +111,12 @@ "serverName": "Name des Servers:", "yesDelete": "Ja, ich bin mir sicher", "noDelete": "Doch nicht", - "loadingDiscovery": "Lade..." + "loadingDiscovery": "Lade...", + "description:": "Beschreibung:", + "systemSelect:": "Kanal für Systemnachrichten:", + "sendrandomwelcome?": "Sende eine zufällige Nachricht, wenn jemand dieser Gilde beitritt", + "helpTips?": "Sende hilfreiche Tipps für deine Gilde!", + "defaultNoti": "Lege die Standardbenachrichtigungseinstellungen deiner Gilde fest!" }, "role": { "color": "Farbe", @@ -120,5 +126,10 @@ "localuser": { "privacyPolcyURL": "Datenschutzerklärung:", "TOSURL": "Nutzungsbedingungen:" + }, + "invite": { + "channel:": "Kanal:", + "inviteMaker": "Einladungsgenerator", + "createInvite": "Einladung erstellen" } } diff --git a/translations/ko.json b/translations/ko.json index 45116978..76710d9a 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -1,6 +1,7 @@ { "@metadata": { "authors": [ + "Suleiman the Magnificent Television", "Ykhwong" ] }, @@ -72,7 +73,7 @@ "nsfw:": "NSFW:", "selectType": "채널 유형 선택", "selectName": "채널 이름", - "selectCatName": "채널 이름", + "selectCatName": "분류 이름", "createChannel": "채널 만들기", "createCatagory": "분류 만들기" }, @@ -114,12 +115,15 @@ "region:": "지역:", "roles": "역할", "all": "모두", - "none": "노드", + "none": "없음", "confirmLeave": "떠나시겠습니까?", "yesLeave": "네, 확실합니다", "serverName": "서버 이름:", "yesDelete": "네, 확실합니다", - "loadingDiscovery": "불러오는 중..." + "loadingDiscovery": "불러오는 중...", + "default": "기본값 ($1)", + "description:": "설명:", + "systemSelect:": "시스템 메시지 채널:" }, "role": { "displaySettings": "표시 설정", @@ -208,14 +212,18 @@ "alreadyJoined": "이미 참여했습니다", "accept": "수락", "longInvitedBy": "$1님이 당신을 $2에 초대했습니다", - "inviteLinkCode": "초대 링크/코드" + "inviteLinkCode": "초대 링크/코드", + "channel:": "채널:", + "createInvite": "초대장 만들기" }, "friends": { "blocked": "차단됨", "blockedusers": "차단된 사용자:", "addfriend": "친구 추가", + "addfriendpromt": "사용자 이름으로 친구 추가:", "notfound": "사용자를 찾을 수 없습니다", "pending": "보류 중", + "pending:": "대기 중인 친구 요청:", "all": "모두", "all:": "모든 친구:", "online": "온라인", @@ -226,7 +234,8 @@ "DMs": { "copyId": "DM ID 복사", "markRead": "읽은 것으로 표시", - "close": "DM 닫기" + "close": "DM 닫기", + "name": "직신" }, "user": { "copyId": "사용자 ID 복사", diff --git a/translations/ru.json b/translations/ru.json index 28f989d7..90c9cb2a 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -10,7 +10,7 @@ "StealthTheAngryBird" ] }, - "readableName": "Английский", + "readableName": "Русский", "reply": "Ответить", "copyrawtext": "Скопировать текст", "copymessageid": "Копировать ID сообщения", @@ -232,7 +232,16 @@ "create": "Создать гильдию", "loadingDiscovery": "Загрузка...", "disoveryTitle": "Путешествие по гильдиям ($1) {{PLURAL:$1|запись|записи|записей}}", - "default": "По умолчанию ($1)" + "emptytitle": "Странное место", + "emptytext": "Вы в странном положении, в этой гильдии нет каналов.", + "default": "По умолчанию ($1)", + "description:": "Описание:", + "systemSelect:": "Канал системных сообщений:", + "sendrandomwelcome?": "Отправлять случайное сообщение, когда кто-то присоединяется к этой гильдии", + "stickWelcomeReact?": "Поощряйте участников вашей гильдии отправлять стикер, когда кто-то присоединяется!", + "boostMessage?": "Отправляйте сообщение, когда кто-то бустит вашу гильдию!", + "helpTips?": "Отправьте полезные советы для вашей гильдии!", + "defaultNoti": "Установите настройки уведомлений по умолчанию для вашей гильдии!" }, "role": { "displaySettings": "Настройки отображения", @@ -346,13 +355,26 @@ "longInvitedBy": "Пользователь $1 пригласил вас на $2", "loginOrCreateAccount": "Войдите или создайте аккаунт ⇌", "joinUsing": "Присоединиться с помощью приглашения", - "inviteLinkCode": "Ссылка-приглашение/Код" + "inviteLinkCode": "Ссылка-приглашение/Код", + "subtext": "до $1 в $2", + "expireAfter": "Истекает через:", + "channel:": "Канал:", + "inviteMaker": "Создатель приглашений", + "createInvite": "Создать приглашение" }, "friends": { + "blocked": "Заблокированные", + "blockedusers": "Заблокированные пользователи:", "addfriend": "Добавить в друзья", "addfriendpromt": "Добавить друзей по имени пользователя:", "notfound": "Пользователь не найден", + "discnotfound": "Дискриминатор не найден:", + "pending": "Ожидающие", + "pending:": "Ожидающиеся заявки в друзья:", + "all": "Все", "all:": "Все друзья:", + "online": "В сети", + "online:": "Друзья в сети:", "friendlist": "Список друзей", "friends": "Друзья" }, @@ -360,7 +382,8 @@ "DMs": { "copyId": "Копировать ID ЛС", "markRead": "Пометить как прочитанное", - "close": "Закрыть ЛС" + "close": "Закрыть ЛС", + "name": "Личные сообщения" }, "user": { "copyId": "Скопировать ID пользователя", From d80d0b24e4e0407a4ad5dbe67b16fcccf48032a0 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 5 Dec 2024 13:20:03 +0100 Subject: [PATCH 0015/1178] Localisation updates from https://translatewiki.net. --- translations/ko.json | 3 ++- translations/lt.json | 3 ++- translations/qqq.json | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/translations/ko.json b/translations/ko.json index 76710d9a..c01599ef 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -1,11 +1,12 @@ { "@metadata": { "authors": [ + "McDutchie", "Suleiman the Magnificent Television", "Ykhwong" ] }, - "readableName": "영어", + "readableName": "한국어", "reply": "답변", "copymessageid": "메시지 ID 복사", "permissions": { diff --git a/translations/lt.json b/translations/lt.json index 2556df8b..9a0ff5a9 100644 --- a/translations/lt.json +++ b/translations/lt.json @@ -1,10 +1,11 @@ { "@metadata": { "authors": [ + "McDutchie", "Nokeoo" ] }, - "readableName": "Anglų", + "readableName": "Lietuvių", "reply": "Atsakyti", "copyrawtext": "Kopijuoti neapdorotą tekstą", "copymessageid": "Kopijuoti žinutės id", diff --git a/translations/qqq.json b/translations/qqq.json index 04e5e26c..dfb94b55 100644 --- a/translations/qqq.json +++ b/translations/qqq.json @@ -4,10 +4,11 @@ "locale": "en", "comment": "Don't know how often I'll update this top part lol", "authors": [ - "MathMan05" + "MathMan05", + "McDutchie" ] }, - "readableName": "This should be the name of the language in the language, please do not translate english into the language for this name", + "readableName": "{{doc-important|This should be the name of the language you are translating into, in that language. Please DO NOT translate this into your language’s word for “English”!}}", "htmlPages": { "box1Items": "this string is slightly atypical, it has a list of items separated by |, please try to keep the same list size as this" }, From 127a9e8250e5285303c2e81199d0e96af1d8edc8 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Mon, 9 Dec 2024 14:51:24 -0600 Subject: [PATCH 0016/1178] various improvements and fixes fixes a DM bug, and improves mention handling --- src/webpage/channel.ts | 39 ++++++++++++++++++++++++--------------- src/webpage/direct.ts | 24 +++++++++++++++--------- src/webpage/guild.ts | 25 ++++++++++++++++++++----- src/webpage/localuser.ts | 3 +++ src/webpage/message.ts | 6 +++++- src/webpage/style.css | 21 +++++++++++++++++---- 6 files changed, 84 insertions(+), 34 deletions(-) diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index feba9584..779ade6b 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -38,7 +38,7 @@ class Channel extends SnowFlake{ position: number = 0; lastreadmessageid: string | undefined; lastmessageid: string | undefined; - mentions!: number; + mentions=0; lastpin!: string; move_id?: string; typing!: number; @@ -518,9 +518,7 @@ class Channel extends SnowFlake{ }; }else{ div.classList.add("channel"); - if(this.hasunreads){ - div.classList.add("cunread"); - } + this.unreads(); Channel.contextmenu.bindContextmenu(div, this,undefined); if(admin){ this.coatDropDiv(div); @@ -624,7 +622,9 @@ class Channel extends SnowFlake{ } } readbottom(){ + this.mentions=0; if(!this.hasunreads){ + this.guild.unreads(); return; } fetch( @@ -637,10 +637,9 @@ class Channel extends SnowFlake{ ); this.lastreadmessageid = this.lastmessageid; this.guild.unreads(); - if(this.myhtml){ - this.myhtml.classList.remove("cunread"); - } + this.unreads(); } + coatDropDiv(div: HTMLDivElement, container: HTMLElement | boolean = false){ div.addEventListener("dragenter", event=>{ console.log("enter"); @@ -1351,6 +1350,20 @@ class Channel extends SnowFlake{ }); } } + unreads(){ + if(!this.hasunreads){ + if(this.myhtml){ + this.myhtml.classList.remove("cunread","mentioned"); + } + }else{ + if(this.myhtml){ + this.myhtml.classList.add("cunread"); + } + if(this.mentions!==0){ + this.myhtml?.classList.add("mentioned") + } + } + } messageCreate(messagep: messageCreateJson): void{ if(!this.hasPermission("VIEW_CHANNEL")){ return; @@ -1361,19 +1374,15 @@ class Channel extends SnowFlake{ this.idToNext.set(this.lastmessageid, messagez.id); this.idToPrev.set(messagez.id, this.lastmessageid); } - + if(messagez.mentionsuser(this.localuser.user)&&messagez.author!==this.localuser.user){ + this.mentions++; + } this.lastmessageid = messagez.id; if(messagez.author === this.localuser.user){ this.lastreadmessageid = messagez.id; - if(this.myhtml){ - this.myhtml.classList.remove("cunread"); - } - }else{ - if(this.myhtml){ - this.myhtml.classList.add("cunread"); - } } + this.unreads(); this.guild.unreads(); if(this === this.localuser.channelfocus){ if(!this.infinitefocus){ diff --git a/src/webpage/direct.ts b/src/webpage/direct.ts index d3c03244..3cf2a18e 100644 --- a/src/webpage/direct.ts +++ b/src/webpage/direct.ts @@ -41,6 +41,7 @@ class Direct extends Guild{ const thischannel = new Group(json, this); this.channelids[thischannel.id] = thischannel; this.channels.push(thischannel); + this.localuser.channelids.set(thischannel.id, thischannel); this.sortchannels(); this.printServers(); return thischannel; @@ -282,8 +283,17 @@ class Direct extends Guild{ channelTopic.append(add); } } + get mentions(){ + let mentions=0; + for(const thing of this.localuser.inrelation){ + if(thing.relationshipType===3){ + mentions+=1; + } + } + return mentions; + } giveMember(_member: memberjson){ - console.error("not a real guild, can't give member object"); + throw new Error("not a real guild, can't give member object"); } getRole(/* ID: string */){ return null; @@ -429,6 +439,7 @@ class Group extends Channel{ } messageCreate(messagep: { d: messagejson }){ + this.mentions++; const messagez = new Message(messagep.d, this); if(this.lastmessageid){ this.idToNext.set(this.lastmessageid, messagez.id); @@ -461,20 +472,15 @@ class Group extends Channel{ } this.unreads(); if(messagez.author === this.localuser.user){ + this.mentions=0; return; } - if( - this.localuser.lookingguild?.prevchannel === this && - document.hasFocus() - ){ + if(this.localuser.lookingguild?.prevchannel === this && document.hasFocus()){ return; } if(this.notification === "all"){ this.notify(messagez); - }else if( - this.notification === "mentions" && - messagez.mentionsuser(this.localuser.user) - ){ + }else if(this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)){ this.notify(messagez); } } diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index d50274ea..702ef0aa 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -588,27 +588,42 @@ class Guild extends SnowFlake{ headers: this.headers, }); } + get mentions(){ + let mentions=0; + for(const thing of this.channels){ + mentions+=thing.mentions; + } + return mentions; + } unreads(html?: HTMLElement | undefined){ if(html){ this.html = html; }else{ html = this.html; } + if(!html){ + return; + } let read = true; + let mentions=this.mentions; for(const thing of this.channels){ if(thing.hasunreads){ - console.log(thing); read = false; break; } } - if(!html){ - return; + const noti=html.children[0]; + if(mentions!==0){ + noti.classList.add("pinged"); + noti.textContent=""+mentions; + }else{ + noti.textContent=""; + noti.classList.remove("pinged"); } if(read){ - html.children[0].classList.remove("notiunread"); + noti.classList.remove("notiunread"); }else{ - html.children[0].classList.add("notiunread"); + noti.classList.add("notiunread"); } } getHTML(){ diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 8d6cf4c7..50dcd89a 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -551,6 +551,9 @@ class Localuser{ user.relationshipType = temp.d.type; this.inrelation.add(user); this.relationshipsUpdate(); + const me=this.guildids.get("@me"); + if(!me)break; + me.unreads(); break; } case "RELATIONSHIP_REMOVE":{ diff --git a/src/webpage/message.ts b/src/webpage/message.ts index d13cc3ce..5517a938 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -243,7 +243,11 @@ class Message extends SnowFlake{ if(userd instanceof User){ return this.mentions.includes(userd); }else if(userd instanceof Member){ - return this.mentions.includes(userd.user); + if(this.mentions.includes(userd.user)){ + return true + }else{ + return !new Set(this.mentions).isDisjointFrom(new Set(userd.roles));//if the message mentions a role the user has + } }else{ return false; } diff --git a/src/webpage/style.css b/src/webpage/style.css index 6e94355b..96f3b0a0 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -611,6 +611,10 @@ span.instanceStatus { border-radius: 4px; transition: transform .2s, height .2s; } +.servernoti:hover .unread.pinged { + transform: translate(34px, 14px); + height: 20px; +} .servernoti:hover .unread { transform: translate(-12px, 12px); height: 24px; @@ -618,6 +622,11 @@ span.instanceStatus { .serveropen .unread { transform: translate(-12px, 8px) !important; height: 32px !important; + width: 8px !important; + +} +.serveropen .unread.pinged{ + color: transparent; } .notiunread { transform: translate(-12px, 20px); @@ -625,18 +634,19 @@ span.instanceStatus { #sentdms { position: relative; } -.unread.pinged, .servernoti:hover .unread.pinged { +.unread.pinged{ height: 16px; width: 16px; - transform: translate(28px, 28px); + transform: translate(34px, 34px); background: var(--red); font-size: .75rem; font-weight: bold; line-height: 15px; text-align: center; - border: 4px solid var(--servers-bg); - border-radius: 50%; + /* border: 4px solid var(--servers-bg); */ + /* border-radius: 50%; */ pointer-events: none; + z-index: 10; } /* Channel Panel */ @@ -711,6 +721,9 @@ span.instanceStatus { background: var(--primary-text); border-radius: 50%; } +.cunread.mentioned:after{ + background: var(--red); +} .space { flex: none; height: 1em; From 0ced3f594c06e4db3bb67ca2ae7ba85361ab7695 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Tue, 10 Dec 2024 11:44:56 -0600 Subject: [PATCH 0017/1178] bug fix --- src/webpage/channel.ts | 5 ++++- src/webpage/message.ts | 6 ++++++ src/webpage/user.ts | 11 ++++++++++- translations/en.json | 4 +++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 779ade6b..3031b08a 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -761,7 +761,7 @@ class Channel extends SnowFlake{ typebox.classList.remove("typeboxreplying"); } } - async getmessage(id: string): Promise{ + async getmessage(id: string): Promise{ const message = this.messages.get(id); if(message){ return message; @@ -771,6 +771,9 @@ class Channel extends SnowFlake{ { headers: this.headers } ); const json = await gety.json(); + if(json.length===0){ + return undefined; + } return new Message(json[0], this); } } diff --git a/src/webpage/message.ts b/src/webpage/message.ts index 5517a938..540ef402 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -439,6 +439,12 @@ class Message extends SnowFlake{ replyline.classList.add("flexltr","replyflex"); // TODO: Fix this this.channel.getmessage(this.message_reference.message_id).then(message=>{ + if(!message){ + minipfp.remove(); + username.textContent=I18n.getTranslation("message.deleted"); + username.classList.remove("username"); + return; + } if(message.author.relationshipType === 2){ username.textContent = "Blocked user"; return; diff --git a/src/webpage/user.ts b/src/webpage/user.ts index 003fe4a7..3126ebde 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -164,7 +164,12 @@ class User extends SnowFlake{ this.contextmenu.addbutton(()=>I18n.getTranslation("user.friendReq"), function(this: User){ this.changeRelationship(1); },null,function(){ - return this.relationshipType===0; + return this.relationshipType===0||this.relationshipType===3; + }); + this.contextmenu.addbutton(()=>I18n.getTranslation("friends.removeFriend"), function(this: User){ + this.changeRelationship(0); + },null,function(){ + return this.relationshipType===1; }); this.contextmenu.addbutton( ()=>I18n.getTranslation("user.kick"), @@ -363,11 +368,15 @@ class User extends SnowFlake{ } if(member){ member.bind(html); + }else{ + User.contextmenu.bindContextmenu(html, this, undefined); } }) .catch(err=>{ console.log(err); }); + }else{ + User.contextmenu.bindContextmenu(html, this, undefined); } if(guild){ this.profileclick(html, guild); diff --git a/translations/en.json b/translations/en.json index 3bf4cde3..1a16deed 100644 --- a/translations/en.json +++ b/translations/en.json @@ -322,7 +322,8 @@ "reactionAdd":"Add reaction", "delete":"Delete message", "edit":"Edit message", - "edited":"(edited)" + "edited":"(edited)", + "deleted":"Deleted message" }, "instanceStats":{ "name":"Instance stats: $1", @@ -364,6 +365,7 @@ "blocked":"Blocked", "blockedusers":"Blocked Users:", "addfriend":"Add Friend", + "removeFriend":"Remove Friend", "addfriendpromt":"Add friends by username:", "notfound":"User not found", "discnotfound":"Discriminator not found", From d573a061887289b93c823954f95fe5a61a21f6f8 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Tue, 10 Dec 2024 11:55:14 -0600 Subject: [PATCH 0018/1178] fix stupid invite URL --- src/webpage/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpage/home.html b/src/webpage/home.html index 8189617a..34347044 100644 --- a/src/webpage/home.html +++ b/src/webpage/home.html @@ -18,7 +18,7 @@

Jank Client

- Spacebar Guild From 8e7aea193ccc8f8ead7122813ce65e76b12c9eca Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 11 Dec 2024 21:07:59 -0600 Subject: [PATCH 0019/1178] per guild profiles --- src/webpage/channel.ts | 2 +- src/webpage/guild.ts | 7 +- src/webpage/jsontypes.ts | 4 +- src/webpage/localuser.ts | 15 ++- src/webpage/member.ts | 260 ++++++++++++++++++++++++++++++++++++++- src/webpage/user.ts | 165 ++++++++++++++++++++----- translations/en.json | 6 +- 7 files changed, 414 insertions(+), 45 deletions(-) diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 3031b08a..a9baa875 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -1440,7 +1440,7 @@ class Channel extends SnowFlake{ } const notification = new Notification(this.notititle(message), { body: noticontent, - icon: message.author.getpfpsrc(), + icon: message.author.getpfpsrc(this.guild), image: imgurl, }); notification.addEventListener("click", _=>{ diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index 702ef0aa..dac23be3 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -342,6 +342,7 @@ class Guild extends SnowFlake{ } }); } + this.perminfo ??= { channels: {} }; for(const thing of json.channels){ const temp = new Channel(thing, this); @@ -436,9 +437,9 @@ class Guild extends SnowFlake{ calculateReorder(){ let position = -1; const build: { - id: string; - position: number | undefined; - parent_id: string | undefined; + id: string; + position: number | undefined; + parent_id: string | undefined; }[] = []; for(const thing of this.headchannels){ const thisthing: { diff --git a/src/webpage/jsontypes.ts b/src/webpage/jsontypes.ts index 767e91b1..45e10d8f 100644 --- a/src/webpage/jsontypes.ts +++ b/src/webpage/jsontypes.ts @@ -141,7 +141,7 @@ type userjson = { premium_since: string; premium_type: number; theme_colors: string; - pronouns: string; + pronouns?: string; badge_ids: string[]; }; type memberjson = { @@ -149,6 +149,8 @@ type memberjson = { id: string; user: userjson | null; guild_id: string; + avatar?:string; + banner?:string; guild: { id: string; } | null; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 50dcd89a..a59fd068 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -90,6 +90,7 @@ class Localuser{ this.userinfo.username = this.user.username; this.userinfo.id = this.user.id; this.userinfo.pfpsrc = this.user.getpfpsrc(); + this.status = this.ready.d.user_settings.status; this.channelfocus = undefined; this.lookingguild = undefined; @@ -477,8 +478,10 @@ class Localuser{ temp.d.guild_id ??= "@me"; const channel = this.channelids.get(temp.d.channel_id); if(!channel)break; + const message = channel.messages.get(temp.d.message_id); if(!message)break; + message.reactionRemove(temp.d.emoji, temp.d.user_id); } break; @@ -739,7 +742,7 @@ class Localuser{ for(const member of list){ const memberdiv=document.createElement("div"); - const pfp=await member.user.buildstatuspfp(); + const pfp=await member.user.buildstatuspfp(member); const username=document.createElement("span"); username.classList.add("ellipsis"); username.textContent=member.name; @@ -1094,10 +1097,10 @@ class Localuser{ } } updateProfile(json: { - bio?: string; - pronouns?: string; - accent_color?: number; - }){ + bio?: string; + pronouns?: string; + accent_color?: number; + }){ fetch(this.info.api + "/users/@me/profile", { method: "PATCH", headers: this.headers, @@ -1180,7 +1183,7 @@ class Localuser{ const pronounbox = settingsLeft.addTextInput( I18n.getTranslation("pronouns"), _=>{ - if(newpronouns || newbio || changed){ + if(newpronouns!==undefined||newbio!==undefined||changed!==undefined){ this.updateProfile({ pronouns: newpronouns, bio: newbio, diff --git a/src/webpage/member.ts b/src/webpage/member.ts index 2afb7882..aa4fbaf2 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -4,7 +4,7 @@ import{ Guild }from"./guild.js"; import{ SnowFlake }from"./snowflake.js"; import{ memberjson, presencejson }from"./jsontypes.js"; import { I18n } from "./i18n.js"; -import { Dialog } from "./settings.js"; +import { Dialog, Options } from "./settings.js"; class Member extends SnowFlake{ static already = {}; @@ -12,8 +12,12 @@ class Member extends SnowFlake{ user: User; roles: Role[] = []; nick!: string; - + avatar:void|string=undefined; + banner:void|string=undefined; private constructor(memberjson: memberjson, owner: Guild){ + if(memberjson.id==="1086860370880362328"&&owner.id==="1006649183970562092"){ + console.trace(memberjson); + } super(memberjson.id); this.owner = owner; if(this.localuser.userMap.has(memberjson.id)){ @@ -59,6 +63,251 @@ class Member extends SnowFlake{ this.user.members.delete(this.guild); this.guild.members.delete(this); } + getpfpsrc():string{ + if(this.hypotheticalpfp&&this.avatar){ + return this.avatar; + } + if(this.avatar !== undefined&&this.avatar!==null){ + return`${this.info.cdn}/guilds/${this.guild.id}/users/${this.id}/avatars${ + this.avatar + }.${this.avatar.startsWith("a_")?"gif":"png"}`; + } + return this.user.getpfpsrc(); + } + getBannerUrl():string|undefined{ + if(this.hypotheticalbanner&&this.banner){ + return this.banner; + } + if(this.banner){ + return `${this.info.cdn}/banners/${this.guild.id}/${ + this.banner + }.${this.banner.startsWith("a_")?"gif":"png"}`;; + }else{ + return undefined; + } + } + joined_at!:string; + premium_since!:string; + deaf!:boolean; + mute!:boolean; + pending!:boolean + clone(){ + return new Member({ + id:this.id+"#clone", + user:this.user.tojson(), + guild_id:this.guild.id, + guild:{id:this.guild.id}, + avatar:this.avatar as (string|undefined), + banner:this.banner as (string|undefined), + //TODO presence + nick:this.nick, + roles:this.roles.map(_=>_.id), + joined_at:this.joined_at, + premium_since:this.premium_since, + deaf:this.deaf, + mute:this.mute, + pending:this.pending + + },this.owner) + } + pronouns?:string; + bio?:string; + hypotheticalpfp=false; + hypotheticalbanner=false; + accent_color?:number; + get headers(){ + return this.owner.headers; + } + + updatepfp(file: Blob): void{ + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = ()=>{ + fetch(this.info.api + `/guilds/${this.guild.id}/members/${this.id}/`, { + method: "PATCH", + headers: this.headers, + body: JSON.stringify({ + avatar: reader.result, + }), + }); + }; + } + updatebanner(file: Blob | null): void{ + if(file){ + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = ()=>{ + fetch(this.info.api + `/guilds/${this.guild.id}/profile/${this.id}`, { + method: "PATCH", + headers: this.headers, + body: JSON.stringify({ + banner: reader.result, + }), + }); + }; + }else{ + fetch(this.info.api + `/guilds/${this.guild.id}/profile/${this.id}`, { + method: "PATCH", + headers: this.headers, + body: JSON.stringify({ + banner: null, + }), + }); + } + } + + updateProfile(json: { + bio?: string|null; + pronouns?: string|null; + nick?:string|null; + }){ + console.log(JSON.stringify(json)); + /* + if(json.bio===""){ + json.bio=null; + } + if(json.pronouns===""){ + json.pronouns=null; + } + if(json.nick===""){ + json.nick=null; + } + */ + fetch(this.info.api + `/guilds/${this.guild.id}/profile/${this.id}`, { + method: "PATCH", + headers: this.headers, + body: JSON.stringify(json), + }); + } + editProfile(options:Options){ + if(this.hasPermission("CHANGE_NICKNAME")){ + const hypotheticalProfile = document.createElement("div"); + let file: undefined | File | null; + let newpronouns: string | undefined; + let newbio: string | undefined; + let nick:string|undefined; + const hypomember = this.clone(); + + let color: string; + async function regen(){ + hypotheticalProfile.textContent = ""; + const hypoprofile = await hypomember.user.buildprofile(-1, -1,hypomember); + + hypotheticalProfile.appendChild(hypoprofile); + } + regen(); + const settingsLeft = options.addOptions(""); + const settingsRight = options.addOptions(""); + settingsRight.addHTMLArea(hypotheticalProfile); + + const nicky=settingsLeft.addTextInput(I18n.getTranslation("member.nick:"),()=>{},{ + initText:this.nick||"" + }); + nicky.watchForChange(_=>{ + hypomember.nick=_; + nick=_; + regen(); + }) + + const finput = settingsLeft.addFileInput( + I18n.getTranslation("uploadPfp"), + _=>{ + if(file){ + this.updatepfp(file); + } + }, + { clear: true } + ); + finput.watchForChange(_=>{ + if(!_){ + file = null; + hypomember.avatar = undefined; + hypomember.hypotheticalpfp = true; + regen(); + return; + } + if(_.length){ + file = _[0]; + const blob = URL.createObjectURL(file); + hypomember.avatar = blob; + hypomember.hypotheticalpfp = true; + regen(); + } + }); + let bfile: undefined | File | null; + const binput = settingsLeft.addFileInput( + I18n.getTranslation("uploadBanner"), + _=>{ + if(bfile !== undefined){ + this.updatebanner(bfile); + } + }, + { clear: true } + ); + binput.watchForChange(_=>{ + if(!_){ + bfile = null; + hypomember.banner = undefined; + hypomember.hypotheticalbanner = true; + regen(); + return; + } + if(_.length){ + bfile = _[0]; + const blob = URL.createObjectURL(bfile); + hypomember.banner = blob; + hypomember.hypotheticalbanner = true; + regen(); + } + }); + let changed = false; + const pronounbox = settingsLeft.addTextInput( + I18n.getTranslation("pronouns"), + _=>{ + if(newpronouns!==undefined||newbio!==undefined||changed!==undefined){ + this.updateProfile({ + pronouns: newpronouns, + bio: newbio, + //accent_color: Number.parseInt("0x" + color.substr(1), 16), + nick + }); + } + }, + { initText: this.pronouns } + ); + pronounbox.watchForChange(_=>{ + hypomember.pronouns = _; + newpronouns = _; + regen(); + }); + const bioBox = settingsLeft.addMDInput(I18n.getTranslation("bio"), _=>{}, { + initText: this.bio, + }); + bioBox.watchForChange(_=>{ + newbio = _; + hypomember.bio = _; + regen(); + }); + return;//Returns early to stop errors + if(this.accent_color){ + color = "#" + this.accent_color.toString(16); + }else{ + color = "transparent"; + } + const colorPicker = settingsLeft.addColorInput( + I18n.getTranslation("profileColor"), + _=>{}, + { initColor: color } + ); + colorPicker.watchForChange(_=>{ + console.log(); + color = _; + hypomember.accent_color = Number.parseInt("0x" + _.substr(1), 16); + changed = true; + regen(); + }); + } + } update(memberjson: memberjson){ this.roles=[]; for(const key of Object.keys(memberjson)){ @@ -114,11 +363,16 @@ class Member extends SnowFlake{ owner.members.add(memb); return memb; }else if(memb instanceof Promise){ - return await memb; //I should do something else, though for now this is "good enough" + const member=await memb; //I should do something else, though for now this is "good enough"; + if(member){ + member.update(memberjson); + } + return member; }else{ if(memberjson.presence){ memb.getPresence(memberjson.presence); } + memb.update(memberjson); return memb; } }else{ diff --git a/src/webpage/user.ts b/src/webpage/user.ts index 3126ebde..fa6addb5 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -9,6 +9,7 @@ import { Role } from "./role.js"; import { Search } from "./search.js"; import { I18n } from "./i18n.js"; import { Direct } from "./direct.js"; +import { Settings } from "./settings.js"; class User extends SnowFlake{ owner: Localuser; @@ -19,7 +20,7 @@ class User extends SnowFlake{ relationshipType: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0; bio!: MarkDown; discriminator!: string; - pronouns!: string; + pronouns?: string; bot!: boolean; public_flags!: number; accent_color!: number; @@ -57,11 +58,10 @@ class User extends SnowFlake{ } } - clone(): User{ - return new User( - { + tojson():userjson{ + return { username: this.username, - id: this.id + "#clone", + id: this.id, public_flags: this.public_flags, discriminator: this.discriminator, avatar: this.avatar, @@ -74,7 +74,14 @@ class User extends SnowFlake{ theme_colors: this.theme_colors, pronouns: this.pronouns, badge_ids: this.badge_ids, - }, + } + } + + clone(): User{ + const json=this.tojson(); + json.id+="#clone"; + return new User( + json, this.owner ); } @@ -189,6 +196,20 @@ class User extends SnowFlake{ return us.hasPermission("KICK_MEMBERS") || false; } ); + + this.contextmenu.addbutton( + ()=>I18n.getTranslation("user.editServerProfile"), + function(this: User, member: Member | undefined){ + if(!member) return; + const settings=new Settings(I18n.getTranslation("user.editServerProfile")); + member.editProfile(settings.addButton(I18n.getTranslation("user.editServerProfile"),{ltr:true})); + settings.show(); + }, + null, + member=>{ + return !!member; + } + ); this.contextmenu.addbutton( ()=>I18n.getTranslation("user.ban"), function(this: User, member: Member | undefined){ @@ -319,19 +340,32 @@ class User extends SnowFlake{ } } - buildpfp(): HTMLImageElement{ + buildpfp(guild:Guild|void|Member|null): HTMLImageElement{ const pfp = document.createElement("img"); pfp.loading = "lazy"; pfp.src = this.getpfpsrc(); pfp.classList.add("pfp"); pfp.classList.add("userid:" + this.id); + if(guild){ + (async()=>{ + if(guild instanceof Guild){ + const memb= await Member.resolveMember(this,guild) + if(!memb) return; + pfp.src = memb.getpfpsrc(); + }else{ + pfp.src = guild.getpfpsrc(); + } + + })(); + + } return pfp; } - async buildstatuspfp(): Promise{ + async buildstatuspfp(guild:Guild|void|Member|null): Promise{ const div = document.createElement("div"); div.classList.add("pfpDiv") - const pfp = this.buildpfp(); + const pfp = this.buildpfp(guild); div.append(pfp); const status = document.createElement("div"); status.classList.add("statusDiv"); @@ -423,11 +457,19 @@ class User extends SnowFlake{ } } } - - getpfpsrc(): string{ + /** + * @param guild this is an optional thing that'll get the src of the member if it exists, otherwise ignores it, this is meant to be fast, not accurate + */ + getpfpsrc(guild:Guild|void): string{ if(this.hypotheticalpfp && this.avatar){ return this.avatar; } + if(guild){ + const member=this.members.get(guild) + if(member instanceof Member){ + return member.getpfpsrc(); + } + } if(this.avatar !== null){ return`${this.info.cdn}/avatars/${this.id.replace("#clone", "")}/${ this.avatar @@ -441,12 +483,21 @@ class User extends SnowFlake{ async buildprofile( x: number, y: number, - guild: Guild | null = null + guild: Guild | null | Member = null ): Promise{ if(Contextmenu.currentmenu != ""){ Contextmenu.currentmenu.remove(); } - + const membres=(async ()=>{ + if(!guild) return; + let member:Member|undefined; + if(guild instanceof Guild){ + member=await Member.resolveMember(this,guild) + }else{ + member=guild; + } + return member; + })() const div = document.createElement("div"); if(this.accent_color){ @@ -457,20 +508,18 @@ class User extends SnowFlake{ }else{ div.style.setProperty("--accent_color", "transparent"); } - if(this.banner){ - const banner = document.createElement("img"); - let src: string; - if(!this.hypotheticalbanner){ - src = `${this.info.cdn}/avatars/${this.id.replace("#clone", "")}/${ - this.banner - }.png`; - }else{ - src = this.banner; + const banner=this.getBanner(guild); + div.append(banner); + membres.then(member=>{ + if(!member) return; + if(member.accent_color&&member.accent_color!==0){ + div.style.setProperty( + "--accent_color", + `#${member.accent_color.toString(16).padStart(6, "0")}` + ); } - banner.src = src; - banner.classList.add("banner"); - div.append(banner); - } + }) + if(x !== -1){ div.style.left = `${x}px`; div.style.top = `${y}px`; @@ -501,7 +550,7 @@ class User extends SnowFlake{ } } })(); - const pfp = await this.buildstatuspfp(); + const pfp = await this.buildstatuspfp(guild); div.appendChild(pfp); const userbody = document.createElement("div"); userbody.classList.add("flexttb","infosection"); @@ -516,16 +565,33 @@ class User extends SnowFlake{ userbody.appendChild(discrimatorhtml); const pronounshtml = document.createElement("p"); - pronounshtml.textContent = this.pronouns; + pronounshtml.textContent = this.pronouns||""; pronounshtml.classList.add("pronouns"); userbody.appendChild(pronounshtml); + membres.then(member=>{ + if(!member) return; + if(member.pronouns&&member.pronouns!==""){ + pronounshtml.textContent=member.pronouns; + } + }); + const rule = document.createElement("hr"); userbody.appendChild(rule); const biohtml = this.bio.makeHTML(); userbody.appendChild(biohtml); + + membres.then(member=>{ + if(!member)return; + if(member.bio&&member.bio!==""){ + //TODO make markdown take Guild + userbody.insertBefore(new MarkDown(member.bio,this.localuser).makeHTML(),biohtml); + biohtml.remove(); + } + }); + if(guild){ - Member.resolveMember(this, guild).then(member=>{ + membres.then(member=>{ if(!member)return; usernamehtml.textContent=member.name; const roles = document.createElement("div"); @@ -556,7 +622,48 @@ class User extends SnowFlake{ } return div; } + getBanner(guild:Guild|null|Member):HTMLImageElement{ + const banner = document.createElement("img"); + const bsrc=this.getBannerUrl(); + if(bsrc){ + banner.src = bsrc; + banner.classList.add("banner"); + } + + if(guild){ + if(guild instanceof Member){ + const bsrc=guild.getBannerUrl(); + if(bsrc){ + banner.src = bsrc; + banner.classList.add("banner"); + } + }else{ + Member.resolveMember(this,guild).then(memb=>{ + if(!memb) return; + const bsrc=memb.getBannerUrl(); + if(bsrc){ + banner.src = bsrc; + banner.classList.add("banner"); + } + }) + } + } + return banner + } + getBannerUrl():string|undefined{ + if(this.banner){ + if(!this.hypotheticalbanner){ + return `${this.info.cdn}/avatars/${this.id.replace("#clone", "")}/${ + this.banner + }.png`; + }else{ + return this.banner; + } + }else{ + return undefined; + } + } profileclick(obj: HTMLElement, guild?: Guild): void{ obj.onclick = (e: MouseEvent)=>{ this.buildprofile(e.clientX, e.clientY, guild); diff --git a/translations/en.json b/translations/en.json index 1a16deed..578933ae 100644 --- a/translations/en.json +++ b/translations/en.json @@ -396,7 +396,8 @@ "kick":"Kick member", "ban":"Ban member", "addRole":"Add roles", - "removeRole":"Remove roles" + "removeRole":"Remove roles", + "editServerProfile":"Edit server profile" }, "login":{ "checking":"Checking Instance", @@ -407,7 +408,8 @@ "member":{ "kick":"Kick $1 from $2", "reason:":"Reason:", - "ban":"Ban $1 from $2" + "ban":"Ban $1 from $2", + "nick:":"Nickname:" }, "uploadFilesText":"Upload your files here!", "errorReconnect":"Unable to connect to the server, retrying in **$1** seconds...", From a0e4888806c7ef113ef0b65a2ee8f72dd9247b0d Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 11 Dec 2024 21:21:11 -0600 Subject: [PATCH 0020/1178] tweaks --- src/webpage/guild.ts | 7 +++++++ src/webpage/member.ts | 7 ++++++- src/webpage/user.ts | 4 +--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index dac23be3..ae9f8618 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -43,6 +43,13 @@ class Guild extends SnowFlake{ this.setnotifcation(); }); + this.contextmenu.addbutton( + ()=>I18n.getTranslation("user.editServerProfile"), + function(){ + this.member.showEditProfile(); + } + ); + Guild.contextmenu.addbutton( ()=>I18n.getTranslation("guild.leave"), function(this: Guild){ diff --git a/src/webpage/member.ts b/src/webpage/member.ts index aa4fbaf2..0a617b10 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -4,7 +4,7 @@ import{ Guild }from"./guild.js"; import{ SnowFlake }from"./snowflake.js"; import{ memberjson, presencejson }from"./jsontypes.js"; import { I18n } from "./i18n.js"; -import { Dialog, Options } from "./settings.js"; +import { Dialog, Options, Settings } from "./settings.js"; class Member extends SnowFlake{ static already = {}; @@ -179,6 +179,11 @@ class Member extends SnowFlake{ body: JSON.stringify(json), }); } + showEditProfile(){ + const settings=new Settings(""); + this.editProfile(settings.addButton(I18n.getTranslation("user.editServerProfile"),{ltr:true})); + settings.show(); + } editProfile(options:Options){ if(this.hasPermission("CHANGE_NICKNAME")){ const hypotheticalProfile = document.createElement("div"); diff --git a/src/webpage/user.ts b/src/webpage/user.ts index fa6addb5..97733d8f 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -201,9 +201,7 @@ class User extends SnowFlake{ ()=>I18n.getTranslation("user.editServerProfile"), function(this: User, member: Member | undefined){ if(!member) return; - const settings=new Settings(I18n.getTranslation("user.editServerProfile")); - member.editProfile(settings.addButton(I18n.getTranslation("user.editServerProfile"),{ltr:true})); - settings.show(); + member.showEditProfile(); }, null, member=>{ From ac0901aa1c478f1fb0121f5b085f432b2e32043a Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 11 Dec 2024 21:44:50 -0600 Subject: [PATCH 0021/1178] fix invite page bugs --- src/webpage/invite.ts | 2 +- src/webpage/service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webpage/invite.ts b/src/webpage/invite.ts index fcc053b4..7dccc813 100644 --- a/src/webpage/invite.ts +++ b/src/webpage/invite.ts @@ -42,7 +42,7 @@ import { getBulkUsers, Specialuser } from "./utils/utils.js"; } await I18n.done; if(!joinable.length){ -document.getElementById("AcceptInvite")!.textContent = I18n.getTranslation("noAccount"); + document.getElementById("AcceptInvite")!.textContent = I18n.getTranslation("htmlPages.noAccount"); } const code = window.location.pathname.split("/")[2]; diff --git a/src/webpage/service.ts b/src/webpage/service.ts index b2bf2881..ea63eff6 100644 --- a/src/webpage/service.ts +++ b/src/webpage/service.ts @@ -68,7 +68,7 @@ function toPath(url:string):string{ const path=Url.pathname; if(path.startsWith("/channels")){ html="./index.html" - }else if(path.startsWith("/invite")){ + }else if(path.startsWith("/invite/")){ html="./invite.html" } } From 1f36db3d897b38e051faa1de0e2be84a6aa4a0e0 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 11 Dec 2024 22:05:23 -0600 Subject: [PATCH 0022/1178] more fixes! --- src/webpage/member.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/webpage/member.ts b/src/webpage/member.ts index 0a617b10..92def5d5 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -314,7 +314,9 @@ class Member extends SnowFlake{ } } update(memberjson: memberjson){ - this.roles=[]; + if(memberjson.roles){ + this.roles=[]; + } for(const key of Object.keys(memberjson)){ if(key === "guild" || key === "owner" || key === "user"){ continue; @@ -326,6 +328,12 @@ class Member extends SnowFlake{ if(!role)continue; this.roles.push(role); } + if(!this.user.bot){ + const everyone=this.guild.roleids.get(this.guild.id); + if(everyone&&(this.roles.indexOf(everyone)===-1)){ + this.roles.push(everyone) + } + } continue; } if(key === "presence"){ From 19076efbb3f00e46496acc4fcaa1aad20b977452 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 11 Dec 2024 22:21:45 -0600 Subject: [PATCH 0023/1178] more updates --- src/webpage/service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpage/service.ts b/src/webpage/service.ts index ea63eff6..8b6b6bf7 100644 --- a/src/webpage/service.ts +++ b/src/webpage/service.ts @@ -68,7 +68,7 @@ function toPath(url:string):string{ const path=Url.pathname; if(path.startsWith("/channels")){ html="./index.html" - }else if(path.startsWith("/invite/")){ + }else if(path.startsWith("/invite/")||path==="/invite"){ html="./invite.html" } } From ac57c8c8c4780ee7e8b33d1cc3ecf3aef3b00f8b Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Wed, 11 Dec 2024 22:53:17 -0600 Subject: [PATCH 0024/1178] delete stupid log --- src/webpage/member.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/webpage/member.ts b/src/webpage/member.ts index 92def5d5..6104e3e5 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -15,9 +15,6 @@ class Member extends SnowFlake{ avatar:void|string=undefined; banner:void|string=undefined; private constructor(memberjson: memberjson, owner: Guild){ - if(memberjson.id==="1086860370880362328"&&owner.id==="1006649183970562092"){ - console.trace(memberjson); - } super(memberjson.id); this.owner = owner; if(this.localuser.userMap.has(memberjson.id)){ From 5ac6da20251cf4874795dcb37b141dce7e39e2b5 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Dec 2024 13:24:30 +0100 Subject: [PATCH 0025/1178] Localisation updates from https://translatewiki.net. --- translations/ru.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/translations/ru.json b/translations/ru.json index 90c9cb2a..c58f75ab 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -324,7 +324,8 @@ "reactionAdd": "Добавить реакцию", "delete": "Удалить сообщение", "edit": "Редактировать сообщение", - "edited": "(отредактировано)" + "edited": "(отредактировано)", + "deleted": "Удалённое сообщение" }, "instanceStats": { "name": "Статистика инстанции: $1", @@ -366,6 +367,7 @@ "blocked": "Заблокированные", "blockedusers": "Заблокированные пользователи:", "addfriend": "Добавить в друзья", + "removeFriend": "Удалить из друзей", "addfriendpromt": "Добавить друзей по имени пользователя:", "notfound": "Пользователь не найден", "discnotfound": "Дискриминатор не найден:", From f74a1cf8c5bec69c1fbbea2f4fea03ffd57ae629 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 10:15:07 -0600 Subject: [PATCH 0026/1178] package.json fixes --- package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 1b889083..8d03653a 100644 --- a/package.json +++ b/package.json @@ -14,34 +14,34 @@ "dependencies": { "compression": "^1.7.4", "express": "^4.19.2", - "gulp-sourcemaps": "^3.0.0", + "gulp-sourcemaps": "^2.6.5", "gulp-swc": "^2.2.0", "rimraf": "^6.0.1" }, "devDependencies": { + "@eslint/js": "^9.10.0", + "@html-eslint/eslint-plugin": "^0.25.0", "@html-eslint/parser": "^0.27.0", - "eslint-plugin-html": "^8.1.1", - "@stylistic/eslint-plugin-js": "^2.8.0", - "@typescript-eslint/eslint-plugin": "^8.14.0", - "@typescript-eslint/parser": "^8.14.0", "@rsbuild/core": "^1.1.4", "@rsbuild/plugin-node-polyfill": "^1.2.0", - "@swc/core": "^1.7.26", - "swc": "^1.0.11", - "@eslint/js": "^9.10.0", - "@html-eslint/eslint-plugin": "^0.25.0", "@stylistic/eslint-plugin": "^2.3.0", + "@stylistic/eslint-plugin-js": "^2.8.0", + "@swc/core": "^1.7.26", "@types/compression": "^1.7.5", "@types/eslint__js": "^8.42.3", "@types/express": "^4.17.21", "@types/node-fetch": "^2.6.11", + "@typescript-eslint/eslint-plugin": "^8.14.0", + "@typescript-eslint/parser": "^8.14.0", "eslint": "^8.57.1", + "eslint-plugin-html": "^8.1.1", "eslint-plugin-sonarjs": "^1.0.4", "eslint-plugin-unicorn": "^55.0.0", "gulp": "^5.0.0", "gulp-copy": "^5.0.0", "gulp-plumber": "^1.2.1", "gulp-typescript": "^6.0.0-alpha.1", + "swc": "^1.0.11", "typescript": "^5.6.2", "typescript-eslint": "^8.14.0" } From e776d5032fc77f084f38aef5e9c57302b4b30ac2 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 11:46:00 -0600 Subject: [PATCH 0027/1178] fix issues --- .gitignore | 3 + package-lock.json | 5377 --------------------------------------------- 2 files changed, 3 insertions(+), 5377 deletions(-) delete mode 100644 package-lock.json diff --git a/.gitignore b/.gitignore index 84887f9a..b4b07622 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,6 @@ uptime.json .dist/ bun.lockb src/webpage/translations/langs.js + +package-lock.json +pnpm-lock.yaml diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 025864cd..00000000 --- a/package-lock.json +++ /dev/null @@ -1,5377 +0,0 @@ -{ - "name": "jankclient", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "jankclient", - "version": "0.1.0", - "license": "GPL-3.0", - "dependencies": { - "@html-eslint/parser": "^0.27.0", - "compression": "^1.7.4", - "express": "^4.19.2", - "node-fetch": "^3.3.2", - "ts-to-jsdoc": "^2.2.0" - }, - "devDependencies": { - "@eslint/js": "^9.10.0", - "@html-eslint/eslint-plugin": "^0.25.0", - "@types/compression": "^1.7.5", - "@types/eslint__js": "^8.42.3", - "@types/express": "^4.17.21", - "@types/node-fetch": "^2.6.11", - "eslint": "^8.57.1", - "gulp": "^5.0.0", - "gulp-copy": "^5.0.0", - "gulp-typescript": "^6.0.0-alpha.1", - "typescript": "^5.6.2", - "typescript-eslint": "^7.18.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", - "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@gulpjs/messages": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", - "integrity": "sha512-Ys9sazDatyTgZVb4xPlDufLweJ/Os2uHWOv+Caxvy2O85JcnT4M3vc73bi8pdLWlv3fdWQz3pdI9tVwo8rQQSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@gulpjs/to-absolute-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz", - "integrity": "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@html-eslint/eslint-plugin": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@html-eslint/eslint-plugin/-/eslint-plugin-0.25.0.tgz", - "integrity": "sha512-5DlvqO8bbe90cKSfFDuEblyrEnhAdgNTjWxXeUxt/XXC2OuMC8CsxzLZjtK3+0X6yM8m4xcE3fymCPwg7zdcXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@html-eslint/parser": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@html-eslint/parser/-/parser-0.27.0.tgz", - "integrity": "sha512-F/A1M0jnDAYoRvJiiSC7pIBD9DAsf4EhbndbvEi81aozD/wI8WWXON50xZPUaGHCI1C+2syTVifxDz8MvDKaQA==", - "license": "MIT", - "dependencies": { - "es-html-parser": "^0.0.9" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@ts-morph/common": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.22.0.tgz", - "integrity": "sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw==", - "license": "MIT", - "dependencies": { - "fast-glob": "^3.3.2", - "minimatch": "^9.0.3", - "mkdirp": "^3.0.1", - "path-browserify": "^1.0.1" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.56.11", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.11.tgz", - "integrity": "sha512-sVBpJMf7UPo/wGecYOpk2aQya2VUGeHhe38WG7/mN5FufNSubf5VT9Uh9Uyp8/eLJpu1/tuhJ/qTo4mhSB4V4Q==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint__js": { - "version": "8.42.3", - "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", - "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.14.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz", - "integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "node_modules/@types/qs": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", - "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/async-done": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-2.0.0.tgz", - "integrity": "sha512-j0s3bzYq9yKIVLKGE/tWlCpa3PfFLcrDZLTSVdnnCTGagXuXBJO4SsY9Xdk/fQBirCkH4evW5xOeJXqlAQFdsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.4.4", - "once": "^1.4.0", - "stream-exhaust": "^1.0.2" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/async-settle": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-2.0.0.tgz", - "integrity": "sha512-Obu/KE8FurfQRN6ODdHN9LuXqwC+JFIM9NRyZqJJ4ZfLJmIYN9Rg0/kb+wF70VV5+fJusTMQlJ1t5rF7J/ETdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-done": "^2.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/bach": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bach/-/bach-2.0.1.tgz", - "integrity": "sha512-A7bvGMGiTOxGMpNupYl9HQTf0FFDNF4VCmks4PJpFyN1AX2pdKuxuwdvUz2Hu388wcgp+OvGFNsumBfFNkR7eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-done": "^2.0.0", - "async-settle": "^2.0.0", - "now-and-later": "^3.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-block-writer": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz", - "integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==", - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "license": "MIT", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/copy-props": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-4.0.0.tgz", - "integrity": "sha512-bVWtw1wQLzzKiYROtvNlbJgxgBYt2bMJpkCbKmXM3xyijvcjjWXEk5nyrrT3bgJ7ODb19ZohE2T0Y3FgNPyoTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "each-props": "^3.0.0", - "is-plain-object": "^5.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/each-props": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-3.0.0.tgz", - "integrity": "sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^5.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-html-parser": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/es-html-parser/-/es-html-parser-0.0.9.tgz", - "integrity": "sha512-oniQMi+466VFsDzcdron9Ry/sqUJpDJg1bbDn0jFJKDdxXhwIOYDr4DgBnO5/yPLGj2xv+n5yy4L1Q0vAC5TYQ==" - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/findup-sync": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", - "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.3", - "micromatch": "^4.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/fined": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-2.0.0.tgz", - "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^5.0.0", - "object.defaults": "^1.1.0", - "object.pick": "^1.3.0", - "parse-filepath": "^1.0.2" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/flagged-respawn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-2.0.0.tgz", - "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", - "dev": true, - "license": "MIT", - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-mkdirp-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", - "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.8", - "streamx": "^2.12.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-stream": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-8.0.2.tgz", - "integrity": "sha512-R8z6eTB55t3QeZMmU1C+Gv+t5UnNRkA55c5yo67fAVfxODxieTwsjNG7utxS/73NdP1NbDgCrhVEg2h00y4fFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@gulpjs/to-absolute-glob": "^4.0.0", - "anymatch": "^3.1.3", - "fastq": "^1.13.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "is-negated-glob": "^1.0.0", - "normalize-path": "^3.0.0", - "streamx": "^2.12.5" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-watcher": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-6.0.0.tgz", - "integrity": "sha512-wGM28Ehmcnk2NqRORXFOTOR064L4imSw3EeOqU5bIwUf62eXGwg89WivH6VMahL8zlQHeodzvHpXplrqzrz3Nw==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-done": "^2.0.0", - "chokidar": "^3.5.3" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glogg": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-2.2.0.tgz", - "integrity": "sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A==", - "dev": true, - "license": "MIT", - "dependencies": { - "sparkles": "^2.1.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/gulp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-5.0.0.tgz", - "integrity": "sha512-S8Z8066SSileaYw1S2N1I64IUc/myI2bqe2ihOBzO6+nKpvNSg7ZcWJt/AwF8LC/NVN+/QZ560Cb/5OPsyhkhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-watcher": "^6.0.0", - "gulp-cli": "^3.0.0", - "undertaker": "^2.0.0", - "vinyl-fs": "^4.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/gulp-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-3.0.0.tgz", - "integrity": "sha512-RtMIitkT8DEMZZygHK2vEuLPqLPAFB4sntSxg4NoDta7ciwGZ18l7JuhCTiS5deOJi2IoK0btE+hs6R4sfj7AA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@gulpjs/messages": "^1.1.0", - "chalk": "^4.1.2", - "copy-props": "^4.0.0", - "gulplog": "^2.2.0", - "interpret": "^3.1.1", - "liftoff": "^5.0.0", - "mute-stdout": "^2.0.0", - "replace-homedir": "^2.0.0", - "semver-greatest-satisfied-range": "^2.0.0", - "string-width": "^4.2.3", - "v8flags": "^4.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/gulp-copy": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gulp-copy/-/gulp-copy-5.0.0.tgz", - "integrity": "sha512-XgTPwevIxr5bPITtrq24euacqASBMOy2R30IEUXX1mLsbd/GoOo0AM3T9qjF9L2Yp+muRr/spdRskVUjUCDqkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "plugin-error": "^2.0.1", - "through2": "^2.0.3" - }, - "peerDependencies": { - "gulp": "^4.0.1 || ^5.0.0" - } - }, - "node_modules/gulp-typescript": { - "version": "6.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz", - "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "plugin-error": "^1.0.1", - "source-map": "^0.7.3", - "through2": "^3.0.1", - "vinyl": "^2.2.0", - "vinyl-fs": "^3.0.3" - }, - "engines": { - "node": ">= 8" - }, - "peerDependencies": { - "typescript": "~2.7.1 || >=2.8.0-dev || >=2.9.0-dev || ~3.0.0 || >=3.0.0-dev || >=3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev " - } - }, - "node_modules/gulp-typescript/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/gulp-typescript/node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/fs-mkdirp-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulp-typescript/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/gulp-typescript/node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-typescript/node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", - "dev": true, - "license": "MIT", - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-typescript/node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/plugin-error/node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-typescript/node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/gulp-typescript/node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/to-through/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulp-typescript/node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "license": "MIT", - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-typescript/node_modules/vinyl-fs/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulp-typescript/node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulplog": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", - "integrity": "sha512-V2FaKiOhpR3DRXZuYdRLn/qiY0yI5XmqbTKrYbdemJ+xOh2d2MOweI/XFgMzd/9+1twdvMwllnZbWZNJ+BOm4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "glogg": "^2.2.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/last-run": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz", - "integrity": "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lead": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz", - "integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.0.tgz", - "integrity": "sha512-a5BQjbCHnB+cy+gsro8lXJ4kZluzOijzJ1UVVfyJYZC+IP2pLv1h4+aysQeKuTmyO8NAqfyQAk4HWaP/HjcKTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "extend": "^3.0.2", - "findup-sync": "^5.0.0", - "fined": "^2.0.0", - "flagged-respawn": "^2.0.0", - "is-plain-object": "^5.0.0", - "rechoir": "^0.8.0", - "resolve": "^1.20.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mute-stdout": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz", - "integrity": "sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", - "integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "license": "MIT" - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/plugin-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-2.0.1.tgz", - "integrity": "sha512-zMakqvIDyY40xHOvzXka0kUvf40nYIuwRE8dWhti2WtjQZ31xAgBZBhxsK7vK3QbRXS1Xms/LO7B5cuAsfB2Gg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^1.0.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/plugin-error/node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true, - "license": "MIT" - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true, - "license": "ISC" - }, - "node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/replace-homedir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", - "integrity": "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-options": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz", - "integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "value-or-function": "^4.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-2.0.0.tgz", - "integrity": "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "sver": "^1.8.3" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, - "node_modules/sparkles": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", - "integrity": "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stream-composer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", - "integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "streamx": "^2.13.2" - } - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true, - "license": "MIT" - }, - "node_modules/stream-shift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/streamx": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", - "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.3.2", - "queue-tick": "^1.0.1", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sver": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/sver/-/sver-1.8.4.tgz", - "integrity": "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "semver": "^6.3.0" - } - }, - "node_modules/sver/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/teex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", - "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "streamx": "^2.12.5" - } - }, - "node_modules/text-decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", - "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/to-through": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz", - "integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "streamx": "^2.12.5" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-morph": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-21.0.1.tgz", - "integrity": "sha512-dbDtVdEAncKctzrVZ+Nr7kHpHkv+0JDJb2MjjpBaj8bFeCkePU9rHfMklmhuLFnpeq/EJZk2IhStY6NzqgjOkg==", - "license": "MIT", - "dependencies": { - "@ts-morph/common": "~0.22.0", - "code-block-writer": "^12.0.0" - } - }, - "node_modules/ts-to-jsdoc": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-to-jsdoc/-/ts-to-jsdoc-2.2.0.tgz", - "integrity": "sha512-5miE85Iy8Hwo3KU4QpoXxSYbTyA7cUitgUAMZF6cQgvOzRmonNFWbxiYE5JcREqV5uvb0DGT/2BTwemlgyV3UQ==", - "license": "MIT", - "dependencies": { - "arg": "^5.0.1", - "ts-morph": "^21.0.1" - }, - "bin": { - "ts-to-jsdoc": "bin/ts-to-jsdoc" - } - }, - "node_modules/ts-to-jsdoc/node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "license": "MIT" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.18.0.tgz", - "integrity": "sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "7.18.0", - "@typescript-eslint/parser": "7.18.0", - "@typescript-eslint/utils": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/undertaker": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-2.0.0.tgz", - "integrity": "sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bach": "^2.0.1", - "fast-levenshtein": "^3.0.0", - "last-run": "^2.0.0", - "undertaker-registry": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/undertaker-registry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-2.0.0.tgz", - "integrity": "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/undertaker/node_modules/fast-levenshtein": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", - "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fastest-levenshtein": "^1.0.7" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, - "license": "MIT" - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/v8flags": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", - "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/value-or-function": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", - "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-contents": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", - "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^5.0.0", - "vinyl": "^3.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-contents/node_modules/replace-ext": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", - "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/vinyl-contents/node_modules/vinyl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", - "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^2.1.2", - "clone-stats": "^1.0.0", - "remove-trailing-separator": "^1.1.0", - "replace-ext": "^2.0.0", - "teex": "^1.0.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-fs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.0.tgz", - "integrity": "sha512-7GbgBnYfaquMk3Qu9g22x000vbYkOex32930rBnc3qByw6HfMEAoELjCjoJv4HuEQxHAurT+nvMHm6MnJllFLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fs-mkdirp-stream": "^2.0.1", - "glob-stream": "^8.0.0", - "graceful-fs": "^4.2.11", - "iconv-lite": "^0.6.3", - "is-valid-glob": "^1.0.0", - "lead": "^4.0.0", - "normalize-path": "3.0.0", - "resolve-options": "^2.0.0", - "stream-composer": "^1.0.2", - "streamx": "^2.14.0", - "to-through": "^3.0.0", - "value-or-function": "^4.0.0", - "vinyl": "^3.0.0", - "vinyl-sourcemap": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-fs/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vinyl-fs/node_modules/replace-ext": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", - "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/vinyl-fs/node_modules/vinyl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", - "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^2.1.2", - "clone-stats": "^1.0.0", - "remove-trailing-separator": "^1.1.0", - "replace-ext": "^2.0.0", - "teex": "^1.0.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", - "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "convert-source-map": "^2.0.0", - "graceful-fs": "^4.2.10", - "now-and-later": "^3.0.0", - "streamx": "^2.12.5", - "vinyl": "^3.0.0", - "vinyl-contents": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/vinyl-sourcemap/node_modules/replace-ext": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", - "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/vinyl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", - "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^2.1.2", - "clone-stats": "^1.0.0", - "remove-trailing-separator": "^1.1.0", - "replace-ext": "^2.0.0", - "teex": "^1.0.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} From 53f6807c8d7830a9c3c3be472e1dc913f558b8c9 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 14:31:13 -0600 Subject: [PATCH 0028/1178] fix dep issues --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 8d03653a..c6384660 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@rsbuild/plugin-node-polyfill": "^1.2.0", "@stylistic/eslint-plugin": "^2.3.0", "@stylistic/eslint-plugin-js": "^2.8.0", - "@swc/core": "^1.7.26", + "@swc/core": "^1.10.1", "@types/compression": "^1.7.5", "@types/eslint__js": "^8.42.3", "@types/express": "^4.17.21", @@ -41,7 +41,6 @@ "gulp-copy": "^5.0.0", "gulp-plumber": "^1.2.1", "gulp-typescript": "^6.0.0-alpha.1", - "swc": "^1.0.11", "typescript": "^5.6.2", "typescript-eslint": "^8.14.0" } From e3f9efdd4b1df0004f109c7a859dad3c87c0de21 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 14:36:35 -0600 Subject: [PATCH 0029/1178] dep fixes --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c6384660..cde064ec 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "devDependencies": { "@eslint/js": "^9.10.0", + "@swc/cli": "^0.5.2", "@html-eslint/eslint-plugin": "^0.25.0", "@html-eslint/parser": "^0.27.0", "@rsbuild/core": "^1.1.4", From 9862c2dd1a9a0a54af94228d810476de27ae7a22 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 15:06:25 -0600 Subject: [PATCH 0030/1178] fix dep issues again --- gulpfile.cjs | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gulpfile.cjs b/gulpfile.cjs index 681c6556..c1a43f4c 100644 --- a/gulpfile.cjs +++ b/gulpfile.cjs @@ -60,7 +60,7 @@ gulp.task("clean", (cb) => { .pipe(gulp.dest("dist")); } else if(argv.bunswc){ return await new Promise(ret=>{ - exec("bun swc ./src -s -d dist").on('exit', function (code) { + exec("bun swc --strip-leading-paths ./src -s -d ./dist/").on('exit', function (code) { ret(); }); }) diff --git a/package.json b/package.json index cde064ec..6456ecb9 100644 --- a/package.json +++ b/package.json @@ -20,13 +20,13 @@ }, "devDependencies": { "@eslint/js": "^9.10.0", - "@swc/cli": "^0.5.2", "@html-eslint/eslint-plugin": "^0.25.0", "@html-eslint/parser": "^0.27.0", "@rsbuild/core": "^1.1.4", "@rsbuild/plugin-node-polyfill": "^1.2.0", "@stylistic/eslint-plugin": "^2.3.0", "@stylistic/eslint-plugin-js": "^2.8.0", + "@swc/cli": "^0.5.2", "@swc/core": "^1.10.1", "@types/compression": "^1.7.5", "@types/eslint__js": "^8.42.3", From eddb92abe8a6fe2a7d4cd1ad820066a6d681ef4c Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 15:08:49 -0600 Subject: [PATCH 0031/1178] adding emoji support --- src/webpage/guild.ts | 75 ++++++++++++++++++++++++++++++++++++++-- src/webpage/jsontypes.ts | 25 ++++++++++++-- src/webpage/localuser.ts | 9 ++++- src/webpage/message.ts | 2 +- src/webpage/style.css | 26 ++++++++++++++ 5 files changed, 130 insertions(+), 7 deletions(-) diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index ae9f8618..c217cb7a 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -6,9 +6,10 @@ import{ Member }from"./member.js"; import{ Dialog, Options, Settings }from"./settings.js"; import{ Permissions }from"./permissions.js"; import{ SnowFlake }from"./snowflake.js"; -import{channeljson,guildjson,emojijson,memberjson,invitejson,rolesjson,}from"./jsontypes.js"; +import{channeljson,guildjson,emojijson,memberjson,invitejson,rolesjson, emojipjson,}from"./jsontypes.js"; import{ User }from"./user.js"; import { I18n } from "./i18n.js"; +import { Emoji } from "./emoji.js"; class Guild extends SnowFlake{ owner!: Localuser; @@ -26,7 +27,7 @@ class Guild extends SnowFlake{ parent_id!: string; member!: Member; html!: HTMLElement; - emojis!: emojijson[]; + emojis!: emojipjson[]; large!: boolean; members=new Set(); static contextmenu = new Contextmenu("guild menu"); @@ -178,6 +179,75 @@ class Guild extends SnowFlake{ s1.options.push( new RoleList(permlist, this, this.updateRolePermissions.bind(this),false) ); + { + const emoji=settings.addButton("Emojis"); + emoji.addButtonInput("","Upload Emoji",()=>{ + const popup=new Dialog("Upload emoji"); + const form=popup.options.addForm("",()=>{ + popup.hide(); + },{ + fetchURL:`${this.info.api}/guilds/${this.id}/emojis`, + method:"POST", + headers:this.headers + }); + form.addFileInput("Image:","image",{required:true}); + form.addTextInput("Name:","name",{required:true}); + popup.show(); + }); + const containdiv=document.createElement("div"); + const genDiv=()=>{ + containdiv.innerHTML=""; + for(const emoji of this.emojis){ + const div=document.createElement("div"); + div.classList.add("flexltr","emojiOption"); + const emojic=new Emoji(emoji,this); + + const text=document.createElement("input"); + text.type="text"; + text.value=emoji.name; + text.addEventListener("change",()=>{ + fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`,{ + method:"PATCH", + headers:this.headers, + body:JSON.stringify({name:text.value}) + }).then(e=>{if(!e.ok)text.value=emoji.name;})//if not ok, undo + }); + + const del=document.createElement("span"); + del.classList.add("svgicon", "svg-x","deleteEmoji"); + del.onclick=()=>{ + const diaolog=new Dialog(""); + diaolog.options.addTitle("Are you sure you want to delete this emoji?"); + const options=diaolog.options.addOptions("",{ltr:true}); + options.addButtonInput("",I18n.getTranslation("yes"),()=>{ + fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`,{ + method:"DELETE", + headers:this.headers + }) + diaolog.hide(); + }); + options.addButtonInput("",I18n.getTranslation("no"),()=>{ + diaolog.hide(); + }) + diaolog.show(); + } + + + div.append(emojic.getHTML(true),":",text,":",del); + + containdiv.append(div); + } + } + this.onEmojiUpdate=()=>{ + if(!document.body.contains(containdiv)){ + this.onEmojiUpdate=()=>{}; + return; + } + genDiv(); + } + genDiv(); + emoji.addHTMLArea(containdiv); + } settings.show(); } makeInviteMenu(options:Options,valid:void|(Channel[])){ @@ -303,6 +373,7 @@ class Guild extends SnowFlake{ this.roles.splice(this.roles.indexOf(role),1); this.roleUpdate(role,-1); } + onEmojiUpdate=(_:emojipjson[])=>{}; constructor( json: guildjson | -1, owner: Localuser, diff --git a/src/webpage/jsontypes.ts b/src/webpage/jsontypes.ts index 45e10d8f..57b39d36 100644 --- a/src/webpage/jsontypes.ts +++ b/src/webpage/jsontypes.ts @@ -168,14 +168,24 @@ type emojijson = { name: string; id?: string; animated?: boolean; - emoji?:string + emoji?:string; }; +type emojipjson=emojijson&{ + available: boolean, + guild_id:string, + user_id:string, + managed:boolean, + require_colons:boolean, + roles:string[], + groups:null//TODO figure out what this means lol +}; + type guildjson = { application_command_counts: { [key: string]: number }; channels: channeljson[]; data_mode: string; - emojis: emojijson[]; + emojis: emojipjson[]; guild_scheduled_events: []; id: string; large: boolean; @@ -543,6 +553,14 @@ roleCreate | { user:userjson }, s:number +}|{ + op: 0, + t: "GUILD_EMOJIS_UPDATE", + d: { + guild_id: string, + emojis: emojipjson[] + }, + s: number }; @@ -706,5 +724,6 @@ export{ voiceserverupdate, webRTCSocket, sdpback, - opRTC12 + opRTC12, + emojipjson }; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index a59fd068..43d5288d 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -5,7 +5,7 @@ import{ AVoice }from"./audio/voice.js"; import{ User }from"./user.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{channeljson,emojipjson,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"; import{ getTextNodeAtPosition, MarkDown }from"./markdown.js"; @@ -589,6 +589,13 @@ class Localuser{ member.remove(); break; } + case "GUILD_EMOJIS_UPDATE":{ + const guild=this.guildids.get(temp.d.guild_id); + if(!guild) break; + guild.emojis=temp.d.emojis; + guild.onEmojiUpdate(guild.emojis); + break; + } default :{ //@ts-ignore console.warn("Unhandled case "+temp.t,temp); diff --git a/src/webpage/message.ts b/src/webpage/message.ts index 540ef402..a65dd2d7 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -468,7 +468,7 @@ class Message extends SnowFlake{ div.appendChild(replyline); } div.appendChild(build); - const messageTypes=new Set([0,19]) + const messageTypes=new Set([0,19]); if(messageTypes.has(this.type) || this.attachments.length !== 0){ const pfpRow = document.createElement("div"); let pfpparent, current; diff --git a/src/webpage/style.css b/src/webpage/style.css index 96f3b0a0..3edfb675 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -2175,6 +2175,8 @@ fieldset input[type="radio"] { } .bigemoji{ width:.6in; + object-fit: contain; + height: .6in; } .friendlyButton{ padding: .07in; @@ -2189,3 +2191,27 @@ fieldset input[type="radio"] { .friendlyButton:hover{ background:black; } +.emojiOption{ + border: solid 1px var(--black); + display:flex; + align-items: center; + padding: .075in; + margin-bottom: .2in; + border-radius: .1in; + background: var(--primary-hover); + position: relative; + input{ + width:2in !important; + height:.3in; + } + .bigemoji{ + padding-right:.5in; + } +} +.deleteEmoji{ + width: .3in; + height: .3in; + position: absolute; + right: .2in; + cursor: pointer; +} From af7d331ac5f2d27a7c286c2251622679d66ffa49 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 22:42:42 -0600 Subject: [PATCH 0032/1178] fix condition --- src/webpage/user.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webpage/user.ts b/src/webpage/user.ts index 97733d8f..51756440 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -204,8 +204,8 @@ class User extends SnowFlake{ member.showEditProfile(); }, null, - member=>{ - return !!member; + function(member){ + return member?.id===this.localuser.user.id; } ); this.contextmenu.addbutton( From e06e6de08524f1ceff67d8e8098ed6abbb90f642 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 14 Dec 2024 19:38:23 -0600 Subject: [PATCH 0033/1178] nsfw channel updates --- src/webpage/channel.ts | 89 +++++++++++++++++++++++------- src/webpage/icons/announcensfw.svg | 1 + src/webpage/icons/channelnsfw.svg | 1 + src/webpage/icons/voicensfw.svg | 1 + src/webpage/style.css | 10 ++++ 5 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 src/webpage/icons/announcensfw.svg create mode 100644 src/webpage/icons/channelnsfw.svg create mode 100644 src/webpage/icons/voicensfw.svg diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index a9baa875..7238c8f2 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -5,7 +5,7 @@ import{ Contextmenu }from"./contextmenu.js"; import{ Guild }from"./guild.js"; import{ Localuser }from"./localuser.js"; import{ Permissions }from"./permissions.js"; -import{ Dialog, Settings }from"./settings.js"; +import{ Dialog, Float, Settings }from"./settings.js"; import{ Role, RoleList }from"./role.js"; import{ InfiniteScroller }from"./infiniteScroller.js"; import{ SnowFlake }from"./snowflake.js"; @@ -534,17 +534,17 @@ class Channel extends SnowFlake{ if(this.type === 0){ const decoration = document.createElement("span"); button.appendChild(decoration); - decoration.classList.add("space", "svgicon", "svg-channel"); + decoration.classList.add("space", "svgicon", this.nsfw?"svg-channelnsfw":"svg-channel"); }else if(this.type === 2){ // const decoration = document.createElement("span"); button.appendChild(decoration); - decoration.classList.add("space", "svgicon", "svg-voice"); + decoration.classList.add("space", "svgicon", this.nsfw?"svg-voicensfw":"svg-voice"); }else if(this.type === 5){ // const decoration = document.createElement("span"); button.appendChild(decoration); - decoration.classList.add("space", "svgicon", "svg-announce"); + decoration.classList.add("space", "svgicon", this.nsfw?"svg-announcensfw":"svg-announce"); }else{ console.log(this.type); } @@ -787,25 +787,50 @@ class Channel extends SnowFlake{ } } static genid: number = 0; - async getHTML(addstate=true){ - const id = ++Channel.genid; - if(this.localuser.channelfocus){ - this.localuser.channelfocus.infinite.delete(); - } - if(this.guild !== this.localuser.lookingguild){ - this.guild.loadGuild(); + nsfwPannel(){ + (document.getElementById("typebox") as HTMLDivElement).contentEditable =""+false; + (document.getElementById("upload") as HTMLElement).style.visibility="hidden"; + (document.getElementById("typediv") as HTMLElement).style.visibility="hidden"; + const messages = document.getElementById("channelw") as HTMLDivElement; + const messageContainers = Array.from( + messages.getElementsByClassName("messagecontainer") + ); + for(const thing of messageContainers){ + thing.remove(); } - if(this.localuser.channelfocus && this.localuser.channelfocus.myhtml){ - this.localuser.channelfocus.myhtml.classList.remove("viewChannel"); + const elements = Array.from(messages.getElementsByClassName("scroller")); + for(const elm of elements){ + elm.remove(); + console.warn("rouge element detected and removed"); } - if(this.myhtml){ - this.myhtml.classList.add("viewChannel"); + const div=document.getElementById("sideDiv") as HTMLDivElement; + div.innerHTML=""; + const float=new Float(""); + const options=float.options; + //@ts-ignore weird hack, ik, but the user here does have that information + //TODO make an extention of the user class with these aditional properties + //TODO make a popup for `nsfw_allowed==null` to input age + if(this.localuser.user.nsfw_allowed){ + options.addTitle("This is a NSFW channel, do you wish to proceed?"); + const buttons=options.addOptions("",{ltr:true}); + buttons.addButtonInput("","Yes",()=>{ + this.perminfo.nsfwOk=true; + this.localuser.userinfo.updateLocal(); + this.getHTML(); + }); + buttons.addButtonInput("","No",()=>{ + window.history.back(); + }) + }else{ + options.addTitle("You are not allowed in this channel."); } - this.guild.prevchannel = this; - this.guild.perminfo.prevchannel = this.id; - this.localuser.userinfo.updateLocal(); - this.localuser.channelfocus = this; - const prom = this.infinite.delete(); + const html=float.generateHTML(); + html.classList.add("messagecontainer") + messages.append(html); + + } + async getHTML(addstate=true){ + if(addstate){ history.pushState([this.guild_id,this.id], "", "/channels/" + this.guild_id + "/" + this.id); } @@ -819,6 +844,30 @@ class Channel extends SnowFlake{ ).makeHTML()); channelTopic.removeAttribute("hidden"); }else channelTopic.setAttribute("hidden", ""); + if(this.guild !== this.localuser.lookingguild){ + this.guild.loadGuild(); + } + if(this.localuser.channelfocus && this.localuser.channelfocus.myhtml){ + this.localuser.channelfocus.myhtml.classList.remove("viewChannel"); + } + if(this.myhtml){ + this.myhtml.classList.add("viewChannel"); + } + const id = ++Channel.genid; + if(this.localuser.channelfocus){ + this.localuser.channelfocus.infinite.delete(); + } + this.guild.prevchannel = this; + this.guild.perminfo.prevchannel = this.id; + this.localuser.userinfo.updateLocal(); + this.localuser.channelfocus = this; + //@ts-ignore another hack + if(this.nsfw&&(!this.perminfo.nsfwOk||!this.localuser.user.nsfw_allowed)){ + this.nsfwPannel(); + return; + } + + const prom = this.infinite.delete(); const loading = document.getElementById("loadingdiv") as HTMLDivElement; Channel.regenLoadingMessages(); diff --git a/src/webpage/icons/announcensfw.svg b/src/webpage/icons/announcensfw.svg new file mode 100644 index 00000000..2e3864b0 --- /dev/null +++ b/src/webpage/icons/announcensfw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/webpage/icons/channelnsfw.svg b/src/webpage/icons/channelnsfw.svg new file mode 100644 index 00000000..55258d15 --- /dev/null +++ b/src/webpage/icons/channelnsfw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/webpage/icons/voicensfw.svg b/src/webpage/icons/voicensfw.svg new file mode 100644 index 00000000..9ba44ba3 --- /dev/null +++ b/src/webpage/icons/voicensfw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/webpage/style.css b/src/webpage/style.css index 3edfb675..ffeaef83 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -269,6 +269,16 @@ textarea { .svg-addfriend{ mask: url(/icons/addfriend.svg); } + +.svg-channelnsfw { + mask: url(/icons/channelnsfw.svg); +} +.svg-announcensfw { + mask: url(/icons/announcensfw.svg); +} +.svg-voicensfw{ + mask: url(/icons/voicensfw.svg); +} .svgicon { display: block; height: 100%; From 30ee3aad6a2a27a45d70f2e3d2864d6b66a72ae8 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sun, 15 Dec 2024 21:26:03 -0600 Subject: [PATCH 0034/1178] target more recent TS --- gulpfile.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.cjs b/gulpfile.cjs index c1a43f4c..7b052331 100644 --- a/gulpfile.cjs +++ b/gulpfile.cjs @@ -60,7 +60,7 @@ gulp.task("clean", (cb) => { .pipe(gulp.dest("dist")); } else if(argv.bunswc){ return await new Promise(ret=>{ - exec("bun swc --strip-leading-paths ./src -s -d ./dist/").on('exit', function (code) { + exec("bun swc --strip-leading-paths ./src -s -d ./dist/ -C jsc.target=es2022").on('exit', function (code) { ret(); }); }) From d32a8ab02bdb0aafa7326c573f7e5d993f304f80 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sun, 15 Dec 2024 22:08:07 -0600 Subject: [PATCH 0035/1178] reaction hover events --- src/webpage/hover.ts | 30 ++++++++++++++++++++++-------- src/webpage/localuser.ts | 19 ++++++++++++++++++- src/webpage/member.ts | 3 +++ src/webpage/message.ts | 37 +++++++++++++++++++++++++++++++------ src/webpage/user.ts | 20 +++++++++++++++++++- 5 files changed, 93 insertions(+), 16 deletions(-) diff --git a/src/webpage/hover.ts b/src/webpage/hover.ts index fcd5982a..aa02bbd1 100644 --- a/src/webpage/hover.ts +++ b/src/webpage/hover.ts @@ -2,29 +2,43 @@ import { Contextmenu } from "./contextmenu.js"; import { MarkDown } from "./markdown.js"; class Hover{ - str:string|MarkDown - constructor(txt:string|MarkDown){ + str:string|MarkDown|(()=>Promise|MarkDown|string); + constructor(txt:string|MarkDown|(()=>Promise|MarkDown|string)){ this.str=txt; } addEvent(elm:HTMLElement){ let timeOut=setTimeout(()=>{},0); let elm2=document.createElement("div"); elm.addEventListener("mouseover",()=>{ - timeOut=setTimeout(()=>{ - elm2=this.makeHover(elm); + timeOut=setTimeout(async ()=>{ + elm2=await this.makeHover(elm); },750) }); elm.addEventListener("mouseout",()=>{ clearTimeout(timeOut); elm2.remove(); - }) + }); + new MutationObserver(function (e) { + if (e[0].removedNodes) { + clearTimeout(timeOut); + elm2.remove(); + }; + }).observe(elm,{ childList: true }); } - makeHover(elm:HTMLElement){ + async makeHover(elm:HTMLElement){ + if(!document.contains(elm)) return document.createDocumentFragment() as unknown as HTMLDivElement; const div=document.createElement("div"); if(this.str instanceof MarkDown){ - div.append(this.str.makeHTML({stdsize:true})) + div.append(this.str.makeHTML()) + }else if(this.str instanceof Function){ + const hover=await this.str(); + if(hover instanceof MarkDown){ + div.append(hover.makeHTML()); + }else{ + div.innerText=hover; + } }else{ - div.append(this.str); + div.innerText=this.str; } const box=elm.getBoundingClientRect(); div.style.top=(box.bottom+4)+"px"; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 43d5288d..5e953e3b 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -1473,7 +1473,7 @@ class Localuser{ localStorage.setItem("Voice enabled","true") }else{ - box.value=true; + box.value=false; const checkbox=box.input.deref(); if(checkbox){ checkbox.checked=false; @@ -1483,6 +1483,23 @@ class Localuser{ localStorage.removeItem("Voice enabled"); } } + const box2=security.addCheckboxInput("Enable logging of bad stuff",()=>{},{initState:Boolean(localStorage.getItem("logbad"))}); + box2.onchange=(e)=>{ + if(e){ + if(confirm("this is meant for spacebar devs")){ + localStorage.setItem("logbad","true") + + }else{ + box2.value=false; + const checkbox=box2.input.deref(); + if(checkbox){ + checkbox.checked=false; + } + } + }else{ + localStorage.removeItem("logbad"); + } + } } }; genSecurity(); diff --git a/src/webpage/member.ts b/src/webpage/member.ts index 6104e3e5..d08be76c 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -359,6 +359,9 @@ class Member extends SnowFlake{ ): Promise{ let user: User; if(owner.localuser.userMap.has(memberjson.id)){ + if(memberjson.user){ + new User(memberjson.user, owner.localuser); + } user = owner.localuser.userMap.get(memberjson.id) as User; }else if(memberjson.user){ user = new User(memberjson.user, owner.localuser); diff --git a/src/webpage/message.ts b/src/webpage/message.ts index a65dd2d7..27d632bd 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -8,7 +8,7 @@ import{ Localuser }from"./localuser.js"; import{ Role }from"./role.js"; import{ File }from"./file.js"; import{ SnowFlake }from"./snowflake.js"; -import{ memberjson, messagejson }from"./jsontypes.js"; +import{ memberjson, messagejson, userjson }from"./jsontypes.js"; import{ Emoji }from"./emoji.js"; import{ mobile }from"./utils/utils.js"; import { I18n } from "./i18n.js"; @@ -725,17 +725,42 @@ class Message extends SnowFlake{ } let emoji: HTMLElement; if(thing.emoji.id || /\d{17,21}/.test(thing.emoji.name)){ - if(/\d{17,21}/.test(thing.emoji.name)) + if(/\d{17,21}/.test(thing.emoji.name)){ thing.emoji.id = thing.emoji.name; //Should stop being a thing once the server fixes this bug - const emo = new Emoji( - thing.emoji as { name: string; id: string; animated: boolean }, - this.guild - ); + } + const emo = new Emoji(thing.emoji as { name: string; id: string; animated: boolean },this.guild); emoji = emo.getHTML(false); }else{ emoji = document.createElement("p"); emoji.textContent = thing.emoji.name; } + const h=new Hover(async ()=>{ + //TODO this can't be real, name conflicts must happen, but for now it's fine + const f=await fetch(`${this.info.api}/channels/${this.channel.id}/messages/${this.id}/reactions/${thing.emoji.name}?limit=3&type=0`,{headers:this.headers}); + const json=await f.json() as userjson[]; + let build=""; + let users=json.map(_=>new User(_,this.localuser)); + //FIXME this is a spacebar bug, I can't fix this the api ignores limit and just sends everything. + users=users.splice(0,3); + let first=true; + for(const user of users){ + if(!first){ + build+=", "; + } + build+=user.name; + first=false; + } + if(thing.count>3){ + build+=", and more!" + }else{ + + } + build+="\nReacted with "+thing.emoji.name; + console.log(build); + return build; + + }); + h.addEvent(reaction); const count = document.createElement("p"); count.textContent = "" + thing.count; count.classList.add("reactionCount"); diff --git a/src/webpage/user.ts b/src/webpage/user.ts index 51756440..6401446d 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -38,6 +38,9 @@ class User extends SnowFlake{ constructor(userjson: userjson, owner: Localuser, dontclone = false){ super(userjson.id); this.owner = owner; + if(localStorage.getItem("logbad")&&owner.user&&owner.user.id!==userjson.id){ + this.checkfortmi(userjson) + } if(!owner){ console.error("missing localuser"); } @@ -57,7 +60,22 @@ class User extends SnowFlake{ return User.checkuser(userjson, owner); } } - + /** + * function is meant to check if userjson contains too much information IE non-public stuff + * + * + */ + checkfortmi(json:any){ + if(json.data){ + console.error("Server sent *way* too much info, this is really bad, it sent data") + } + const bad=new Set(["fingerprints", "extended_settings", "mfa_enabled", "nsfw_allowed", "premium_usage_flags", "totp_last_ticket", "totp_secret", "webauthn_enabled"]); + for(const thing of bad){ + if(json.hasOwnProperty(thing)){ + console.error(thing+" should not be exposed to the client"); + } + } + } tojson():userjson{ return { username: this.username, From 161181f8de5e6d3ff6e373d515f683a28ad2db74 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 16 Dec 2024 13:21:09 +0100 Subject: [PATCH 0036/1178] Localisation updates from https://translatewiki.net. --- translations/ko.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/translations/ko.json b/translations/ko.json index c01599ef..fc65a243 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -187,7 +187,8 @@ "reactionAdd": "반응 추가", "delete": "메시지 삭제", "edit": "메시지 편집", - "edited": "(편집됨)" + "edited": "(편집됨)", + "deleted": "삭제된 메시지" }, "instanceStats": { "name": "인스턴스 통계: $1", @@ -221,6 +222,7 @@ "blocked": "차단됨", "blockedusers": "차단된 사용자:", "addfriend": "친구 추가", + "removeFriend": "친구 제거", "addfriendpromt": "사용자 이름으로 친구 추가:", "notfound": "사용자를 찾을 수 없습니다", "pending": "보류 중", @@ -247,14 +249,16 @@ "unblock": "사용자 차단 해제", "friendReq": "친구 요청", "addRole": "역할 추가", - "removeRole": "역할 제거" + "removeRole": "역할 제거", + "editServerProfile": "서버 프로필 편집" }, "login": { "checking": "인스턴스 확인 중", "invalid": "유효하지 않은 인스턴스입니다. 다시 시도하세요" }, "member": { - "reason:": "이유:" + "reason:": "이유:", + "nick:": "별명:" }, "uploadFilesText": "여기에 파일을 올리세요!", "retrying": "다시 시도하는 중..." From 4458308d98da69b4d8d5fe7c5f3009d73b443b0b Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 19 Dec 2024 13:22:04 +0100 Subject: [PATCH 0037/1178] Localisation updates from https://translatewiki.net. --- translations/ru.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/translations/ru.json b/translations/ru.json index c58f75ab..96dd8af3 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -398,7 +398,8 @@ "kick": "Выгнать участника", "ban": "Забанить участника", "addRole": "Добавить роли", - "removeRole": "Убрать роли" + "removeRole": "Убрать роли", + "editServerProfile": "Редактировать профиль сервера" }, "login": { "checking": "Проверка инстанции", From ffe21e6d6c5771a781c35340c475ba2a0b4b37a3 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 20 Dec 2024 18:59:40 -0600 Subject: [PATCH 0038/1178] search updates --- package.json | 1 + src/webpage/channel.ts | 12 +++++++- src/webpage/index.html | 1 + src/webpage/index.ts | 21 ++++++++++++++ src/webpage/infiniteScroller.ts | 1 - src/webpage/localuser.ts | 49 ++++++++++++++++++++++++++++++- src/webpage/markdown.ts | 51 ++++++++++++++++++++++----------- src/webpage/message.ts | 47 +++++++++++++++++------------- src/webpage/style.css | 44 ++++++++++++++++++++++++++-- src/webpage/user.ts | 1 - 10 files changed, 185 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 6456ecb9..bf586bab 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "express": "^4.19.2", "gulp-sourcemaps": "^2.6.5", "gulp-swc": "^2.2.0", + "prettier": "^3.4.2", "rimraf": "^6.0.1" }, "devDependencies": { diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 7238c8f2..9b0d4295 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -777,6 +777,14 @@ class Channel extends SnowFlake{ return new Message(json[0], this); } } + async focus(id:string){ + console.time() + console.log(await this.getmessage(id)); + await this.getHTML(); + console.timeEnd() + console.warn(id); + this.infinite.focus(id); + } editLast(){ let message:Message|undefined=this.lastmessage; while(message&&message.author!==this.localuser.user){ @@ -1180,7 +1188,7 @@ class Channel extends SnowFlake{ } async buildmessages(){ this.infinitefocus = false; - this.tryfocusinfinate(); + await this.tryfocusinfinate(); } infinitefocus = false; async tryfocusinfinate(){ @@ -1548,3 +1556,5 @@ class Channel extends SnowFlake{ } Channel.setupcontextmenu(); export{ Channel }; + + diff --git a/src/webpage/index.html b/src/webpage/index.html index 1cf492ec..114e9177 100644 --- a/src/webpage/index.html +++ b/src/webpage/index.html @@ -60,6 +60,7 @@

Server Name

Channel name + diff --git a/src/webpage/index.ts b/src/webpage/index.ts index b7fa3bb1..0a8abed6 100644 --- a/src/webpage/index.ts +++ b/src/webpage/index.ts @@ -204,7 +204,28 @@ import { I18n } from "./i18n.js"; if(event.key === "Enter" && !event.shiftKey) event.preventDefault(); }); markdown.giveBox(typebox); + { + const searchBox = document.getElementById("searchBox") as CustomHTMLDivElement; + const markdown = new MarkDown("", thisUser); + searchBox.markdown = markdown; + + searchBox.addEventListener("keydown", event=>{ + + if(event.key === "Enter") { + event.preventDefault(); + thisUser.mSearch(markdown.rawString) + }; + }); + markdown.giveBox(searchBox); + markdown.setCustomBox((e)=>{ + const span=document.createElement("span"); + span.textContent=e.replace("\n",""); + return span; + }); + + + } const images: Blob[] = []; const imagesHtml: HTMLElement[] = []; diff --git a/src/webpage/infiniteScroller.ts b/src/webpage/infiniteScroller.ts index 5332bb42..ac657243 100644 --- a/src/webpage/infiniteScroller.ts +++ b/src/webpage/infiniteScroller.ts @@ -37,7 +37,6 @@ offset: number this.destroyFromID(thing[1]); } this.HTMLElements=[]; - this.div=null; } constructor( getIDFromOffset: InfiniteScroller["getIDFromOffset"], diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 5e953e3b..7282aa66 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -5,7 +5,7 @@ import{ AVoice }from"./audio/voice.js"; import{ User }from"./user.js"; import{ getapiurls, SW }from"./utils/utils.js"; import { getBulkInfo, setTheme, Specialuser } from "./utils/utils.js"; -import{channeljson,emojipjson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js"; +import{channeljson,emojipjson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,messagejson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js"; import{ Member }from"./member.js"; import{ Dialog, Form, FormError, Options, Settings }from"./settings.js"; import{ getTextNodeAtPosition, MarkDown }from"./markdown.js"; @@ -15,6 +15,7 @@ import { VoiceFactory } from "./voice.js"; import { I18n, langmap } from "./i18n.js"; import { Emoji } from "./emoji.js"; import { Play } from "./audio/play.js"; +import { Message } from "./message.js"; const wsCodesRetry = new Set([4000,4001,4002, 4003, 4005, 4007, 4008, 4009]); @@ -669,8 +670,10 @@ class Localuser{ return channel; // Add this line to return the 'channel' variable } async memberListUpdate(list:memberlistupdatejson|void){ + if(this.searching)return; const div=document.getElementById("sideDiv") as HTMLDivElement; div.innerHTML=""; + div.classList.remove("searchDiv"); const guild=this.lookingguild; if(!guild) return; const channel=this.channelfocus; @@ -832,6 +835,7 @@ class Localuser{ } } loadGuild(id: string,forceReload=false): Guild | undefined{ + this.searching=false; let guild = this.guildids.get(id); if(!guild){ guild = this.guildids.get("@me"); @@ -1968,6 +1972,49 @@ class Localuser{ } box.innerHTML=""; } + searching=false; + mSearch(query:string){ + const p=new URLSearchParams("?"); + this.searching=true; + p.set("content",query.trim()); + fetch(this.info.api+`/guilds/${this.lookingguild?.id}/messages/search/?`+p.toString(),{ + headers:this.headers + }).then(_=>_.json()).then((json:{messages:[messagejson][],total_results:number})=>{ + //FIXME total_results shall be ignored as it's known to be bad, spacebar bug. + const messages=json.messages.map(([m])=>{ + const c=this.channelids.get(m.channel_id); + if(!c) return; + if(c.messages.get(m.id)){ + return c.messages.get(m.id); + } + return new Message(m,c,true); + }).filter(_=>_!==undefined); + const sideDiv= document.getElementById("sideDiv"); + if(!sideDiv)return; + sideDiv.innerHTML=""; + sideDiv.classList.add("searchDiv"); + let channel:Channel|undefined=undefined; + for(const message of messages){ + if(channel!==message.channel){ + channel=message.channel; + const h3=document.createElement("h3"); + h3.textContent=channel.name; + h3.classList.add("channelSTitle") + sideDiv.append(h3); + } + const html=message.buildhtml(undefined,true); + html.addEventListener("click",async ()=>{ + try{ + await message.channel.focus(message.id); + }catch(e){ + console.error(e); + } + }) + sideDiv.append(html) + } + }); + } + keydown:(event:KeyboardEvent)=>unknown=()=>{}; keyup:(event:KeyboardEvent)=>boolean=()=>false; //---------- resolving members code ----------- diff --git a/src/webpage/markdown.ts b/src/webpage/markdown.ts index 5072e5c1..0fef6e7d 100644 --- a/src/webpage/markdown.ts +++ b/src/webpage/markdown.ts @@ -300,11 +300,7 @@ class MarkDown{ } } if( - find === count && -(count != 1 || -txt[j + 1] === " " || -txt[j + 1] === "\n" || -txt[j + 1] === undefined) + find === count &&(count != 1 ||txt[j + 1] === " " ||txt[j + 1] === "\n" ||txt[j + 1] === undefined) ){ appendcurrent(); i = j; @@ -715,16 +711,37 @@ txt[j + 1] === undefined) box.onkeyup(new KeyboardEvent("_")); }; } + customBox?:[(arg1:string)=>HTMLElement,((arg1:HTMLElement)=>string)]; + clearCustom(){ + this.customBox=undefined; + } + setCustomBox(stringToHTML:(arg1:string)=>HTMLElement,HTMLToString=MarkDown.gatherBoxText.bind(MarkDown)){ + this.customBox=[stringToHTML,HTMLToString]; + } boxupdate(offset=0){ const box=this.box.deref(); if(!box) return; - const restore = saveCaretPosition(box,offset); + let restore:undefined|(()=>void); + if(this.customBox){ + restore= saveCaretPosition(box,offset,this.customBox[1]); + }else{ + restore= saveCaretPosition(box,offset) + } box.innerHTML = ""; - box.append(this.makeHTML({ keep: true })); + if(this.customBox){ + box.append(this.customBox[0](this.rawString)); + }else{ + box.append(this.makeHTML({ keep: true })); + } if(restore){ restore(); - const test=saveCaretPosition(box); - if(test) test(); + if(this.customBox){ + const test=saveCaretPosition(box,0,this.customBox[1]); + if(test) test(); + }else{ + const test=saveCaretPosition(box); + if(test) test(); + } } this.onUpdate(text,formatted); } @@ -816,7 +833,7 @@ txt[j + 1] === undefined) //solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div let text = ""; let formatted=false; -function saveCaretPosition(context: HTMLElement,offset=0){ +function saveCaretPosition(context: HTMLElement,offset=0,txtLengthFunc=MarkDown.gatherBoxText.bind(MarkDown)){ const selection = window.getSelection() as Selection; if(!selection)return; try{ @@ -837,7 +854,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){ i++; } if(base instanceof HTMLElement){ - baseString=MarkDown.gatherBoxText(base) + baseString=txtLengthFunc(base) }else{ baseString=base.textContent as string; } @@ -855,7 +872,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){ const children=[...context.childNodes]; if(children.length===1&&children[0] instanceof Text){ if(selection.containsNode(context,false)){ - build+=MarkDown.gatherBoxText(context as HTMLElement); + build+=txtLengthFunc(context as HTMLElement); }else if(selection.containsNode(context,true)){ if(context.contains(base)||context===base||base.contains(context)){ build+=baseString; @@ -871,7 +888,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){ if(selection.containsNode(node,false)){ if(node instanceof HTMLElement){ - build+=MarkDown.gatherBoxText(node); + build+=txtLengthFunc(node); }else{ build+=node.textContent; } @@ -892,10 +909,10 @@ function saveCaretPosition(context: HTMLElement,offset=0){ } text=build; let len=build.length+offset; - len=Math.min(len,MarkDown.gatherBoxText(context).length) + len=Math.min(len,txtLengthFunc(context).length) return function restore(){ if(!selection)return; - const pos = getTextNodeAtPosition(context, len); + const pos = getTextNodeAtPosition(context, len,txtLengthFunc); selection.removeAllRanges(); const range = new Range(); range.setStart(pos.node, pos.position); @@ -906,7 +923,7 @@ function saveCaretPosition(context: HTMLElement,offset=0){ } } -function getTextNodeAtPosition(root: Node, index: number):{ +function getTextNodeAtPosition(root: Node, index: number,txtLengthFunc=MarkDown.gatherBoxText.bind(MarkDown)):{ node: Node, position: number, }{ @@ -931,7 +948,7 @@ function getTextNodeAtPosition(root: Node, index: number):{ lastElm=node; let len:number if(node instanceof HTMLElement){ - len=MarkDown.gatherBoxText(node).length; + len=txtLengthFunc(node).length; }else{ len=(node.textContent as string).length } diff --git a/src/webpage/message.ts b/src/webpage/message.ts index 27d632bd..2d5bb5e4 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -101,12 +101,14 @@ class Message extends SnowFlake{ if(prev) prev.generateMessage(); this.generateMessage(undefined,false) } - constructor(messagejson: messagejson, owner: Channel){ + constructor(messagejson: messagejson, owner: Channel,dontStore=false){ super(messagejson.id); this.owner = owner; this.headers = this.owner.headers; this.giveData(messagejson); - this.owner.messages.set(this.id, this); + if(!dontStore){ + this.owner.messages.set(this.id, this); + } } reactionToggle(emoji: string | Emoji){ let remove = false; @@ -184,8 +186,11 @@ class Message extends SnowFlake{ } if(this.div){ this.generateMessage(); + return; + } + if(+this.id>+(this.channel.lastmessageid||"0")){ + func(); } - func(); } canDelete(){ return( @@ -338,15 +343,16 @@ class Message extends SnowFlake{ this.generateMessage(); } } - generateMessage(premessage?: Message | undefined, ignoredblock = false){ - if(!this.div)return; + generateMessage(premessage?: Message | undefined, ignoredblock = false,dupe:false|HTMLDivElement=false){ + const div = dupe||this.div; + if(!div)return; + const editmode=this.channel.editing===this; - if(!premessage){ + if(!premessage&&!dupe){ premessage = this.channel.messages.get( this.channel.idToPrev.get(this.id) as string ); } - const div = this.div; for(const user of this.mentions){ if(user === this.localuser.user){ div.classList.add("mentioned"); @@ -390,14 +396,10 @@ class Message extends SnowFlake{ build.classList.add("blocked", "topMessage"); const span = document.createElement("span"); let count = 1; - let next = this.channel.messages.get( - this.channel.idToNext.get(this.id) as string - ); + let next = this.channel.messages.get(this.channel.idToNext.get(this.id) as string); while(next?.author === this.author){ count++; - next = this.channel.messages.get( - this.channel.idToNext.get(next.id) as string - ); + next = this.channel.messages.get(this.channel.idToNext.get(next.id) as string); } span.textContent = I18n.getTranslation("showBlockedMessages",count+""); build.append(span); @@ -620,12 +622,14 @@ class Message extends SnowFlake{ text.append(time); div.classList.add("topMessage"); } - const reactions = document.createElement("div"); - reactions.classList.add("flexltr", "reactiondiv"); - this.reactdiv = new WeakRef(reactions); - this.updateReactions(); - div.append(reactions); - this.bindButtonEvent(); + if(!dupe){ + const reactions = document.createElement("div"); + reactions.classList.add("flexltr", "reactiondiv"); + this.reactdiv = new WeakRef(reactions); + this.updateReactions(); + div.append(reactions); + this.bindButtonEvent(); + } return div; } bindButtonEvent(){ @@ -829,7 +833,10 @@ class Message extends SnowFlake{ } } } - buildhtml(premessage?: Message | undefined): HTMLElement{ + buildhtml(premessage?: Message | undefined,dupe=false): HTMLElement{ + if(dupe){ + return this.generateMessage(premessage,false,document.createElement("div")) as HTMLElement; + } if(this.div){ console.error(`HTML for ${this.id} already exists, aborting`); return this.div; diff --git a/src/webpage/style.css b/src/webpage/style.css index ffeaef83..380c1b3c 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -61,6 +61,10 @@ body { flex-grow: 1; min-height: 0; } +.channelSTitle{ + margin-top:.2in; + margin-bottom:0; +} p, h1, h2, h3, pre, form { margin: 0; } @@ -957,6 +961,26 @@ span.instanceStatus { display:flex; flex-direction: row; } + +.searchBox:empty { + width:2in; +} +.searchBox { + white-space: nowrap; + height: .075in; + padding: 7px 10px 13px 10px; + background: var(--dock-bg); + border-radius: 4px; + /* overflow-y: auto; */ + display:flex; + flex-direction: row; + width: 3in; + margin: 0 .1in; + overflow: hidden; + margin-left: auto; + flex-shrink: 0; + transition: width .2s; +} .outerTypeBox > span::before { content: "\feff"; } @@ -1385,7 +1409,21 @@ img.bigembedimg { .acceptinvbutton:hover, .acceptinvbutton:disabled { background: color-mix(in hsl, var(--green) 80%, var(--black)); } - +#sideDiv.searchDiv{ + width: 30vw; + .topMessage{ + margin-top:2px; + margin-bottom:10px; + cursor:pointer; + padding:.05in; + border-radius:.075in; + background:#00000020; + } + .topMessage:hover{ + background:#00000050; + + } +} /* Sidebar */ #sideDiv { display: none; @@ -1396,6 +1434,7 @@ img.bigembedimg { overflow-y: auto; box-sizing: border-box; } + .memberList { padding-bottom: 16px; color: var(--primary-text-soft); @@ -1416,8 +1455,9 @@ img.bigembedimg { #memberlisttoggleicon { display: block; padding: 12px 0; - margin-left: auto; + margin-left: 0; cursor: pointer; + flex-grow: 0; } #memberlisttoggleicon span { height: 16px; diff --git a/src/webpage/user.ts b/src/webpage/user.ts index 6401446d..475bf0ce 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -9,7 +9,6 @@ import { Role } from "./role.js"; import { Search } from "./search.js"; import { I18n } from "./i18n.js"; import { Direct } from "./direct.js"; -import { Settings } from "./settings.js"; class User extends SnowFlake{ owner: Localuser; From d2d0f45c816f7a6bb0b2c64825d620264b1052e6 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 20 Dec 2024 19:28:08 -0600 Subject: [PATCH 0039/1178] formatting updates --- package.json | 6 + src/index.ts | 152 +-- src/stats.ts | 170 ++- src/utils.ts | 66 +- src/webpage/audio/audio.ts | 64 +- src/webpage/audio/index.html | 43 +- src/webpage/audio/page.ts | 199 +-- src/webpage/audio/play.ts | 88 +- src/webpage/audio/track.ts | 87 +- src/webpage/audio/voice.ts | 301 +++-- src/webpage/channel.ts | 1230 +++++++++--------- src/webpage/contextmenu.ts | 138 +- src/webpage/direct.ts | 457 +++---- src/webpage/disimg.ts | 38 +- src/webpage/embed.ts | 228 ++-- src/webpage/emoji.ts | 169 ++- src/webpage/file.ts | 54 +- src/webpage/guild.ts | 852 ++++++------ src/webpage/home.html | 65 +- src/webpage/home.ts | 119 +- src/webpage/hover.ts | 111 +- src/webpage/i18n.ts | 212 ++- src/webpage/index.html | 53 +- src/webpage/index.ts | 222 ++-- src/webpage/infiniteScroller.ts | 207 ++- src/webpage/invite.html | 33 +- src/webpage/invite.ts | 105 +- src/webpage/jsontypes.ts | 589 +++++---- src/webpage/localuser.ts | 2010 +++++++++++++++-------------- src/webpage/login.html | 50 +- src/webpage/login.ts | 216 ++-- src/webpage/markdown.ts | 817 ++++++------ src/webpage/member.ts | 452 +++---- src/webpage/message.ts | 686 +++++----- src/webpage/oauth2/auth.ts | 342 ++--- src/webpage/oauth2/authorize.html | 33 +- src/webpage/permissions.ts | 81 +- src/webpage/register.html | 63 +- src/webpage/register.ts | 125 +- src/webpage/role.ts | 420 +++--- src/webpage/search.ts | 134 +- src/webpage/service.ts | 127 +- src/webpage/settings.ts | 875 ++++++------- src/webpage/snowflake.ts | 14 +- src/webpage/style.css | 538 ++++---- src/webpage/themes.css | 8 +- src/webpage/user.ts | 601 ++++----- src/webpage/utils/binaryUtils.ts | 170 +-- src/webpage/utils/utils.ts | 600 +++++---- src/webpage/voice.ts | 825 ++++++------ 50 files changed, 7798 insertions(+), 7447 deletions(-) diff --git a/package.json b/package.json index bf586bab..e82819ff 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,12 @@ "prettier": "^3.4.2", "rimraf": "^6.0.1" }, + "prettier":{ + "useTabs":true, + "printWidth":100, + "semi":true, + "bracketSpacing":false + }, "devDependencies": { "@eslint/js": "^9.10.0", "@html-eslint/eslint-plugin": "^0.25.0", diff --git a/src/index.ts b/src/index.ts index 1b6040f8..6b9094e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,176 +1,180 @@ #!/usr/bin/env node -import compression from"compression"; -import express, { Request, Response }from"express"; -import fs from"node:fs/promises"; -import path from"node:path"; -import{ observe, uptime }from"./stats.js"; -import{ getApiUrls, inviteResponse }from"./utils.js"; -import{ fileURLToPath }from"node:url"; +import compression from "compression"; +import express, {Request, Response} from "express"; +import fs from "node:fs/promises"; +import path from "node:path"; +import {observe, uptime} from "./stats.js"; +import {getApiUrls, inviteResponse} from "./utils.js"; +import {fileURLToPath} from "node:url"; import {readFileSync} from "fs"; -import process from"node:process"; +import process from "node:process"; const devmode = (process.env.NODE_ENV || "development") === "development"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); interface Instance { - name: string; - [key: string]: any; + name: string; + [key: string]: any; } const app = express(); -type instace={ - name:string, - description?:string, - descriptionLong?:string, - image?:string, - url?:string, - language:string, - country:string, - display:boolean, - urls?:{ - wellknown:string, - api:string, - cdn:string, - gateway:string, - login?:string - }, - contactInfo?:{ - discord?:string, - github?:string, - email?:string, - spacebar?:string, - matrix?:string, - mastodon?:string - } -} -const instances=JSON.parse(readFileSync(process.env.JANK_INSTANCES_PATH||(__dirname+"/webpage/instances.json")).toString()) as instace[]; +type instace = { + name: string; + description?: string; + descriptionLong?: string; + image?: string; + url?: string; + language: string; + country: string; + display: boolean; + urls?: { + wellknown: string; + api: string; + cdn: string; + gateway: string; + login?: string; + }; + contactInfo?: { + discord?: string; + github?: string; + email?: string; + spacebar?: string; + matrix?: string; + mastodon?: string; + }; +}; +const instances = JSON.parse( + readFileSync(process.env.JANK_INSTANCES_PATH || __dirname + "/webpage/instances.json").toString(), +) as instace[]; const instanceNames = new Map(); -for(const instance of instances){ +for (const instance of instances) { instanceNames.set(instance.name, instance); } app.use(compression()); -async function updateInstances(): Promise{ - try{ - const response = await fetch("https://raw.githubusercontent.com/spacebarchat/spacebarchat/master/instances/instances.json"); +async function updateInstances(): Promise { + try { + const response = await fetch( + "https://raw.githubusercontent.com/spacebarchat/spacebarchat/master/instances/instances.json", + ); const json = (await response.json()) as Instance[]; - for(const instance of json){ - if(instanceNames.has(instance.name)){ + for (const instance of json) { + if (instanceNames.has(instance.name)) { const existingInstance = instanceNames.get(instance.name); - if(existingInstance){ - for(const key of Object.keys(instance)){ - if(!existingInstance[key]){ + if (existingInstance) { + for (const key of Object.keys(instance)) { + if (!existingInstance[key]) { existingInstance[key] = instance[key]; } } } - }else{ + } else { instances.push(instance as any); } } observe(instances); - }catch(error){ + } catch (error) { console.error("Error updating instances:", error); } } updateInstances(); -app.use("/getupdates", async (_req: Request, res: Response)=>{ - try{ +app.use("/getupdates", async (_req: Request, res: Response) => { + try { const stats = await fs.stat(path.join(__dirname, "webpage")); res.send(stats.mtimeMs.toString()); - }catch(error){ + } catch (error) { console.error("Error getting updates:", error); res.status(500).send("Error getting updates"); } }); -app.use("/services/oembed", (req: Request, res: Response)=>{ +app.use("/services/oembed", (req: Request, res: Response) => { inviteResponse(req, res); }); -app.use("/uptime", (req: Request, res: Response)=>{ +app.use("/uptime", (req: Request, res: Response) => { const instanceUptime = uptime.get(req.query.name as string); res.send(instanceUptime); }); -app.use("/", async (req: Request, res: Response)=>{ +app.use("/", async (req: Request, res: Response) => { const scheme = req.secure ? "https" : "http"; const host = `${scheme}://${req.get("Host")}`; const ref = host + req.originalUrl; - if(host && ref){ + if (host && ref) { const link = `${host}/services/oembed?url=${encodeURIComponent(ref)}`; res.set( "Link", - `<${link}>; rel="alternate"; type="application/json+oembed"; title="Jank Client oEmbed format"` + `<${link}>; rel="alternate"; type="application/json+oembed"; title="Jank Client oEmbed format"`, ); } - if(req.path === "/"){ + if (req.path === "/") { res.sendFile(path.join(__dirname, "webpage", "home.html")); return; } - if(req.path.startsWith("/instances.json")){ + if (req.path.startsWith("/instances.json")) { res.json(instances); return; } - if(req.path.startsWith("/invite/")){ + if (req.path.startsWith("/invite/")) { res.sendFile(path.join(__dirname, "webpage", "invite.html")); return; } const filePath = path.join(__dirname, "webpage", req.path); - try{ + try { await fs.access(filePath); - if(devmode){ + if (devmode) { const filePath2 = path.join(__dirname, "../src/webpage", req.path); - try{ + try { await fs.access(filePath2); res.sendFile(filePath2); return; - }catch{} + } catch {} } res.sendFile(filePath); - }catch{ - try{ + } catch { + try { await fs.access(`${filePath}.html`); - if(devmode){ + if (devmode) { const filePath2 = path.join(__dirname, "../src/webpage", req.path); - try{ + try { await fs.access(filePath2 + ".html"); res.sendFile(filePath2 + ".html"); return; - }catch{} + } catch {} } res.sendFile(`${filePath}.html`); - }catch{ - if(req.path.startsWith("/src/webpage")){ + } catch { + if (req.path.startsWith("/src/webpage")) { const filePath2 = path.join(__dirname, "..", req.path); - try{ + try { await fs.access(filePath2); res.sendFile(filePath2); return; - }catch{} + } catch {} } res.sendFile(path.join(__dirname, "webpage", "index.html")); } } }); -app.set('trust proxy', (ip:string) => ip.startsWith("127.")); +app.set("trust proxy", (ip: string) => ip.startsWith("127.")); const PORT = process.env.PORT || Number(process.argv[2]) || 8080; -app.listen(PORT, ()=>{ +app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); }); -export{ getApiUrls }; +export {getApiUrls}; diff --git a/src/stats.ts b/src/stats.ts index 1356d30d..d26062b0 100644 --- a/src/stats.ts +++ b/src/stats.ts @@ -1,39 +1,39 @@ -import fs from"node:fs"; -import path from"node:path"; -import{ getApiUrls }from"./utils.js"; -import{ fileURLToPath }from"node:url"; -import{ setTimeout, clearTimeout }from"node:timers"; +import fs from "node:fs"; +import path from "node:path"; +import {getApiUrls} from "./utils.js"; +import {fileURLToPath} from "node:url"; +import {setTimeout, clearTimeout} from "node:timers"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); interface UptimeEntry { - time: number; - online: boolean; + time: number; + online: boolean; } interface Instance { - name: string; - urls?: { api: string }; - url?: string; - online?: boolean; - uptime?: { - daytime: number; - weektime: number; - alltime: number; - }; + name: string; + urls?: {api: string}; + url?: string; + online?: boolean; + uptime?: { + daytime: number; + weektime: number; + alltime: number; + }; } const uptimeObject: Map = loadUptimeObject(); -export{ uptimeObject as uptime }; +export {uptimeObject as uptime}; -function loadUptimeObject(): Map{ - const filePath = process.env.JANK_UPTIME_JSON_PATH||path.join(__dirname, "..", "uptime.json"); - if(fs.existsSync(filePath)){ - try{ +function loadUptimeObject(): Map { + const filePath = process.env.JANK_UPTIME_JSON_PATH || path.join(__dirname, "..", "uptime.json"); + if (fs.existsSync(filePath)) { + try { const data = JSON.parse(fs.readFileSync(filePath, "utf8")); return new Map(Object.entries(data)); - }catch(error){ + } catch (error) { console.error("Error reading uptime.json:", error); return new Map(); } @@ -43,26 +43,26 @@ function loadUptimeObject(): Map{ let saveTimeout: ReturnType | null = null; -function saveUptimeObject(): void{ - if(saveTimeout){ +function saveUptimeObject(): void { + if (saveTimeout) { clearTimeout(saveTimeout); } - saveTimeout = setTimeout(()=>{ + saveTimeout = setTimeout(() => { const data = Object.fromEntries(uptimeObject); fs.writeFile( - process.env.JANK_UPTIME_JSON_PATH||path.join(__dirname, "..", "uptime.json"), + process.env.JANK_UPTIME_JSON_PATH || path.join(__dirname, "..", "uptime.json"), JSON.stringify(data), - error=>{ - if(error){ + (error) => { + if (error) { console.error("Error saving uptime.json:", error); } - } + }, ); }, 5000); // Batch updates every 5 seconds } -function removeUndefinedKey(): void{ - if(uptimeObject.has("undefined")){ +function removeUndefinedKey(): void { + if (uptimeObject.has("undefined")) { uptimeObject.delete("undefined"); saveUptimeObject(); } @@ -70,101 +70,89 @@ function removeUndefinedKey(): void{ removeUndefinedKey(); -export async function observe(instances: Instance[]): Promise{ +export async function observe(instances: Instance[]): Promise { const activeInstances = new Set(); - const instancePromises = instances.map(instance=>resolveInstance(instance, activeInstances) - ); + const instancePromises = instances.map((instance) => resolveInstance(instance, activeInstances)); await Promise.allSettled(instancePromises); updateInactiveInstances(activeInstances); } -async function resolveInstance( - instance: Instance, - activeInstances: Set -): Promise{ - try{ +async function resolveInstance(instance: Instance, activeInstances: Set): Promise { + try { calcStats(instance); const api = await getApiUrl(instance); - if(!api){ + if (!api) { handleUnresolvedApi(instance); return; } activeInstances.add(instance.name); await checkHealth(instance, api); scheduleHealthCheck(instance, api); - }catch(error){ + } catch (error) { console.error("Error resolving instance:", error); } } -async function getApiUrl(instance: Instance): Promise{ - if(instance.urls){ +async function getApiUrl(instance: Instance): Promise { + if (instance.urls) { return instance.urls.api; } - if(instance.url){ + if (instance.url) { const urls = await getApiUrls(instance.url); return urls ? urls.api : null; } return null; } -function handleUnresolvedApi(instance: Instance): void{ +function handleUnresolvedApi(instance: Instance): void { setStatus(instance, false); console.warn(`${instance.name} does not resolve api URL`, instance); - setTimeout(()=>resolveInstance(instance, new Set()), 1000 * 60 * 30); + setTimeout(() => resolveInstance(instance, new Set()), 1000 * 60 * 30); } -function scheduleHealthCheck(instance: Instance, api: string): void{ +function scheduleHealthCheck(instance: Instance, api: string): void { const checkInterval = 1000 * 60 * 30; const initialDelay = Math.random() * 1000 * 60 * 10; - setTimeout(()=>{ + setTimeout(() => { checkHealth(instance, api); - setInterval(()=>checkHealth(instance, api), checkInterval); + setInterval(() => checkHealth(instance, api), checkInterval); }, initialDelay); } -async function checkHealth( - instance: Instance, - api: string, - tries = 0 -): Promise{ - try{ - const response = await fetch(`${api}/ping`, { method: "HEAD" }); +async function checkHealth(instance: Instance, api: string, tries = 0): Promise { + try { + const response = await fetch(`${api}/ping`, {method: "HEAD"}); console.log(`Checking health for ${instance.name}: ${response.status}`); - if(response.ok || tries > 3){ + if (response.ok || tries > 3) { setStatus(instance, response.ok); - }else{ + } else { retryHealthCheck(instance, api, tries); } - }catch(error){ + } catch (error) { console.error(`Error checking health for ${instance.name}:`, error); - if(tries > 3){ + if (tries > 3) { setStatus(instance, false); - }else{ + } else { retryHealthCheck(instance, api, tries); } } } -function retryHealthCheck( - instance: Instance, - api: string, - tries: number -): void{ - setTimeout(()=>checkHealth(instance, api, tries + 1), 30000); +function retryHealthCheck(instance: Instance, api: string, tries: number): void { + setTimeout(() => checkHealth(instance, api, tries + 1), 30000); } -function updateInactiveInstances(activeInstances: Set): void{ - for(const key of uptimeObject.keys()){ - if(!activeInstances.has(key)){ +function updateInactiveInstances(activeInstances: Set): void { + for (const key of uptimeObject.keys()) { + if (!activeInstances.has(key)) { setStatus(key, false); } } } -function calcStats(instance: Instance): void{ +function calcStats(instance: Instance): void { const obj = uptimeObject.get(instance.name); - if(!obj)return; + if (!obj) return; const now = Date.now(); const day = now - 1000 * 60 * 60 * 24; @@ -176,7 +164,7 @@ function calcStats(instance: Instance): void{ let weektime = 0; let online = false; - for(let i = 0; i < obj.length; i++){ + for (let i = 0; i < obj.length; i++) { const entry = obj[i]; online = entry.online; const stamp = entry.time; @@ -186,11 +174,11 @@ function calcStats(instance: Instance): void{ totalTimePassed += timePassed; alltime += Number(online) * timePassed; - if(stamp + timePassed > week){ + if (stamp + timePassed > week) { const weekTimePassed = Math.min(timePassed, nextStamp - week); weektime += Number(online) * weekTimePassed; - if(stamp + timePassed > day){ + if (stamp + timePassed > day) { const dayTimePassed = Math.min(weekTimePassed, nextStamp - day); daytime += Number(online) * dayTimePassed; } @@ -198,13 +186,7 @@ function calcStats(instance: Instance): void{ } instance.online = online; - instance.uptime = calculateUptimeStats( - totalTimePassed, - alltime, - daytime, - weektime, - online - ); + instance.uptime = calculateUptimeStats(totalTimePassed, alltime, daytime, weektime, online); } function calculateUptimeStats( @@ -212,46 +194,46 @@ function calculateUptimeStats( alltime: number, daytime: number, weektime: number, - online: boolean -): { daytime: number; weektime: number; alltime: number }{ + online: boolean, +): {daytime: number; weektime: number; alltime: number} { const dayInMs = 1000 * 60 * 60 * 24; const weekInMs = dayInMs * 7; alltime /= totalTimePassed; - if(totalTimePassed > dayInMs){ + if (totalTimePassed > dayInMs) { daytime = daytime || (online ? dayInMs : 0); daytime /= dayInMs; - if(totalTimePassed > weekInMs){ + if (totalTimePassed > weekInMs) { weektime = weektime || (online ? weekInMs : 0); weektime /= weekInMs; - }else{ + } else { weektime = alltime; } - }else{ + } else { weektime = alltime; daytime = alltime; } - return{ daytime, weektime, alltime }; + return {daytime, weektime, alltime}; } -function setStatus(instance: string | Instance, status: boolean): void{ +function setStatus(instance: string | Instance, status: boolean): void { const name = typeof instance === "string" ? instance : instance.name; let obj = uptimeObject.get(name); - if(!obj){ + if (!obj) { obj = []; uptimeObject.set(name, obj); } const lastEntry = obj.at(-1); - if(!lastEntry || lastEntry.online !== status){ - obj.push({ time: Date.now(), online: status }); + if (!lastEntry || lastEntry.online !== status) { + obj.push({time: Date.now(), online: status}); saveUptimeObject(); - if(typeof instance !== "string"){ + if (typeof instance !== "string") { calcStats(instance); } } diff --git a/src/utils.ts b/src/utils.ts index 029a13c7..b553fa1d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,74 +1,76 @@ -import{ Request, Response }from"express"; +import {Request, Response} from "express"; interface ApiUrls { - api: string; - gateway: string; - cdn: string; - wellknown: string; + api: string; + gateway: string; + cdn: string; + wellknown: string; } interface Invite { - guild: { - name: string; - description?: string; - icon?: string; - id: string; - }; - inviter?: { - username: string; - }; + guild: { + name: string; + description?: string; + icon?: string; + id: string; + }; + inviter?: { + username: string; + }; } -export async function getApiUrls(url: string): Promise{ - if(!url.endsWith("/")){ +export async function getApiUrls(url: string): Promise { + if (!url.endsWith("/")) { url += "/"; } - try{ - const info: ApiUrls = await fetch(`${url}.well-known/spacebar`).then(res=>res.json()); + try { + const info: ApiUrls = await fetch(`${url}.well-known/spacebar`).then((res) => res.json()); const api = info.api; const apiUrl = new URL(api); const policies: any = await fetch( - `${api}${apiUrl.pathname.includes("api") ? "" : "api"}/policies/instance/domains` - ).then(res=>res.json()); - return{ + `${api}${apiUrl.pathname.includes("api") ? "" : "api"}/policies/instance/domains`, + ).then((res) => res.json()); + return { api: policies.apiEndpoint, gateway: policies.gateway, cdn: policies.cdn, wellknown: url, }; - }catch(error){ + } catch (error) { console.error("Error fetching API URLs:", error); return null; } } -export async function inviteResponse(req: Request, res: Response): Promise{ +export async function inviteResponse(req: Request, res: Response): Promise { let url: URL; - try{ + try { url = new URL(req.query.url as string); - }catch{ + } catch { const scheme = req.secure ? "https" : "http"; const host = `${scheme}://${req.get("Host")}`; url = new URL(host); } - try{ - if(url.pathname.startsWith("invite")){ + try { + if (url.pathname.startsWith("invite")) { throw new Error("Invalid invite URL"); } const code = url.pathname.split("/")[2]; const instance = url.searchParams.get("instance"); - if(!instance){ + if (!instance) { throw new Error("Instance not specified"); } const urls = await getApiUrls(instance); - if(!urls){ + if (!urls) { throw new Error("Failed to get API URLs"); } - const invite = await fetch(`${urls.api}/invites/${code}`).then(json=>json.json() as Promise); + const invite = await fetch(`${urls.api}/invites/${code}`).then( + (json) => json.json() as Promise, + ); const title = invite.guild.name; const description = invite.inviter ? `${invite.inviter.username} has invited you to ${invite.guild.name}${invite.guild.description ? `\n${invite.guild.description}` : ""}` @@ -84,7 +86,7 @@ export async function inviteResponse(req: Request, res: Response): Promise thumbnail, description, }); - }catch(error){ + } catch (error) { console.error("Error processing invite response:", error); res.json({ type: "link", @@ -95,4 +97,4 @@ export async function inviteResponse(req: Request, res: Response): Promise url: url.toString(), }); } -} \ No newline at end of file +} diff --git a/src/webpage/audio/audio.ts b/src/webpage/audio/audio.ts index d69a8c98..ecebd359 100644 --- a/src/webpage/audio/audio.ts +++ b/src/webpage/audio/audio.ts @@ -1,34 +1,34 @@ -import { BinRead } from "../utils/binaryUtils.js"; -import { Track } from "./track.js"; +import {BinRead} from "../utils/binaryUtils.js"; +import {Track} from "./track.js"; -export class Audio{ - name:string; - tracks:(Track|number)[]; - constructor(name:string,tracks:(Track|number)[]){ - this.tracks=tracks; - this.name=name; - } - static parse(read:BinRead,trackarr:Track[]):Audio{ - const name=read.readString8(); - const length=read.read16(); - const tracks:(Track|number)[]=[] - for(let i=0;isetTimeout(res,thing)); - } - } - } +export class Audio { + name: string; + tracks: (Track | number)[]; + constructor(name: string, tracks: (Track | number)[]) { + this.tracks = tracks; + this.name = name; + } + static parse(read: BinRead, trackarr: Track[]): Audio { + const name = read.readString8(); + const length = read.read16(); + const tracks: (Track | number)[] = []; + for (let i = 0; i < length; i++) { + let index = read.read16(); + if (index === 0) { + tracks.push(read.readFloat32()); + } else { + tracks.push(trackarr[index - 1]); + } + } + return new Audio(name, tracks); + } + async play() { + for (const thing of this.tracks) { + if (thing instanceof Track) { + thing.play(); + } else { + await new Promise((res) => setTimeout(res, thing)); + } + } + } } diff --git a/src/webpage/audio/index.html b/src/webpage/audio/index.html index 1d71d8f2..360beb53 100644 --- a/src/webpage/audio/index.html +++ b/src/webpage/audio/index.html @@ -1,26 +1,39 @@ - + - - - + + Jank Audio - - - - - - - + + + + + + + - +

This will eventually be something

-

I want to let the sound system of jank not be so hard coded, but I still need to work on everything a bit before that can happen. Thanks for your patience.

+

+ I want to let the sound system of jank not be so hard coded, but I still need to work on + everything a bit before that can happen. Thanks for your patience. +

why does this tool need to exist?

-

For size reasons jank does not use normal sound files, so I need to make this whole format to be more adaptable

+

+ For size reasons jank does not use normal sound files, so I need to make this whole format to + be more adaptable +

- diff --git a/src/webpage/audio/page.ts b/src/webpage/audio/page.ts index ccc5d45a..8905bd5f 100644 --- a/src/webpage/audio/page.ts +++ b/src/webpage/audio/page.ts @@ -1,9 +1,9 @@ -import { BinWrite } from "../utils/binaryUtils.js"; -import { setTheme } from "../utils/utils.js"; -import { Play } from "./play.js"; +import {BinWrite} from "../utils/binaryUtils.js"; +import {setTheme} from "../utils/utils.js"; +import {Play} from "./play.js"; setTheme(); -const w=new BinWrite(2**12); +const w = new BinWrite(2 ** 12); w.writeStringNo("jasf"); w.write8(4); @@ -18,100 +18,103 @@ w.writeString8("custom"); w.write32Float(150); //return Math.sin(((t + 2) ** Math.cos(t * 4)) * Math.PI * 2 * freq); //Math.sin((((t+2)**Math.cos((t*4)))*((Math.PI*2)*f))) -w.write8(4);//sin -w.write8(5)//times +w.write8(4); //sin +w.write8(5); //times { - w.write8(9);//Power - - { - w.write8(6);//adding - w.write8(1);//t - w.write8(0);w.write32Float(2);//2 - } - w.write8(13);//cos - w.write8(5);// times - w.write8(1);//t - w.write8(0);w.write32Float(4);//4 + w.write8(9); //Power + + { + w.write8(6); //adding + w.write8(1); //t + w.write8(0); + w.write32Float(2); //2 + } + w.write8(13); //cos + w.write8(5); // times + w.write8(1); //t + w.write8(0); + w.write32Float(4); //4 } { - w.write8(5)//times - w.write8(5)//times - w.write8(3);//PI - w.write8(0);w.write32Float(2);//2 - w.write8(2);//freq + w.write8(5); //times + w.write8(5); //times + w.write8(3); //PI + w.write8(0); + w.write32Float(2); //2 + w.write8(2); //freq } -w.write16(4);//3 tracks +w.write16(4); //3 tracks -w.write16(1);//zip +w.write16(1); //zip w.write8(4); -w.write32Float(1) -w.write32Float(700) +w.write32Float(1); +w.write32Float(700); -w.write16(3);//beep +w.write16(3); //beep { - w.write8(1); - w.write32Float(1) - w.write32Float(700); - w.write32Float(50); - - w.write8(0); - w.write32Float(100); - - w.write8(1); - w.write32Float(1) - w.write32Float(700); - w.write32Float(50); + w.write8(1); + w.write32Float(1); + w.write32Float(700); + w.write32Float(50); + + w.write8(0); + w.write32Float(100); + + w.write8(1); + w.write32Float(1); + w.write32Float(700); + w.write32Float(50); } -w.write16(5);//three +w.write16(5); //three { - w.write8(1); - w.write32Float(1) - w.write32Float(800); - w.write32Float(50); - - w.write8(0); - w.write32Float(50); - - w.write8(1); - w.write32Float(1) - w.write32Float(1000); - w.write32Float(50); - - w.write8(0); - w.write32Float(50); - - w.write8(1); - w.write32Float(1) - w.write32Float(1300); - w.write32Float(50); + w.write8(1); + w.write32Float(1); + w.write32Float(800); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(1); + w.write32Float(1); + w.write32Float(1000); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(1); + w.write32Float(1); + w.write32Float(1300); + w.write32Float(50); } -w.write16(5);//square +w.write16(5); //square { - w.write8(3); - w.write32Float(1) - w.write32Float(600); - w.write32Float(50); - - w.write8(0); - w.write32Float(50); - - w.write8(3); - w.write32Float(1) - w.write32Float(800); - w.write32Float(50); - - w.write8(0); - w.write32Float(50); - - w.write8(3); - w.write32Float(1) - w.write32Float(1000); - w.write32Float(50); + w.write8(3); + w.write32Float(1); + w.write32Float(600); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(3); + w.write32Float(1); + w.write32Float(800); + w.write32Float(50); + + w.write8(0); + w.write32Float(50); + + w.write8(3); + w.write32Float(1); + w.write32Float(1000); + w.write32Float(50); } -w.write16(4);//2 audio +w.write16(4); //2 audio w.writeString8("zip"); w.write16(1); @@ -128,8 +131,8 @@ w.write16(3); w.writeString8("square"); w.write16(1); w.write16(4); -const buff=w.getBuffer(); -const play=Play.parseBin(buff); +const buff = w.getBuffer(); +const play = Play.parseBin(buff); /* const zip=play.audios.get("square"); if(zip){ @@ -140,18 +143,18 @@ if(zip){ console.log(play.voices[3][0].info.wave) }; */ -console.log(play,buff); - -const download=document.getElementById("download"); -if(download){ - download.onclick=()=>{ - const blob = new Blob([buff], { type: "binary" }); - const downloadUrl = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = downloadUrl; - a.download = "sounds.jasf"; - document.body.appendChild(a); - a.click(); - URL.revokeObjectURL(downloadUrl); - } +console.log(play, buff); + +const download = document.getElementById("download"); +if (download) { + download.onclick = () => { + const blob = new Blob([buff], {type: "binary"}); + const downloadUrl = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = downloadUrl; + a.download = "sounds.jasf"; + document.body.appendChild(a); + a.click(); + URL.revokeObjectURL(downloadUrl); + }; } diff --git a/src/webpage/audio/play.ts b/src/webpage/audio/play.ts index 8ae81f96..eb6adca3 100644 --- a/src/webpage/audio/play.ts +++ b/src/webpage/audio/play.ts @@ -1,48 +1,48 @@ -import { BinRead } from "../utils/binaryUtils.js"; -import { Track } from "./track.js"; -import { AVoice } from "./voice.js"; -import { Audio } from "./audio.js"; -export class Play{ - voices:[AVoice,string][] - tracks:Track[] - audios:Map; - constructor(voices:[AVoice,string][],tracks:Track[],audios:Map){ - this.voices=voices; - this.tracks=tracks; - this.audios=audios; - } - static parseBin(buffer:ArrayBuffer){ - const read=new BinRead(buffer); - if(read.readStringNo(4)!=="jasf") throw new Error("this is not a jasf file"); - let voices=read.read8(); - let six=false; - if(voices===255){ - voices=read.read16(); - six=true; - } - const voiceArr:[AVoice,string][]=[]; - for(let i=0;i; + constructor(voices: [AVoice, string][], tracks: Track[], audios: Map) { + this.voices = voices; + this.tracks = tracks; + this.audios = audios; + } + static parseBin(buffer: ArrayBuffer) { + const read = new BinRead(buffer); + if (read.readStringNo(4) !== "jasf") throw new Error("this is not a jasf file"); + let voices = read.read8(); + let six = false; + if (voices === 255) { + voices = read.read16(); + six = true; + } + const voiceArr: [AVoice, string][] = []; + for (let i = 0; i < voices; i++) { + voiceArr.push(AVoice.getVoice(read)); + } - const tracks=read.read16(); - const trackArr:Track[]=[]; - for(let i=0;i(); - for(let i=0;i(); + for (let i = 0; i < audios; i++) { + const a = Audio.parse(read, trackArr); + audioArr.set(a.name, a); + } - return new Play(voiceArr,trackArr,audioArr); - } - static async playURL(url:string){ - const res=await fetch(url); - const arr=await res.arrayBuffer(); - return this.parseBin(arr); - } + return new Play(voiceArr, trackArr, audioArr); + } + static async playURL(url: string) { + const res = await fetch(url); + const arr = await res.arrayBuffer(); + return this.parseBin(arr); + } } diff --git a/src/webpage/audio/track.ts b/src/webpage/audio/track.ts index dac4af31..0e201448 100644 --- a/src/webpage/audio/track.ts +++ b/src/webpage/audio/track.ts @@ -1,46 +1,45 @@ -import { BinRead } from "../utils/binaryUtils.js"; -import { AVoice } from "./voice.js"; +import {BinRead} from "../utils/binaryUtils.js"; +import {AVoice} from "./voice.js"; -export class Track{ - seq:(AVoice|number)[]; - constructor(playing:(AVoice|number)[]){ - this.seq=playing; - } - static parse(read:BinRead,play:[AVoice,string][],six:boolean):Track{ - const length=read.read16(); - const play2:(AVoice|number)[]=[]; - for(let i=0;isetTimeout(res,thing)); - } - } - } +export class Track { + seq: (AVoice | number)[]; + constructor(playing: (AVoice | number)[]) { + this.seq = playing; + } + static parse(read: BinRead, play: [AVoice, string][], six: boolean): Track { + const length = read.read16(); + const play2: (AVoice | number)[] = []; + for (let i = 0; i < length; i++) { + let index: number; + if (six) { + index = read.read16(); + } else { + index = read.read8(); + } + if (index === 0) { + play2.push(read.readFloat32()); + continue; + } + index--; + if (!play[index]) throw new Error("voice not found"); + const [voice] = play[index]; + let temp: AVoice; + if (voice.info.wave instanceof Function) { + temp = voice.clone(read.readFloat32(), read.readFloat32()); + } else { + temp = voice.clone(read.readFloat32(), read.readFloat32(), read.readFloat32()); + } + play2.push(temp); + } + return new Track(play2); + } + async play() { + for (const thing of this.seq) { + if (thing instanceof AVoice) { + thing.playL(); + } else { + await new Promise((res) => setTimeout(res, thing)); + } + } + } } diff --git a/src/webpage/audio/voice.ts b/src/webpage/audio/voice.ts index 703fa126..69f1287d 100644 --- a/src/webpage/audio/voice.ts +++ b/src/webpage/audio/voice.ts @@ -1,23 +1,23 @@ -import { BinRead } from "../utils/binaryUtils.js"; +import {BinRead} from "../utils/binaryUtils.js"; -class AVoice{ +class AVoice { audioCtx: AudioContext; - info: { wave: string | Function; freq: number }; + info: {wave: string | Function; freq: number}; playing: boolean; myArrayBuffer: AudioBuffer; gainNode: GainNode; buffer: Float32Array; source: AudioBufferSourceNode; - length=1; - constructor(wave: string | Function, freq: number, volume = 1,length=1000){ - this.length=length; + length = 1; + constructor(wave: string | Function, freq: number, volume = 1, length = 1000) { + this.length = length; this.audioCtx = new window.AudioContext(); - this.info = { wave, freq }; + this.info = {wave, freq}; this.playing = false; this.myArrayBuffer = this.audioCtx.createBuffer( 1, - this.audioCtx.sampleRate*length/1000, - this.audioCtx.sampleRate + (this.audioCtx.sampleRate * length) / 1000, + this.audioCtx.sampleRate, ); this.gainNode = this.audioCtx.createGain(); this.gainNode.gain.value = volume; @@ -29,193 +29,193 @@ class AVoice{ this.source.start(); this.updateWave(); } - clone(volume:number,freq:number,length=this.length){ - return new AVoice(this.wave,freq,volume,length); + clone(volume: number, freq: number, length = this.length) { + return new AVoice(this.wave, freq, volume, length); } - get wave(): string | Function{ + get wave(): string | Function { return this.info.wave; } - get freq(): number{ + get freq(): number { return this.info.freq; } - set wave(wave: string | Function){ + set wave(wave: string | Function) { this.info.wave = wave; this.updateWave(); } - set freq(freq: number){ + set freq(freq: number) { this.info.freq = freq; this.updateWave(); } - updateWave(): void{ + updateWave(): void { const func = this.waveFunction(); - for(let i = 0; i < this.buffer.length; i++){ + for (let i = 0; i < this.buffer.length; i++) { this.buffer[i] = func(i / this.audioCtx.sampleRate, this.freq); } } - waveFunction(): Function{ - if(typeof this.wave === "function"){ + waveFunction(): Function { + if (typeof this.wave === "function") { return this.wave; } - switch(this.wave){ - case"sin": - return(t: number, freq: number)=>{ - return Math.sin(t * Math.PI * 2 * freq); - }; - case"triangle": - return(t: number, freq: number)=>{ - return Math.abs(((4 * t * freq) % 4) - 2) - 1; - }; - case"sawtooth": - return(t: number, freq: number)=>{ - return((t * freq) % 1) * 2 - 1; - }; - case"square": - return(t: number, freq: number)=>{ - return(t * freq) % 2 < 1 ? 1 : -1; - }; - case"white": - return(_t: number, _freq: number)=>{ - return Math.random() * 2 - 1; - }; + switch (this.wave) { + case "sin": + return (t: number, freq: number) => { + return Math.sin(t * Math.PI * 2 * freq); + }; + case "triangle": + return (t: number, freq: number) => { + return Math.abs(((4 * t * freq) % 4) - 2) - 1; + }; + case "sawtooth": + return (t: number, freq: number) => { + return ((t * freq) % 1) * 2 - 1; + }; + case "square": + return (t: number, freq: number) => { + return (t * freq) % 2 < 1 ? 1 : -1; + }; + case "white": + return (_t: number, _freq: number) => { + return Math.random() * 2 - 1; + }; } return new Function(); } - play(): void{ - if(this.playing){ + play(): void { + if (this.playing) { return; } this.source.connect(this.gainNode); this.playing = true; } - playL(){ + playL() { this.play(); - setTimeout(()=>{ + setTimeout(() => { this.stop(); - },this.length); + }, this.length); } - stop(): void{ - if(this.playing){ + stop(): void { + if (this.playing) { this.source.disconnect(); this.playing = false; } } - static noises(noise: string): void{ - switch(noise){ - case"three": { - const voicy = new AVoice("sin", 800); - voicy.play(); - setTimeout(_=>{ - voicy.freq = 1000; - }, 50); - setTimeout(_=>{ - voicy.freq = 1300; - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case"zip": { - const voicy = new AVoice((t: number, freq: number)=>{ - return Math.sin((t + 2) ** Math.cos(t * 4) * Math.PI * 2 * freq); - }, 700); - voicy.play(); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case"square": { - const voicy = new AVoice("square", 600, 0.4); - voicy.play(); - setTimeout(_=>{ - voicy.freq = 800; - }, 50); - setTimeout(_=>{ - voicy.freq = 1000; - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case"beep": { - const voicy = new AVoice("sin", 800); - voicy.play(); - setTimeout(_=>{ - voicy.stop(); - }, 50); - setTimeout(_=>{ + static noises(noise: string): void { + switch (noise) { + case "three": { + const voicy = new AVoice("sin", 800); voicy.play(); - }, 100); - setTimeout(_=>{ - voicy.stop(); - }, 150); - break; - } - case "join":{ - const voicy = new AVoice("triangle", 600,.1); - voicy.play(); - setTimeout(_=>{ - voicy.freq=800; - }, 75); - setTimeout(_=>{ - voicy.freq=1000; - }, 150); - setTimeout(_=>{ - voicy.stop(); - }, 200); - break; - } - case "leave":{ - const voicy = new AVoice("triangle", 850,.5); - voicy.play(); - setTimeout(_=>{ - voicy.freq=700; - }, 100); - setTimeout(_=>{ - voicy.stop(); - voicy.freq=400; - }, 180); - setTimeout(_=>{ + setTimeout((_) => { + voicy.freq = 1000; + }, 50); + setTimeout((_) => { + voicy.freq = 1300; + }, 100); + setTimeout((_) => { + voicy.stop(); + }, 150); + break; + } + case "zip": { + const voicy = new AVoice((t: number, freq: number) => { + return Math.sin((t + 2) ** Math.cos(t * 4) * Math.PI * 2 * freq); + }, 700); voicy.play(); - }, 200); - setTimeout(_=>{ - voicy.stop(); - }, 250); - break; - } + setTimeout((_) => { + voicy.stop(); + }, 150); + break; + } + case "square": { + const voicy = new AVoice("square", 600, 0.4); + voicy.play(); + setTimeout((_) => { + voicy.freq = 800; + }, 50); + setTimeout((_) => { + voicy.freq = 1000; + }, 100); + setTimeout((_) => { + voicy.stop(); + }, 150); + break; + } + case "beep": { + const voicy = new AVoice("sin", 800); + voicy.play(); + setTimeout((_) => { + voicy.stop(); + }, 50); + setTimeout((_) => { + voicy.play(); + }, 100); + setTimeout((_) => { + voicy.stop(); + }, 150); + break; + } + case "join": { + const voicy = new AVoice("triangle", 600, 0.1); + voicy.play(); + setTimeout((_) => { + voicy.freq = 800; + }, 75); + setTimeout((_) => { + voicy.freq = 1000; + }, 150); + setTimeout((_) => { + voicy.stop(); + }, 200); + break; + } + case "leave": { + const voicy = new AVoice("triangle", 850, 0.5); + voicy.play(); + setTimeout((_) => { + voicy.freq = 700; + }, 100); + setTimeout((_) => { + voicy.stop(); + voicy.freq = 400; + }, 180); + setTimeout((_) => { + voicy.play(); + }, 200); + setTimeout((_) => { + voicy.stop(); + }, 250); + break; + } } } - static get sounds(){ - return["three", "zip", "square", "beep"]; + static get sounds() { + return ["three", "zip", "square", "beep"]; } - static getVoice(read:BinRead):[AVoice,string]{ + static getVoice(read: BinRead): [AVoice, string] { const name = read.readString8(); - let length=read.readFloat32(); - let special:Function|string - if(length!==0){ - special=this.parseExpression(read); - }else{ - special=name; - length=1; + let length = read.readFloat32(); + let special: Function | string; + if (length !== 0) { + special = this.parseExpression(read); + } else { + special = name; + length = 1; } - return [new AVoice(special,0,0,length),name] + return [new AVoice(special, 0, 0, length), name]; } - static parseExpression(read:BinRead):Function{ - return new Function("t","f",`return ${this.PEHelper(read)};`); + static parseExpression(read: BinRead): Function { + return new Function("t", "f", `return ${this.PEHelper(read)};`); } - static PEHelper(read:BinRead):string{ - let state=read.read8(); - switch(state){ + static PEHelper(read: BinRead): string { + let state = read.read8(); + switch (state) { case 0: - return ""+read.readFloat32(); + return "" + read.readFloat32(); case 1: return "t"; case 2: return "f"; case 3: - return `Math.PI` + return `Math.PI`; case 4: return `Math.sin(${this.PEHelper(read)})`; case 5: @@ -238,9 +238,8 @@ class AVoice{ return `Math.cos(${this.PEHelper(read)})`; default: throw new Error("unexpected case found!"); - } } } -export{ AVoice as AVoice }; +export {AVoice as AVoice}; diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 9b0d4295..cd043d46 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -1,27 +1,34 @@ "use strict"; -import{ Message }from"./message.js"; -import{ AVoice }from"./audio/voice.js"; -import{ Contextmenu }from"./contextmenu.js"; -import{ Guild }from"./guild.js"; -import{ Localuser }from"./localuser.js"; -import{ Permissions }from"./permissions.js"; -import{ Dialog, Float, Settings }from"./settings.js"; -import{ Role, RoleList }from"./role.js"; -import{ InfiniteScroller }from"./infiniteScroller.js"; -import{ SnowFlake }from"./snowflake.js"; -import{channeljson,embedjson,messageCreateJson,messagejson,readyjson,startTypingjson}from"./jsontypes.js"; -import{ MarkDown }from"./markdown.js"; -import{ Member }from"./member.js"; -import { Voice } from "./voice.js"; -import { User } from "./user.js"; -import { I18n } from "./i18n.js"; +import {Message} from "./message.js"; +import {AVoice} from "./audio/voice.js"; +import {Contextmenu} from "./contextmenu.js"; +import {Guild} from "./guild.js"; +import {Localuser} from "./localuser.js"; +import {Permissions} from "./permissions.js"; +import {Dialog, Float, Settings} from "./settings.js"; +import {Role, RoleList} from "./role.js"; +import {InfiniteScroller} from "./infiniteScroller.js"; +import {SnowFlake} from "./snowflake.js"; +import { + channeljson, + embedjson, + messageCreateJson, + messagejson, + readyjson, + startTypingjson, +} from "./jsontypes.js"; +import {MarkDown} from "./markdown.js"; +import {Member} from "./member.js"; +import {Voice} from "./voice.js"; +import {User} from "./user.js"; +import {I18n} from "./i18n.js"; declare global { -interface NotificationOptions { -image?: string | null | undefined; -} + interface NotificationOptions { + image?: string | null | undefined; + } } -class Channel extends SnowFlake{ +class Channel extends SnowFlake { editing!: Message | null; type!: number; owner!: Guild; @@ -38,11 +45,11 @@ class Channel extends SnowFlake{ position: number = 0; lastreadmessageid: string | undefined; lastmessageid: string | undefined; - mentions=0; + mentions = 0; lastpin!: string; move_id?: string; typing!: number; - message_notifications:number=3; + message_notifications: number = 3; allthewayup!: boolean; static contextmenu = new Contextmenu("channel menu"); replyingto!: Message | null; @@ -50,60 +57,76 @@ class Channel extends SnowFlake{ idToPrev: Map = new Map(); idToNext: Map = new Map(); messages: Map = new Map(); - voice?:Voice; - bitrate:number=128000; + voice?: Voice; + bitrate: number = 128000; - muted:boolean=false; - mute_config= {selected_time_window: -1,end_time: 0} - handleUserOverrides(settings:{message_notifications: number,muted: boolean,mute_config: {selected_time_window: number,end_time: number},channel_id: string}){ - this.message_notifications=settings.message_notifications; - this.muted=settings.muted; - this.mute_config=settings.mute_config; + muted: boolean = false; + mute_config = {selected_time_window: -1, end_time: 0}; + handleUserOverrides(settings: { + message_notifications: number; + muted: boolean; + mute_config: {selected_time_window: number; end_time: number}; + channel_id: string; + }) { + this.message_notifications = settings.message_notifications; + this.muted = settings.muted; + this.mute_config = settings.mute_config; } - static setupcontextmenu(){ - this.contextmenu.addbutton(()=>I18n.getTranslation("channel.copyId"), function(this: Channel){ - navigator.clipboard.writeText(this.id); - }); + static setupcontextmenu() { + this.contextmenu.addbutton( + () => I18n.getTranslation("channel.copyId"), + function (this: Channel) { + navigator.clipboard.writeText(this.id); + }, + ); - this.contextmenu.addbutton(()=>I18n.getTranslation("channel.markRead"), function(this: Channel){ - this.readbottom(); - }); + this.contextmenu.addbutton( + () => I18n.getTranslation("channel.markRead"), + function (this: Channel) { + this.readbottom(); + }, + ); - this.contextmenu.addbutton(()=>I18n.getTranslation("channel.settings"), function(this: Channel){ - this.generateSettings(); - },null,function(){ - return this.hasPermission("MANAGE_CHANNELS"); - }); + this.contextmenu.addbutton( + () => I18n.getTranslation("channel.settings"), + function (this: Channel) { + this.generateSettings(); + }, + null, + function () { + return this.hasPermission("MANAGE_CHANNELS"); + }, + ); this.contextmenu.addbutton( - ()=>I18n.getTranslation("channel.delete"), - function(this: Channel){ + () => I18n.getTranslation("channel.delete"), + function (this: Channel) { this.deleteChannel(); }, null, - function(){ + function () { return this.isAdmin(); - } + }, ); this.contextmenu.addbutton( - ()=>I18n.getTranslation("guild.notifications"), - function(){ + () => I18n.getTranslation("guild.notifications"), + function () { this.setnotifcation(); - } - ) + }, + ); this.contextmenu.addbutton( - ()=>I18n.getTranslation("channel.makeInvite"), - function(this: Channel){ + () => I18n.getTranslation("channel.makeInvite"), + function (this: Channel) { this.createInvite(); }, null, - function(){ + function () { return this.hasPermission("CREATE_INSTANT_INVITE") && this.type !== 4; - } + }, ); } - createInvite(){ + createInvite() { const div = document.createElement("div"); div.classList.add("invitediv"); const text = document.createElement("span"); @@ -116,13 +139,13 @@ class Channel extends SnowFlake{ const copy = document.createElement("span"); copy.classList.add("copybutton", "svgicon", "svg-copy"); copycontainer.append(copy); - copycontainer.onclick = _=>{ - if(text.textContent){ + copycontainer.onclick = (_) => { + if (text.textContent) { navigator.clipboard.writeText(text.textContent); } }; div.append(copycontainer); - const update = ()=>{ + const update = () => { fetch(`${this.info.api}/channels/${this.id}/invites`, { method: "POST", headers: this.headers, @@ -135,8 +158,8 @@ class Channel extends SnowFlake{ temporary: uses !== 0, }), }) - .then(_=>_.json()) - .then(json=>{ + .then((_) => _.json()) + .then((json) => { const params = new URLSearchParams(""); params.set("instance", this.info.wellknown); const encoded = params.toString(); @@ -144,45 +167,75 @@ class Channel extends SnowFlake{ }); }; update(); - const inviteOptions=new Dialog("",{noSubmit:true}); + const inviteOptions = new Dialog("", {noSubmit: true}); inviteOptions.options.addTitle(I18n.getTranslation("inviteOptions.title")); - inviteOptions.options.addText(I18n.getTranslation("invite.subtext",this.name,this.guild.properties.name)); + inviteOptions.options.addText( + I18n.getTranslation("invite.subtext", this.name, this.guild.properties.name), + ); - inviteOptions.options.addSelect(I18n.getTranslation("invite.expireAfter"),()=>{}, - ["30m","1h","6h","12h","1d","7d","30d","never"].map((e)=>I18n.getTranslation("inviteOptions."+e)) - ).onchange=(e)=>{expires=[1800, 3600, 21600, 43200, 86400, 604800, 2592000, 0][e];update()}; + inviteOptions.options.addSelect( + I18n.getTranslation("invite.expireAfter"), + () => {}, + ["30m", "1h", "6h", "12h", "1d", "7d", "30d", "never"].map((e) => + I18n.getTranslation("inviteOptions." + e), + ), + ).onchange = (e) => { + expires = [1800, 3600, 21600, 43200, 86400, 604800, 2592000, 0][e]; + update(); + }; - const timeOptions=["1","5","10","25","50","100"].map((e)=>I18n.getTranslation("inviteOptions.limit",e)) - timeOptions.unshift(I18n.getTranslation("inviteOptions.noLimit")) - inviteOptions.options.addSelect(I18n.getTranslation("invite.expireAfter"),()=>{},timeOptions) - .onchange=(e)=>{uses=[0, 1, 5, 10, 25, 50, 100][e];update()}; + const timeOptions = ["1", "5", "10", "25", "50", "100"].map((e) => + I18n.getTranslation("inviteOptions.limit", e), + ); + timeOptions.unshift(I18n.getTranslation("inviteOptions.noLimit")); + inviteOptions.options.addSelect( + I18n.getTranslation("invite.expireAfter"), + () => {}, + timeOptions, + ).onchange = (e) => { + uses = [0, 1, 5, 10, 25, 50, 100][e]; + update(); + }; inviteOptions.options.addHTMLArea(div); inviteOptions.show(); } - generateSettings(){ + generateSettings() { this.sortPerms(); - const settings = new Settings(I18n.getTranslation("channel.settingsFor",this.name)); + const settings = new Settings(I18n.getTranslation("channel.settingsFor", this.name)); { - const gensettings=settings.addButton("Settings"); - const form=gensettings.addForm("",()=>{},{ - fetchURL:this.info.api + "/channels/" + this.id, + const gensettings = settings.addButton("Settings"); + const form = gensettings.addForm("", () => {}, { + fetchURL: this.info.api + "/channels/" + this.id, method: "PATCH", headers: this.headers, }); - form.addTextInput(I18n.getTranslation("channel.name:"),"name",{initText:this.name}); - form.addMDInput(I18n.getTranslation("channel.topic:"),"topic",{initText:this.topic}); - form.addCheckboxInput(I18n.getTranslation("channel.nsfw:"),"nsfw",{initState:this.nsfw}); - if(this.type!==4){ - const options=["voice", "text", "announcement"]; - form.addSelect("Type:","type",options.map(e=>I18n.getTranslation("channel."+e)),{ - defaultIndex:options.indexOf({0:"text", 2:"voice", 5:"announcement", 4:"category" }[this.type] as string) - },options); - form.addPreprocessor((obj:any)=>{ - obj.type={text: 0, voice: 2, announcement: 5, category: 4 }[obj.type as string] - }) + form.addTextInput(I18n.getTranslation("channel.name:"), "name", { + initText: this.name, + }); + form.addMDInput(I18n.getTranslation("channel.topic:"), "topic", { + initText: this.topic, + }); + form.addCheckboxInput(I18n.getTranslation("channel.nsfw:"), "nsfw", { + initState: this.nsfw, + }); + if (this.type !== 4) { + const options = ["voice", "text", "announcement"]; + form.addSelect( + "Type:", + "type", + options.map((e) => I18n.getTranslation("channel." + e)), + { + defaultIndex: options.indexOf( + {0: "text", 2: "voice", 5: "announcement", 4: "category"}[this.type] as string, + ), + }, + options, + ); + form.addPreprocessor((obj: any) => { + obj.type = {text: 0, voice: 2, announcement: 5, category: 4}[obj.type as string]; + }); } - } const s1 = settings.addButton("Permissions"); s1.options.push( @@ -190,78 +243,70 @@ class Channel extends SnowFlake{ this.permission_overwritesar, this.guild, this.updateRolePermissions.bind(this), - this - ) + this, + ), ); settings.show(); } - sortPerms(){ - this.permission_overwritesar.sort((a, b)=>{ - return( - this.guild.roles.indexOf(a[0]) - - this.guild.roles.indexOf(b[0]) - ); + sortPerms() { + this.permission_overwritesar.sort((a, b) => { + return this.guild.roles.indexOf(a[0]) - this.guild.roles.indexOf(b[0]); }); } - setUpInfiniteScroller(){ + setUpInfiniteScroller() { this.infinite = new InfiniteScroller( - async (id: string, offset: number): Promise=>{ - if(offset === 1){ - if(this.idToPrev.has(id)){ + async (id: string, offset: number): Promise => { + if (offset === 1) { + if (this.idToPrev.has(id)) { return this.idToPrev.get(id); - }else{ + } else { await this.grabBefore(id); return this.idToPrev.get(id); } - }else{ - if(this.idToNext.has(id)){ + } else { + if (this.idToNext.has(id)) { return this.idToNext.get(id); - }else if(this.lastmessage?.id !== id){ + } else if (this.lastmessage?.id !== id) { await this.grabAfter(id); return this.idToNext.get(id); - }else{ - + } else { } } return undefined; }, - async (id: string): Promise=>{ + async (id: string): Promise => { //await new Promise(_=>{setTimeout(_,Math.random()*10)}) const messgage = this.messages.get(id); - try{ - if(messgage){ + try { + if (messgage) { return messgage.buildhtml(); - }else{ + } else { console.error(id + " not found"); } - }catch(e){ + } catch (e) { console.error(e); } return document.createElement("div"); }, - async (id: string)=>{ + async (id: string) => { const message = this.messages.get(id); - try{ - if(message){ + try { + if (message) { message.deleteDiv(); return true; } - }catch(e){ + } catch (e) { console.error(e); - }finally{ + } finally { } return false; }, - this.readbottom.bind(this) + this.readbottom.bind(this), ); } - constructor( - json: channeljson | -1, - owner: Guild, - id: string = json === -1 ? "" : json.id - ){ + constructor(json: channeljson | -1, owner: Guild, id: string = json === -1 ? "" : json.id) { super(id); - if(json === -1){ + if (json === -1) { return; } this.editing; @@ -269,7 +314,7 @@ class Channel extends SnowFlake{ this.owner = owner; this.headers = this.owner.headers; this.name = json.name; - if(json.parent_id){ + if (json.parent_id) { this.parent_id = json.parent_id; } this.parent = undefined; @@ -277,20 +322,17 @@ class Channel extends SnowFlake{ this.guild_id = json.guild_id; this.permission_overwrites = new Map(); this.permission_overwritesar = []; - for(const thing of json.permission_overwrites){ - if(thing.id === "1182819038095799904" ||thing.id === "1182820803700625444"){ + for (const thing of json.permission_overwrites) { + if (thing.id === "1182819038095799904" || thing.id === "1182820803700625444") { continue; } - if(!this.permission_overwrites.has(thing.id)){ + if (!this.permission_overwrites.has(thing.id)) { //either a bug in the server requires this, or the API is cursed - this.permission_overwrites.set( - thing.id, - new Permissions(thing.allow, thing.deny) - ); + this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny)); const permission = this.permission_overwrites.get(thing.id); - if(permission){ + if (permission) { const role = this.guild.roleids.get(thing.id); - if(role){ + if (role) { this.permission_overwritesar.push([role, permission]); } } @@ -301,126 +343,128 @@ class Channel extends SnowFlake{ this.nsfw = json.nsfw; this.position = json.position; this.lastreadmessageid = undefined; - if(json.last_message_id){ + if (json.last_message_id) { this.lastmessageid = json.last_message_id; - }else{ + } else { this.lastmessageid = undefined; } this.setUpInfiniteScroller(); this.perminfo ??= {}; - if(this.type===2&&this.localuser.voiceFactory){ - this.voice=this.localuser.voiceFactory.makeVoice(this.guild.id,this.id,{bitrate:this.bitrate}); + if (this.type === 2 && this.localuser.voiceFactory) { + this.voice = this.localuser.voiceFactory.makeVoice(this.guild.id, this.id, { + bitrate: this.bitrate, + }); this.setUpVoice(); } } - get perminfo(){ + get perminfo() { return this.guild.perminfo.channels[this.id]; } - set perminfo(e){ + set perminfo(e) { this.guild.perminfo.channels[this.id] = e; } - isAdmin(){ + isAdmin() { return this.guild.isAdmin(); } - get guild(){ + get guild() { return this.owner; } - get localuser(){ + get localuser() { return this.guild.localuser; } - get info(){ + get info() { return this.owner.info; } - readStateInfo(json: readyjson["d"]["read_state"]["entries"][0]){ + readStateInfo(json: readyjson["d"]["read_state"]["entries"][0]) { this.lastreadmessageid = json.last_message_id; this.mentions = json.mention_count; this.mentions ??= 0; this.lastpin = json.last_pin_timestamp; } - get hasunreads(): boolean{ - if(!this.hasPermission("VIEW_CHANNEL")){ + get hasunreads(): boolean { + if (!this.hasPermission("VIEW_CHANNEL")) { return false; } - return( + return ( Boolean(this.lastmessageid) && (!this.lastreadmessageid || - SnowFlake.stringToUnixTime(this.lastmessageid as string) > - SnowFlake.stringToUnixTime(this.lastreadmessageid)) && + SnowFlake.stringToUnixTime(this.lastmessageid as string) > + SnowFlake.stringToUnixTime(this.lastreadmessageid)) && this.type !== 4 ); } - hasPermission(name: string, member = this.guild.member): boolean{ - if(member.isAdmin()){ + hasPermission(name: string, member = this.guild.member): boolean { + if (member.isAdmin()) { return true; } - const roles=new Set(member.roles); - const everyone=this.guild.roles[this.guild.roles.length-1]; - if(!member.user.bot||true){ - roles.add(everyone) + const roles = new Set(member.roles); + const everyone = this.guild.roles[this.guild.roles.length - 1]; + if (!member.user.bot || true) { + roles.add(everyone); } - for(const thing of roles){ + for (const thing of roles) { const premission = this.permission_overwrites.get(thing.id); - if(premission){ + if (premission) { const perm = premission.getPermission(name); - if(perm){ + if (perm) { return perm === 1; } } - if(thing.permissions.getPermission(name)){ + if (thing.permissions.getPermission(name)) { return true; } } return false; } - get canMessage(): boolean{ - if(this.permission_overwritesar.length === 0 &&this.hasPermission("MANAGE_CHANNELS")){ - const role = this.guild.roles.find(_=>_.name === "@everyone"); - if(role){ + get canMessage(): boolean { + if (this.permission_overwritesar.length === 0 && this.hasPermission("MANAGE_CHANNELS")) { + const role = this.guild.roles.find((_) => _.name === "@everyone"); + if (role) { this.addRoleToPerms(role); } } return this.hasPermission("SEND_MESSAGES"); } - sortchildren(){ - this.children.sort((a, b)=>{ + sortchildren() { + this.children.sort((a, b) => { return a.position - b.position; }); } - resolveparent(_guild: Guild){ + resolveparent(_guild: Guild) { const parentid = this.parent_id; - if(!parentid)return false; + if (!parentid) return false; this.parent = this.localuser.channelids.get(parentid); this.parent ??= undefined; - if(this.parent !== undefined){ + if (this.parent !== undefined) { this.parent.children.push(this); } return this.parent !== undefined; } - calculateReorder(){ + calculateReorder() { let position = -1; const build: { id: string; position: number | undefined; parent_id: string | undefined; }[] = []; - for(const thing of this.children){ + for (const thing of this.children) { const thisthing: { id: string; position: number | undefined; parent_id: string | undefined; - } = { id: thing.id, position: undefined, parent_id: undefined }; + } = {id: thing.id, position: undefined, parent_id: undefined}; - if(thing.position < position){ + if (thing.position < position) { thing.position = thisthing.position = position + 1; } position = thing.position; - if(thing.move_id && thing.move_id !== thing.parent_id){ + if (thing.move_id && thing.move_id !== thing.parent_id) { thing.parent_id = thing.move_id; thisthing.parent_id = thing.parent?.id; thing.move_id = undefined; //console.log(this.guild.channelids[thisthing.parent_id.id]); } - if(thisthing.position || thisthing.parent_id){ + if (thisthing.position || thisthing.parent_id) { build.push(thisthing); } } @@ -428,35 +472,35 @@ class Channel extends SnowFlake{ } static dragged: [Channel, HTMLDivElement] | [] = []; html: WeakRef | undefined; - get visable(){ + get visable() { return this.hasPermission("VIEW_CHANNEL"); } - voiceUsers=new WeakRef(document.createElement("div")); - createguildHTML(admin = false): HTMLDivElement{ + voiceUsers = new WeakRef(document.createElement("div")); + createguildHTML(admin = false): HTMLDivElement { const div = document.createElement("div"); this.html = new WeakRef(div); - if(!this.visable){ + if (!this.visable) { let quit = true; - for(const thing of this.children){ - if(thing.visable){ + for (const thing of this.children) { + if (thing.visable) { quit = false; } } - if(quit){ + if (quit) { return div; } } // @ts-ignore I dont wanna deal with this div.all = this; div.draggable = admin; - div.addEventListener("dragstart", e=>{ + div.addEventListener("dragstart", (e) => { Channel.dragged = [this, div]; e.stopImmediatePropagation(); }); - div.addEventListener("dragend", ()=>{ + div.addEventListener("dragend", () => { Channel.dragged = []; }); - if(this.type === 4){ + if (this.type === 4) { this.sortchildren(); const caps = document.createElement("div"); @@ -471,56 +515,56 @@ class Channel extends SnowFlake{ decdiv.appendChild(myhtml); caps.appendChild(decdiv); const childrendiv = document.createElement("div"); - if(admin){ + if (admin) { const addchannel = document.createElement("span"); - addchannel.classList.add("addchannel","svgicon","svg-plus"); + addchannel.classList.add("addchannel", "svgicon", "svg-plus"); caps.appendChild(addchannel); - addchannel.onclick = _=>{ + addchannel.onclick = (_) => { this.guild.createchannels(this.createChannel.bind(this)); }; this.coatDropDiv(decdiv, childrendiv); } div.appendChild(caps); - caps.classList.add("flexltr","capsflex"); - decdiv.classList.add("flexltr","channeleffects"); + caps.classList.add("flexltr", "capsflex"); + decdiv.classList.add("flexltr", "channeleffects"); decdiv.classList.add("channel"); - Channel.contextmenu.bindContextmenu(decdiv, this,undefined); + Channel.contextmenu.bindContextmenu(decdiv, this, undefined); // @ts-ignore I dont wanna deal with this decdiv.all = this; - for(const channel of this.children){ + for (const channel of this.children) { childrendiv.appendChild(channel.createguildHTML(admin)); } childrendiv.classList.add("channels"); - setTimeout((_: any)=>{ - if(!this.perminfo.collapsed){ + setTimeout((_: any) => { + if (!this.perminfo.collapsed) { childrendiv.style.height = childrendiv.scrollHeight + "px"; } }, 100); div.appendChild(childrendiv); - if(this.perminfo.collapsed){ + if (this.perminfo.collapsed) { decoration.classList.add("hiddencat"); childrendiv.style.height = "0px"; } - decdiv.onclick = ()=>{ - if(childrendiv.style.height !== "0px"){ + decdiv.onclick = () => { + if (childrendiv.style.height !== "0px") { decoration.classList.add("hiddencat"); this.perminfo.collapsed = true; this.localuser.userinfo.updateLocal(); childrendiv.style.height = "0px"; - }else{ + } else { decoration.classList.remove("hiddencat"); this.perminfo.collapsed = false; this.localuser.userinfo.updateLocal(); childrendiv.style.height = childrendiv.scrollHeight + "px"; } }; - }else{ + } else { div.classList.add("channel"); this.unreads(); - Channel.contextmenu.bindContextmenu(div, this,undefined); - if(admin){ + Channel.contextmenu.bindContextmenu(div, this, undefined); + if (admin) { this.coatDropDiv(div); } // @ts-ignore I dont wanna deal with this @@ -531,171 +575,174 @@ class Channel extends SnowFlake{ const myhtml = document.createElement("span"); myhtml.classList.add("ellipsis"); myhtml.textContent = this.name; - if(this.type === 0){ + if (this.type === 0) { const decoration = document.createElement("span"); button.appendChild(decoration); - decoration.classList.add("space", "svgicon", this.nsfw?"svg-channelnsfw":"svg-channel"); - }else if(this.type === 2){ + decoration.classList.add("space", "svgicon", this.nsfw ? "svg-channelnsfw" : "svg-channel"); + } else if (this.type === 2) { // const decoration = document.createElement("span"); button.appendChild(decoration); - decoration.classList.add("space", "svgicon", this.nsfw?"svg-voicensfw":"svg-voice"); - }else if(this.type === 5){ + decoration.classList.add("space", "svgicon", this.nsfw ? "svg-voicensfw" : "svg-voice"); + } else if (this.type === 5) { // const decoration = document.createElement("span"); button.appendChild(decoration); - decoration.classList.add("space", "svgicon", this.nsfw?"svg-announcensfw":"svg-announce"); - }else{ + decoration.classList.add( + "space", + "svgicon", + this.nsfw ? "svg-announcensfw" : "svg-announce", + ); + } else { console.log(this.type); } button.appendChild(myhtml); - button.onclick = _=>{ + button.onclick = (_) => { this.getHTML(); const toggle = document.getElementById("maintoggle") as HTMLInputElement; toggle.checked = true; }; - if(this.type===2){ - const voiceUsers=document.createElement("div"); + if (this.type === 2) { + const voiceUsers = document.createElement("div"); div.append(voiceUsers); - this.voiceUsers=new WeakRef(voiceUsers); + this.voiceUsers = new WeakRef(voiceUsers); this.updateVoiceUsers(); } } return div; } - async moveForDrag(x:number){ - const mainarea=document.getElementById("mainarea"); - if(!mainarea) return; - if(x===-1){ + async moveForDrag(x: number) { + const mainarea = document.getElementById("mainarea"); + if (!mainarea) return; + if (x === -1) { mainarea.style.removeProperty("left"); mainarea.style.removeProperty("transition"); return; } - mainarea.style.left=x+"px"; - mainarea.style.transition="left 0s" + mainarea.style.left = x + "px"; + mainarea.style.transition = "left 0s"; } - async setUpVoice(){ - if(!this.voice) return; - this.voice.onMemberChange=async (memb,joined)=>{ - console.log(memb,joined); - if(typeof memb!=="string"){ - await Member.new(memb,this.guild); + async setUpVoice() { + if (!this.voice) return; + this.voice.onMemberChange = async (memb, joined) => { + console.log(memb, joined); + if (typeof memb !== "string") { + await Member.new(memb, this.guild); } this.updateVoiceUsers(); - if(this.voice===this.localuser.currentVoice){ + if (this.voice === this.localuser.currentVoice) { AVoice.noises("join"); } - } + }; } - async updateVoiceUsers(){ - const voiceUsers=this.voiceUsers.deref(); - if(!voiceUsers||!this.voice) return; - console.warn(this.voice.userids) + async updateVoiceUsers() { + const voiceUsers = this.voiceUsers.deref(); + if (!voiceUsers || !this.voice) return; + console.warn(this.voice.userids); - const html=(await Promise.all(this.voice.userids.entries().toArray().map(async _=>{ - const user=await User.resolve(_[0],this.localuser); - console.log(user); - const member=await Member.resolveMember(user,this.guild); - const array=[member,_[1]] as [Member, typeof _[1]]; - return array; - }))).flatMap(([member,_obj])=>{ - if(!member){ + const html = ( + await Promise.all( + this.voice.userids + .entries() + .toArray() + .map(async (_) => { + const user = await User.resolve(_[0], this.localuser); + console.log(user); + const member = await Member.resolveMember(user, this.guild); + const array = [member, _[1]] as [Member, (typeof _)[1]]; + return array; + }), + ) + ).flatMap(([member, _obj]) => { + if (!member) { console.warn("This is weird, member doesn't exist :P"); return []; } - const div=document.createElement("div"); + const div = document.createElement("div"); div.classList.add("voiceuser"); - const span=document.createElement("span"); - span.textContent=member.name; + const span = document.createElement("span"); + span.textContent = member.name; div.append(span); return div; }); - voiceUsers.innerHTML=""; + voiceUsers.innerHTML = ""; voiceUsers.append(...html); } - get myhtml(){ - if(this.html){ + get myhtml() { + if (this.html) { return this.html.deref(); - }else{ + } else { return; } } - readbottom(){ - this.mentions=0; - if(!this.hasunreads){ + readbottom() { + this.mentions = 0; + if (!this.hasunreads) { this.guild.unreads(); return; } - fetch( - this.info.api +"/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack", - { - method: "POST", - headers: this.headers, - body: JSON.stringify({}), - } - ); + fetch(this.info.api + "/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack", { + method: "POST", + headers: this.headers, + body: JSON.stringify({}), + }); this.lastreadmessageid = this.lastmessageid; this.guild.unreads(); this.unreads(); } - coatDropDiv(div: HTMLDivElement, container: HTMLElement | boolean = false){ - div.addEventListener("dragenter", event=>{ + coatDropDiv(div: HTMLDivElement, container: HTMLElement | boolean = false) { + div.addEventListener("dragenter", (event) => { console.log("enter"); event.preventDefault(); }); - div.addEventListener("dragover", event=>{ + div.addEventListener("dragover", (event) => { event.preventDefault(); }); - div.addEventListener("drop", event=>{ + div.addEventListener("drop", (event) => { const that = Channel.dragged[0]; - if(!that)return; + if (!that) return; event.preventDefault(); - if(container){ + if (container) { that.move_id = this.id; - if(that.parent){ + if (that.parent) { that.parent.children.splice(that.parent.children.indexOf(that), 1); } that.parent = this; - (container as HTMLElement).prepend( - Channel.dragged[1] as HTMLDivElement - ); + (container as HTMLElement).prepend(Channel.dragged[1] as HTMLDivElement); this.children.unshift(that); - }else{ + } else { console.log(this, Channel.dragged); that.move_id = this.parent_id; - if(that.parent){ + if (that.parent) { that.parent.children.splice(that.parent.children.indexOf(that), 1); - }else{ - this.guild.headchannels.splice( - this.guild.headchannels.indexOf(that), - 1 - ); + } else { + this.guild.headchannels.splice(this.guild.headchannels.indexOf(that), 1); } that.parent = this.parent; - if(that.parent){ + if (that.parent) { const build: Channel[] = []; - for(let i = 0; i < that.parent.children.length; i++){ + for (let i = 0; i < that.parent.children.length; i++) { build.push(that.parent.children[i]); - if(that.parent.children[i] === this){ + if (that.parent.children[i] === this) { build.push(that); } } that.parent.children = build; - }else{ + } else { const build: Channel[] = []; - for(let i = 0; i < this.guild.headchannels.length; i++){ + for (let i = 0; i < this.guild.headchannels.length; i++) { build.push(this.guild.headchannels[i]); - if(this.guild.headchannels[i] === this){ + if (this.guild.headchannels[i] === this) { build.push(that); } } this.guild.headchannels = build; } - if(Channel.dragged[1]){ + if (Channel.dragged[1]) { div.after(Channel.dragged[1]); } } @@ -704,7 +751,7 @@ class Channel extends SnowFlake{ return div; } - createChannel(name: string, type: number){ + createChannel(name: string, type: number) { fetch(this.info.api + "/guilds/" + this.guild.id + "/channels", { method: "POST", headers: this.headers, @@ -716,34 +763,34 @@ class Channel extends SnowFlake{ }), }); } - deleteChannel(){ + deleteChannel() { fetch(this.info.api + "/channels/" + this.id, { method: "DELETE", headers: this.headers, }); } - setReplying(message: Message){ - if(this.replyingto?.div){ + setReplying(message: Message) { + if (this.replyingto?.div) { this.replyingto.div.classList.remove("replying"); } this.replyingto = message; const typebox = document.getElementById("typebox") as HTMLElement; typebox.focus(); - if(!this.replyingto?.div)return; + if (!this.replyingto?.div) return; console.log(message); this.replyingto.div.classList.add("replying"); this.makereplybox(); } - makereplybox(){ + makereplybox() { const replybox = document.getElementById("replybox") as HTMLElement; const typebox = document.getElementById("typebox") as HTMLElement; - if(this.replyingto){ + if (this.replyingto) { replybox.innerHTML = ""; const span = document.createElement("span"); span.textContent = I18n.getTranslation("replyingTo", this.replyingto.author.username); const X = document.createElement("button"); - X.onclick = _=>{ - if(this.replyingto?.div){ + X.onclick = (_) => { + if (this.replyingto?.div) { this.replyingto.div.classList.remove("replying"); } replybox.classList.add("hideReplyBox"); @@ -752,125 +799,121 @@ class Channel extends SnowFlake{ typebox.classList.remove("typeboxreplying"); }; replybox.classList.remove("hideReplyBox"); - X.classList.add("cancelReply","svgicon","svg-x"); + X.classList.add("cancelReply", "svgicon", "svg-x"); replybox.append(span); replybox.append(X); typebox.classList.add("typeboxreplying"); - }else{ + } else { replybox.classList.add("hideReplyBox"); typebox.classList.remove("typeboxreplying"); } } - async getmessage(id: string): Promise{ + async getmessage(id: string): Promise { const message = this.messages.get(id); - if(message){ + if (message) { return message; - }else{ + } else { const gety = await fetch( - this.info.api + "/channels/" +this.id +"/messages?limit=1&around=" +id, - { headers: this.headers } + this.info.api + "/channels/" + this.id + "/messages?limit=1&around=" + id, + {headers: this.headers}, ); const json = await gety.json(); - if(json.length===0){ + if (json.length === 0) { return undefined; } return new Message(json[0], this); } } - async focus(id:string){ - console.time() + async focus(id: string) { + console.time(); console.log(await this.getmessage(id)); await this.getHTML(); - console.timeEnd() + console.timeEnd(); console.warn(id); this.infinite.focus(id); } - editLast(){ - let message:Message|undefined=this.lastmessage; - while(message&&message.author!==this.localuser.user){ - message=this.messages.get(this.idToPrev.get(message.id) as string); + editLast() { + let message: Message | undefined = this.lastmessage; + while (message && message.author !== this.localuser.user) { + message = this.messages.get(this.idToPrev.get(message.id) as string); } - if(message){ + if (message) { message.setEdit(); } } static genid: number = 0; - nsfwPannel(){ - (document.getElementById("typebox") as HTMLDivElement).contentEditable =""+false; - (document.getElementById("upload") as HTMLElement).style.visibility="hidden"; - (document.getElementById("typediv") as HTMLElement).style.visibility="hidden"; + nsfwPannel() { + (document.getElementById("typebox") as HTMLDivElement).contentEditable = "" + false; + (document.getElementById("upload") as HTMLElement).style.visibility = "hidden"; + (document.getElementById("typediv") as HTMLElement).style.visibility = "hidden"; const messages = document.getElementById("channelw") as HTMLDivElement; - const messageContainers = Array.from( - messages.getElementsByClassName("messagecontainer") - ); - for(const thing of messageContainers){ + const messageContainers = Array.from(messages.getElementsByClassName("messagecontainer")); + for (const thing of messageContainers) { thing.remove(); } const elements = Array.from(messages.getElementsByClassName("scroller")); - for(const elm of elements){ + for (const elm of elements) { elm.remove(); console.warn("rouge element detected and removed"); } - const div=document.getElementById("sideDiv") as HTMLDivElement; - div.innerHTML=""; - const float=new Float(""); - const options=float.options; + const div = document.getElementById("sideDiv") as HTMLDivElement; + div.innerHTML = ""; + const float = new Float(""); + const options = float.options; //@ts-ignore weird hack, ik, but the user here does have that information //TODO make an extention of the user class with these aditional properties //TODO make a popup for `nsfw_allowed==null` to input age - if(this.localuser.user.nsfw_allowed){ + if (this.localuser.user.nsfw_allowed) { options.addTitle("This is a NSFW channel, do you wish to proceed?"); - const buttons=options.addOptions("",{ltr:true}); - buttons.addButtonInput("","Yes",()=>{ - this.perminfo.nsfwOk=true; + const buttons = options.addOptions("", {ltr: true}); + buttons.addButtonInput("", "Yes", () => { + this.perminfo.nsfwOk = true; this.localuser.userinfo.updateLocal(); this.getHTML(); }); - buttons.addButtonInput("","No",()=>{ + buttons.addButtonInput("", "No", () => { window.history.back(); - }) - }else{ + }); + } else { options.addTitle("You are not allowed in this channel."); } - const html=float.generateHTML(); - html.classList.add("messagecontainer") + const html = float.generateHTML(); + html.classList.add("messagecontainer"); messages.append(html); - } - async getHTML(addstate=true){ - - if(addstate){ - history.pushState([this.guild_id,this.id], "", "/channels/" + this.guild_id + "/" + this.id); + async getHTML(addstate = true) { + if (addstate) { + history.pushState([this.guild_id, this.id], "", "/channels/" + this.guild_id + "/" + this.id); } this.localuser.pageTitle("#" + this.name); const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement; - if(this.topic){ - channelTopic.innerHTML =""; - channelTopic.append(new MarkDown( - this.topic, - this - ).makeHTML()); + if (this.topic) { + channelTopic.innerHTML = ""; + channelTopic.append(new MarkDown(this.topic, this).makeHTML()); channelTopic.removeAttribute("hidden"); - }else channelTopic.setAttribute("hidden", ""); - if(this.guild !== this.localuser.lookingguild){ + } else channelTopic.setAttribute("hidden", ""); + if (this.guild !== this.localuser.lookingguild) { this.guild.loadGuild(); } - if(this.localuser.channelfocus && this.localuser.channelfocus.myhtml){ + if (this.localuser.channelfocus && this.localuser.channelfocus.myhtml) { this.localuser.channelfocus.myhtml.classList.remove("viewChannel"); } - if(this.myhtml){ + if (this.myhtml) { this.myhtml.classList.add("viewChannel"); } const id = ++Channel.genid; - if(this.localuser.channelfocus){ + if (this.localuser.channelfocus) { this.localuser.channelfocus.infinite.delete(); } this.guild.prevchannel = this; this.guild.perminfo.prevchannel = this.id; this.localuser.userinfo.updateLocal(); this.localuser.channelfocus = this; - //@ts-ignore another hack - if(this.nsfw&&(!this.perminfo.nsfwOk||!this.localuser.user.nsfw_allowed)){ + + if ( + this.nsfw && //@ts-ignore another hack + (!this.perminfo.nsfwOk || !this.localuser.user.nsfw_allowed) + ) { this.nsfwPannel(); return; } @@ -882,29 +925,30 @@ class Channel extends SnowFlake{ loading.classList.add("loading"); this.rendertyping(); this.localuser.getSidePannel(); - if(this.voice&&localStorage.getItem("Voice enabled")){ + if (this.voice && localStorage.getItem("Voice enabled")) { this.localuser.joinVoice(this); } - (document.getElementById("typebox") as HTMLDivElement).contentEditable =""+this.canMessage; - (document.getElementById("upload") as HTMLElement).style.visibility=this.canMessage?"visible":"hidden"; - (document.getElementById("typediv") as HTMLElement).style.visibility="visible"; + (document.getElementById("typebox") as HTMLDivElement).contentEditable = "" + this.canMessage; + (document.getElementById("upload") as HTMLElement).style.visibility = this.canMessage + ? "visible" + : "hidden"; + (document.getElementById("typediv") as HTMLElement).style.visibility = "visible"; (document.getElementById("typebox") as HTMLDivElement).focus(); await this.putmessages(); await prom; - if(id !== Channel.genid){ + if (id !== Channel.genid) { return; } this.makereplybox(); await this.buildmessages(); //loading.classList.remove("loading"); - } typingmap: Map = new Map(); - async typingStart(typing: startTypingjson): Promise{ + async typingStart(typing: startTypingjson): Promise { const memb = await Member.new(typing.d.member!, this.guild); - if(!memb)return; - if(memb.id === this.localuser.user.id){ + if (!memb) return; + if (memb.id === this.localuser.user.id) { console.log("you is typing"); return; } @@ -913,58 +957,56 @@ class Channel extends SnowFlake{ setTimeout(this.rendertyping.bind(this), 10000); this.rendertyping(); } - similar(str:string){ - if(this.type===4) return -1; - const strl=Math.max(str.length,1) - if(this.name.includes(str)){ - return strl/this.name.length; - }else if(this.name.toLowerCase().includes(str.toLowerCase())){ - return strl/this.name.length/1.2; + similar(str: string) { + if (this.type === 4) return -1; + const strl = Math.max(str.length, 1); + if (this.name.includes(str)) { + return strl / this.name.length; + } else if (this.name.toLowerCase().includes(str.toLowerCase())) { + return strl / this.name.length / 1.2; } return 0; } - rendertyping(): void{ + rendertyping(): void { const typingtext = document.getElementById("typing") as HTMLDivElement; let build = ""; let showing = false; let i = 0; const curtime = Date.now() - 5000; - for(const thing of this.typingmap.keys()){ - if((this.typingmap.get(thing) as number) > curtime){ - if(i !== 0){ + for (const thing of this.typingmap.keys()) { + if ((this.typingmap.get(thing) as number) > curtime) { + if (i !== 0) { build += ", "; } i++; - if(thing.nick){ + if (thing.nick) { build += thing.nick; - }else{ + } else { build += thing.user.username; } showing = true; - }else{ + } else { this.typingmap.delete(thing); } } - build=I18n.getTranslation("typing",i+"",build); - if(this.localuser.channelfocus === this){ - if(showing){ + build = I18n.getTranslation("typing", i + "", build); + if (this.localuser.channelfocus === this) { + if (showing) { typingtext.classList.remove("hidden"); - const typingtext2 = document.getElementById( - "typingtext" - ) as HTMLDivElement; + const typingtext2 = document.getElementById("typingtext") as HTMLDivElement; typingtext2.textContent = build; - }else{ + } else { typingtext.classList.add("hidden"); } } } - static regenLoadingMessages(){ + static regenLoadingMessages() { const loading = document.getElementById("loadingdiv") as HTMLDivElement; loading.innerHTML = ""; - for(let i = 0; i < 15; i++){ + for (let i = 0; i < 15; i++) { const div = document.createElement("div"); div.classList.add("loadingmessage"); - if(Math.random() < 0.5){ + if (Math.random() < 0.5) { const pfp = document.createElement("div"); pfp.classList.add("loadingpfp"); const username = document.createElement("div"); @@ -981,36 +1023,50 @@ class Channel extends SnowFlake{ } } lastmessage: Message | undefined; - setnotifcation(){ - const defualt=I18n.getTranslation("guild."+["all", "onlyMentions", "none","default"][this.guild.message_notifications]) - const options=["all", "onlyMentions", "none","default"].map(e=>I18n.getTranslation("guild."+e,defualt)); - const notiselect=new Dialog(""); - const form=notiselect.options.addForm("",(_,sent:any)=>{ - notiselect.hide(); - console.log(sent); - this.message_notifications = sent.channel_overrides[this.id].message_notifications; - },{ - fetchURL:`${this.info.api}/users/@me/guilds/${this.guild.id}/settings/`, - method:"PATCH", - headers:this.headers - }); - form.addSelect(I18n.getTranslation("guild.selectnoti"),"message_notifications",options,{ - radio:true, - defaultIndex:this.message_notifications - },[0,1,2,3]); + setnotifcation() { + const defualt = I18n.getTranslation( + "guild." + ["all", "onlyMentions", "none", "default"][this.guild.message_notifications], + ); + const options = ["all", "onlyMentions", "none", "default"].map((e) => + I18n.getTranslation("guild." + e, defualt), + ); + const notiselect = new Dialog(""); + const form = notiselect.options.addForm( + "", + (_, sent: any) => { + notiselect.hide(); + console.log(sent); + this.message_notifications = sent.channel_overrides[this.id].message_notifications; + }, + { + fetchURL: `${this.info.api}/users/@me/guilds/${this.guild.id}/settings/`, + method: "PATCH", + headers: this.headers, + }, + ); + form.addSelect( + I18n.getTranslation("guild.selectnoti"), + "message_notifications", + options, + { + radio: true, + defaultIndex: this.message_notifications, + }, + [0, 1, 2, 3], + ); - form.addPreprocessor((e:any)=>{ - const message_notifications=e.message_notifications; + form.addPreprocessor((e: any) => { + const message_notifications = e.message_notifications; delete e.message_notifications; - e.channel_overrides={ - [this.id]:{ + e.channel_overrides = { + [this.id]: { message_notifications, - muted:this.muted, - mute_config:this.mute_config, - channel_id:this.id - } - } - }) + muted: this.muted, + mute_config: this.mute_config, + channel_id: this.id, + }, + }; + }); /* let noti = this.message_notifications; const defualt=I18n.getTranslation("guild."+["all", "onlyMentions", "none","default"][this.guild.message_notifications]) @@ -1056,74 +1112,69 @@ class Channel extends SnowFlake{ */ notiselect.show(); } - async putmessages(){ + async putmessages() { //TODO swap out with the WS op code - if(this.allthewayup){ + if (this.allthewayup) { return; } - if(this.lastreadmessageid && this.messages.has(this.lastreadmessageid)){ + if (this.lastreadmessageid && this.messages.has(this.lastreadmessageid)) { return; } - const j = await fetch( - this.info.api + "/channels/" + this.id + "/messages?limit=100", - { - headers: this.headers, - } - ); + const j = await fetch(this.info.api + "/channels/" + this.id + "/messages?limit=100", { + headers: this.headers, + }); const response = await j.json(); - if(response.length !== 100){ + if (response.length !== 100) { this.allthewayup = true; } let prev: Message | undefined; - for(const thing of response){ + for (const thing of response) { const message = new Message(thing, this); - if(prev){ + if (prev) { this.idToNext.set(message.id, prev.id); this.idToPrev.set(prev.id, message.id); - }else{ + } else { this.lastmessage = message; this.lastmessageid = message.id; } prev = message; } } - delChannel(json: channeljson){ + delChannel(json: channeljson) { const build: Channel[] = []; - for(const thing of this.children){ - if(thing.id !== json.id){ + for (const thing of this.children) { + if (thing.id !== json.id) { build.push(thing); } } this.children = build; } - async grabAfter(id: string){ - if(id === this.lastmessage?.id){ + async grabAfter(id: string) { + if (id === this.lastmessage?.id) { return; } - await fetch( - this.info.api + "/channels/" +this.id +"/messages?limit=100&after=" +id,{ - headers: this.headers, - } - ) - .then(j=>{ + await fetch(this.info.api + "/channels/" + this.id + "/messages?limit=100&after=" + id, { + headers: this.headers, + }) + .then((j) => { return j.json(); }) - .then(response=>{ + .then((response) => { let previd: string = id; - for(const i in response){ + for (const i in response) { let messager: Message; let willbreak = false; - if(this.messages.has(response[i].id)){ + if (this.messages.has(response[i].id)) { messager = this.messages.get(response[i].id) as Message; willbreak = true; - }else{ + } else { messager = new Message(response[i], this); } this.idToPrev.set(messager.id, previd); this.idToNext.set(previd, messager.id); previd = messager.id; - if(willbreak){ + if (willbreak) { break; } } @@ -1131,36 +1182,33 @@ class Channel extends SnowFlake{ }); } topid!: string; - async grabBefore(id: string){ - if(this.topid && id === this.topid){ + async grabBefore(id: string) { + if (this.topid && id === this.topid) { return; } - await fetch( - this.info.api + "/channels/" + this.id +"/messages?before=" + id + "&limit=100", - { - headers: this.headers, - } - ) - .then(j=>{ + await fetch(this.info.api + "/channels/" + this.id + "/messages?before=" + id + "&limit=100", { + headers: this.headers, + }) + .then((j) => { return j.json(); }) - .then((response: messagejson[])=>{ - if(response.length < 100){ + .then((response: messagejson[]) => { + if (response.length < 100) { this.allthewayup = true; - if(response.length === 0){ + if (response.length === 0) { this.topid = id; } } let previd = id; - for(const i in response){ + for (const i in response) { let messager: Message; let willbreak = false; - if(this.messages.has(response[i].id)){ + if (this.messages.has(response[i].id)) { console.log("flaky"); messager = this.messages.get(response[i].id) as Message; willbreak = true; - }else{ + } else { messager = new Message(response[i], this); } @@ -1168,171 +1216,161 @@ class Channel extends SnowFlake{ this.idToPrev.set(previd, messager.id); previd = messager.id; - if(Number(i) === response.length - 1 && response.length < 100){ + if (Number(i) === response.length - 1 && response.length < 100) { this.topid = previd; } - if(willbreak){ + if (willbreak) { break; } } }); } /** - * Please dont use this, its not implemented. - * @deprecated - * @todo - **/ - async grabArround(/* id: string */){ + * Please dont use this, its not implemented. + * @deprecated + * @todo + **/ + async grabArround(/* id: string */) { //currently unused and no plans to use it yet throw new Error("please don't call this, no one has implemented it :P"); } - async buildmessages(){ + async buildmessages() { this.infinitefocus = false; await this.tryfocusinfinate(); } infinitefocus = false; - async tryfocusinfinate(){ - if(this.infinitefocus)return; + async tryfocusinfinate() { + if (this.infinitefocus) return; this.infinitefocus = true; const messages = document.getElementById("channelw") as HTMLDivElement; - const messageContainers = Array.from( - messages.getElementsByClassName("messagecontainer") - ); - for(const thing of messageContainers){ + const messageContainers = Array.from(messages.getElementsByClassName("messagecontainer")); + for (const thing of messageContainers) { thing.remove(); } const loading = document.getElementById("loadingdiv") as HTMLDivElement; const removetitle = document.getElementById("removetitle"); //messages.innerHTML=""; let id: string | undefined; - if(this.lastreadmessageid && this.messages.has(this.lastreadmessageid)){ + if (this.lastreadmessageid && this.messages.has(this.lastreadmessageid)) { id = this.lastreadmessageid; - }else if(this.lastreadmessageid && (id = this.findClosest(this.lastreadmessageid))){ - - }else if(this.lastmessageid && this.messages.has(this.lastmessageid)){ + } else if (this.lastreadmessageid && (id = this.findClosest(this.lastreadmessageid))) { + } else if (this.lastmessageid && this.messages.has(this.lastmessageid)) { id = this.goBackIds(this.lastmessageid, 50); } - if(!id){ - if(!removetitle){ + if (!id) { + if (!removetitle) { const title = document.createElement("h2"); title.id = "removetitle"; title.textContent = I18n.getTranslation("noMessages"); - title.classList.add("titlespace","messagecontainer"); + title.classList.add("titlespace", "messagecontainer"); messages.append(title); } this.infinitefocus = false; loading.classList.remove("loading"); return; - }else if(removetitle){ + } else if (removetitle) { removetitle.remove(); } - if(this.localuser.channelfocus !== this){ + if (this.localuser.channelfocus !== this) { return; } const elements = Array.from(messages.getElementsByClassName("scroller")); - for(const elm of elements){ + for (const elm of elements) { elm.remove(); console.warn("rouge element detected and removed"); } messages.append(await this.infinite.getDiv(id)); this.infinite.updatestuff(); - this.infinite.watchForChange().then(async _=>{ + this.infinite.watchForChange().then(async (_) => { //await new Promise(resolve => setTimeout(resolve, 0)); this.infinite.focus(id, false); //if someone could figure out how to make this work correctly without this, that's be great :P loading.classList.remove("loading"); }); //this.infinite.focus(id.id,false); } - private goBackIds( - id: string, - back: number, - returnifnotexistant = true - ): string | undefined{ - while(back !== 0){ + private goBackIds(id: string, back: number, returnifnotexistant = true): string | undefined { + while (back !== 0) { const nextid = this.idToPrev.get(id); - if(nextid){ + if (nextid) { id = nextid; back--; - }else{ - if(returnifnotexistant){ + } else { + if (returnifnotexistant) { break; - }else{ + } else { return undefined; } } } return id; } - private findClosest(id: string | undefined){ - if(!this.lastmessageid || !id)return; + private findClosest(id: string | undefined) { + if (!this.lastmessageid || !id) return; let flake: string | undefined = this.lastmessageid; const time = SnowFlake.stringToUnixTime(id); let flaketime = SnowFlake.stringToUnixTime(flake); - while(flake && time < flaketime){ + while (flake && time < flaketime) { flake = this.idToPrev.get(flake); - if(!flake){ + if (!flake) { return; } flaketime = SnowFlake.stringToUnixTime(flake); } return flake; } - updateChannel(json: channeljson){ + updateChannel(json: channeljson) { this.type = json.type; this.name = json.name; const parent = this.localuser.channelids.get(json.parent_id); - if(parent){ + if (parent) { this.parent = parent; this.parent_id = parent.id; - }else{ + } else { this.parent = undefined; this.parent_id = undefined; } this.children = []; this.guild_id = json.guild_id; - const oldover=this.permission_overwrites; + const oldover = this.permission_overwrites; this.permission_overwrites = new Map(); - this.permission_overwritesar=[]; - for(const thing of json.permission_overwrites){ - if(thing.id === "1182819038095799904" || thing.id === "1182820803700625444"){ + this.permission_overwritesar = []; + for (const thing of json.permission_overwrites) { + if (thing.id === "1182819038095799904" || thing.id === "1182820803700625444") { continue; } - this.permission_overwrites.set( - thing.id, - new Permissions(thing.allow, thing.deny) - ); + this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny)); const permisions = this.permission_overwrites.get(thing.id); - if(permisions){ + if (permisions) { const role = this.guild.roleids.get(thing.id); - if(role){ + if (role) { this.permission_overwritesar.push([role, permisions]); } } } - const nchange=[...new Set().union(oldover).difference(this.permission_overwrites)]; - const pchange=[...new Set().union(this.permission_overwrites).difference(oldover)]; - for(const thing of nchange){ - const role=this.guild.roleids.get(thing); - if(role){ - this.croleUpdate(role,new Permissions("0"),false) + const nchange = [...new Set().union(oldover).difference(this.permission_overwrites)]; + const pchange = [...new Set().union(this.permission_overwrites).difference(oldover)]; + for (const thing of nchange) { + const role = this.guild.roleids.get(thing); + if (role) { + this.croleUpdate(role, new Permissions("0"), false); } } - for(const thing of pchange){ - const role=this.guild.roleids.get(thing); - const perms=this.permission_overwrites.get(thing); - if(role&&perms){ - this.croleUpdate(role,perms,true); + for (const thing of pchange) { + const role = this.guild.roleids.get(thing); + const perms = this.permission_overwrites.get(thing); + if (role && perms) { + this.croleUpdate(role, perms, true); } } - console.log(pchange,nchange); + console.log(pchange, nchange); this.topic = json.topic; this.nsfw = json.nsfw; } - croleUpdate:(role:Role,perm:Permissions,added:boolean)=>unknown=()=>{}; - typingstart(){ - if(this.typing > Date.now()){ + croleUpdate: (role: Role, perm: Permissions, added: boolean) => unknown = () => {}; + typingstart() { + if (this.typing > Date.now()) { return; } this.typing = Date.now() + 6000; @@ -1341,23 +1379,23 @@ class Channel extends SnowFlake{ headers: this.headers, }); } - get notification(){ + get notification() { let notinumber: number | null = this.message_notifications; - if(Number(notinumber) === 3){ + if (Number(notinumber) === 3) { notinumber = null; } notinumber ??= this.guild.message_notifications; - console.warn("info:",notinumber); - switch(Number(notinumber)){ + console.warn("info:", notinumber); + switch (Number(notinumber)) { case 0: - return"all"; + return "all"; case 1: - return"mentions"; + return "mentions"; case 2: - return"none"; + return "none"; case 3: default: - return"default"; + return "default"; } } async sendMessage( @@ -1365,23 +1403,23 @@ class Channel extends SnowFlake{ { attachments = [], replyingto = null, - }: { attachments: Blob[]; embeds: embedjson; replyingto: Message | null } - ){ + }: {attachments: Blob[]; embeds: embedjson; replyingto: Message | null}, + ) { let replyjson: any; - if(replyingto){ + if (replyingto) { replyjson = { guild_id: replyingto.guild.id, channel_id: replyingto.channel.id, message_id: replyingto.id, }; } - if(attachments.length === 0){ + if (attachments.length === 0) { const body = { content, nonce: Math.floor(Math.random() * 1000000000), message_reference: undefined, }; - if(replyjson){ + if (replyjson) { body.message_reference = replyjson; } return await fetch(this.info.api + "/channels/" + this.id + "/messages", { @@ -1389,108 +1427,102 @@ class Channel extends SnowFlake{ headers: this.headers, body: JSON.stringify(body), }); - }else{ + } else { const formData = new FormData(); const body = { content, nonce: Math.floor(Math.random() * 1000000000), message_reference: undefined, }; - if(replyjson){ + if (replyjson) { body.message_reference = replyjson; } formData.append("payload_json", JSON.stringify(body)); - for(const i in attachments){ + for (const i in attachments) { formData.append("files[" + i + "]", attachments[i]); } return await fetch(this.info.api + "/channels/" + this.id + "/messages", { method: "POST", body: formData, - headers: { Authorization: this.headers.Authorization }, + headers: {Authorization: this.headers.Authorization}, }); } } - unreads(){ - if(!this.hasunreads){ - if(this.myhtml){ - this.myhtml.classList.remove("cunread","mentioned"); + unreads() { + if (!this.hasunreads) { + if (this.myhtml) { + this.myhtml.classList.remove("cunread", "mentioned"); } - }else{ - if(this.myhtml){ + } else { + if (this.myhtml) { this.myhtml.classList.add("cunread"); } - if(this.mentions!==0){ - this.myhtml?.classList.add("mentioned") + if (this.mentions !== 0) { + this.myhtml?.classList.add("mentioned"); } } } - messageCreate(messagep: messageCreateJson): void{ - if(!this.hasPermission("VIEW_CHANNEL")){ + messageCreate(messagep: messageCreateJson): void { + if (!this.hasPermission("VIEW_CHANNEL")) { return; } const messagez = new Message(messagep.d, this); this.lastmessage = messagez; - if(this.lastmessageid){ + if (this.lastmessageid) { this.idToNext.set(this.lastmessageid, messagez.id); this.idToPrev.set(messagez.id, this.lastmessageid); } - if(messagez.mentionsuser(this.localuser.user)&&messagez.author!==this.localuser.user){ + if (messagez.mentionsuser(this.localuser.user) && messagez.author !== this.localuser.user) { this.mentions++; } this.lastmessageid = messagez.id; - if(messagez.author === this.localuser.user){ + if (messagez.author === this.localuser.user) { this.lastreadmessageid = messagez.id; } this.unreads(); this.guild.unreads(); - if(this === this.localuser.channelfocus){ - if(!this.infinitefocus){ + if (this === this.localuser.channelfocus) { + if (!this.infinitefocus) { this.tryfocusinfinate(); } this.infinite.addedBottom(); } - if(messagez.author === this.localuser.user){ + if (messagez.author === this.localuser.user) { return; } - if( - this.localuser.lookingguild?.prevchannel === this && document.hasFocus() - ){ + if (this.localuser.lookingguild?.prevchannel === this && document.hasFocus()) { return; } - if(this.notification === "all"){ + if (this.notification === "all") { this.notify(messagez); - }else if( - this.notification === "mentions" && messagez.mentionsuser(this.localuser.user) - ){ + } else if (this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)) { this.notify(messagez); } } - notititle(message: Message): string{ - return( - message.author.username + " > " + this.guild.properties.name + " > " + this.name - ); + notititle(message: Message): string { + return message.author.username + " > " + this.guild.properties.name + " > " + this.name; } - notify(message: Message, deep = 0){ - if(this.localuser.play){ - const voice=this.localuser.play.audios.get(this.localuser.getNotificationSound()); - if(voice){ + notify(message: Message, deep = 0) { + if (this.localuser.play) { + const voice = this.localuser.play.audios.get(this.localuser.getNotificationSound()); + if (voice) { voice.play(); } } - if(!("Notification" in window)){ - }else if(Notification.permission === "granted"){ + if (!("Notification" in window)) { + } else if (Notification.permission === "granted") { let noticontent: string | undefined | null = message.content.textContent; - if(message.embeds[0]){ + if (message.embeds[0]) { noticontent ||= message.embeds[0]?.json.title; noticontent ||= message.content.textContent; } noticontent ||= I18n.getTranslation("blankMessage"); let imgurl: null | string = null; const images = message.getimages(); - if(images.length){ + if (images.length) { const image = images[0]; - if(image.proxy_url){ + if (image.proxy_url) { imgurl ||= image.proxy_url; } imgurl ||= image.url; @@ -1500,61 +1532,53 @@ class Channel extends SnowFlake{ icon: message.author.getpfpsrc(this.guild), image: imgurl, }); - notification.addEventListener("click", _=>{ + notification.addEventListener("click", (_) => { window.focus(); this.getHTML(); }); - }else if(Notification.permission !== "denied"){ - Notification.requestPermission().then(()=>{ - if(deep === 3){ + } else if (Notification.permission !== "denied") { + Notification.requestPermission().then(() => { + if (deep === 3) { return; } this.notify(message, deep + 1); }); } } - async addRoleToPerms(role: Role){ - await fetch( - this.info.api + "/channels/" + this.id + "/permissions/" + role.id, - { - method: "PUT", - headers: this.headers, - body: JSON.stringify({ - allow: "0", - deny: "0", - id: role.id, - type: 0, - }), - } - ); + async addRoleToPerms(role: Role) { + await fetch(this.info.api + "/channels/" + this.id + "/permissions/" + role.id, { + method: "PUT", + headers: this.headers, + body: JSON.stringify({ + allow: "0", + deny: "0", + id: role.id, + type: 0, + }), + }); const perm = new Permissions("0", "0"); this.permission_overwrites.set(role.id, perm); this.permission_overwritesar.push([role, perm]); } - async updateRolePermissions(id: string, perms: Permissions){ + async updateRolePermissions(id: string, perms: Permissions) { const permission = this.permission_overwrites.get(id); - if(permission){ + if (permission) { permission.allow = perms.allow; permission.deny = perms.deny; - }else{ + } else { //this.permission_overwrites.set(id,perms); } - await fetch( - this.info.api + "/channels/" + this.id + "/permissions/" + id, - { - method: "PUT", - headers: this.headers, - body: JSON.stringify({ - allow: perms.allow.toString(), - deny: perms.deny.toString(), - id, - type: 0, - }), - } - ); + await fetch(this.info.api + "/channels/" + this.id + "/permissions/" + id, { + method: "PUT", + headers: this.headers, + body: JSON.stringify({ + allow: perms.allow.toString(), + deny: perms.deny.toString(), + id, + type: 0, + }), + }); } } Channel.setupcontextmenu(); -export{ Channel }; - - +export {Channel}; diff --git a/src/webpage/contextmenu.ts b/src/webpage/contextmenu.ts index 794fd88e..fe738080 100644 --- a/src/webpage/contextmenu.ts +++ b/src/webpage/contextmenu.ts @@ -1,82 +1,82 @@ -import{ iOS }from"./utils/utils.js"; -class Contextmenu{ +import {iOS} from "./utils/utils.js"; +class Contextmenu { static currentmenu: HTMLElement | ""; name: string; buttons: [ - string|(()=>string), + string | (() => string), (this: x, arg: y, e: MouseEvent) => void, string | null, (this: x, arg: y) => boolean, (this: x, arg: y) => boolean, - string + string, ][]; div!: HTMLDivElement; - static setup(){ + static setup() { Contextmenu.currentmenu = ""; - document.addEventListener("click", event=>{ - if(Contextmenu.currentmenu === ""){ + document.addEventListener("click", (event) => { + if (Contextmenu.currentmenu === "") { return; } - if(!Contextmenu.currentmenu.contains(event.target as Node)){ + if (!Contextmenu.currentmenu.contains(event.target as Node)) { Contextmenu.currentmenu.remove(); Contextmenu.currentmenu = ""; } }); } - constructor(name: string){ + constructor(name: string) { this.name = name; this.buttons = []; } addbutton( - text: string|(()=>string), + text: string | (() => string), onclick: (this: x, arg: y, e: MouseEvent) => void, img: null | string = null, - shown: (this: x, arg: y) => boolean = _=>true, - enabled: (this: x, arg: y) => boolean = _=>true - ){ + shown: (this: x, arg: y) => boolean = (_) => true, + enabled: (this: x, arg: y) => boolean = (_) => true, + ) { this.buttons.push([text, onclick, img, shown, enabled, "button"]); - return{}; + return {}; } addsubmenu( - text: string|(()=>string), + text: string | (() => string), onclick: (this: x, arg: y, e: MouseEvent) => void, img = null, - shown: (this: x, arg: y) => boolean = _=>true, - enabled: (this: x, arg: y) => boolean = _=>true - ){ + shown: (this: x, arg: y) => boolean = (_) => true, + enabled: (this: x, arg: y) => boolean = (_) => true, + ) { this.buttons.push([text, onclick, img, shown, enabled, "submenu"]); - return{}; + return {}; } - private makemenu(x: number, y: number, addinfo: x, other: y){ + private makemenu(x: number, y: number, addinfo: x, other: y) { const div = document.createElement("div"); div.classList.add("contextmenu", "flexttb"); let visibleButtons = 0; - for(const thing of this.buttons){ - if(!thing[3].call(addinfo, other))continue; + for (const thing of this.buttons) { + if (!thing[3].call(addinfo, other)) continue; visibleButtons++; const intext = document.createElement("button"); intext.disabled = !thing[4].call(addinfo, other); intext.classList.add("contextbutton"); - if(thing[0] instanceof Function){ + if (thing[0] instanceof Function) { intext.textContent = thing[0](); - }else{ + } else { intext.textContent = thing[0]; } console.log(thing); - if(thing[5] === "button" || thing[5] === "submenu"){ - intext.onclick = (e)=>{ + if (thing[5] === "button" || thing[5] === "submenu") { + intext.onclick = (e) => { div.remove(); - thing[1].call(addinfo, other,e) + thing[1].call(addinfo, other, e); }; } div.appendChild(intext); } - if(visibleButtons == 0)return; + if (visibleButtons == 0) return; - if(Contextmenu.currentmenu != ""){ + if (Contextmenu.currentmenu != "") { Contextmenu.currentmenu.remove(); } div.style.top = y + "px"; @@ -87,64 +87,74 @@ class Contextmenu{ Contextmenu.currentmenu = div; return this.div; } - bindContextmenu(obj: HTMLElement, addinfo: x, other: y,touchDrag:(x:number,y:number)=>unknown=()=>{},touchEnd:(x:number,y:number)=>unknown=()=>{}){ - const func = (event: MouseEvent)=>{ + bindContextmenu( + obj: HTMLElement, + addinfo: x, + other: y, + touchDrag: (x: number, y: number) => unknown = () => {}, + touchEnd: (x: number, y: number) => unknown = () => {}, + ) { + const func = (event: MouseEvent) => { event.preventDefault(); event.stopImmediatePropagation(); this.makemenu(event.clientX, event.clientY, addinfo, other); }; obj.addEventListener("contextmenu", func); - if(iOS){ - let hold:NodeJS.Timeout|undefined; - let x!:number; - let y!:number; - obj.addEventListener("touchstart",(event: TouchEvent)=>{ - x=event.touches[0].pageX; - y=event.touches[0].pageY; - if(event.touches.length > 1){ - event.preventDefault(); - event.stopImmediatePropagation(); - this.makemenu(event.touches[0].clientX, event.touches[0].clientY, addinfo, other); - }else{ - // - event.stopImmediatePropagation(); - hold=setTimeout(()=>{ - if(lastx**2+lasty**2>10**2) return; + if (iOS) { + let hold: NodeJS.Timeout | undefined; + let x!: number; + let y!: number; + obj.addEventListener( + "touchstart", + (event: TouchEvent) => { + x = event.touches[0].pageX; + y = event.touches[0].pageY; + if (event.touches.length > 1) { + event.preventDefault(); + event.stopImmediatePropagation(); this.makemenu(event.touches[0].clientX, event.touches[0].clientY, addinfo, other); - console.log(obj); - },500) - } - },{passive: false}); - let lastx=0; - let lasty=0; - obj.addEventListener("touchend",()=>{ - if(hold){ + } else { + // + event.stopImmediatePropagation(); + hold = setTimeout(() => { + if (lastx ** 2 + lasty ** 2 > 10 ** 2) return; + this.makemenu(event.touches[0].clientX, event.touches[0].clientY, addinfo, other); + console.log(obj); + }, 500); + } + }, + {passive: false}, + ); + let lastx = 0; + let lasty = 0; + obj.addEventListener("touchend", () => { + if (hold) { clearTimeout(hold); } - touchEnd(lastx,lasty); + touchEnd(lastx, lasty); }); - obj.addEventListener("touchmove",(event)=>{ - lastx=event.touches[0].pageX-x; - lasty=event.touches[0].pageY-y; - touchDrag(lastx,lasty); + obj.addEventListener("touchmove", (event) => { + lastx = event.touches[0].pageX - x; + lasty = event.touches[0].pageY - y; + touchDrag(lastx, lasty); }); } return func; } - static keepOnScreen(obj: HTMLElement){ + static keepOnScreen(obj: HTMLElement) { const html = document.documentElement.getBoundingClientRect(); const docheight = html.height; const docwidth = html.width; const box = obj.getBoundingClientRect(); console.log(box, docheight, docwidth); - if(box.right > docwidth){ + if (box.right > docwidth) { console.log("test"); obj.style.left = docwidth - box.width + "px"; } - if(box.bottom > docheight){ + if (box.bottom > docheight) { obj.style.top = docheight - box.height + "px"; } } } Contextmenu.setup(); -export{ Contextmenu }; +export {Contextmenu}; diff --git a/src/webpage/direct.ts b/src/webpage/direct.ts index 3cf2a18e..f803bad2 100644 --- a/src/webpage/direct.ts +++ b/src/webpage/direct.ts @@ -1,22 +1,22 @@ -import{ Guild }from"./guild.js"; -import{ Channel }from"./channel.js"; -import{ Message }from"./message.js"; -import{ Localuser }from"./localuser.js"; -import{ User }from"./user.js"; -import{channeljson,dirrectjson,memberjson,messagejson}from"./jsontypes.js"; -import{ Permissions }from"./permissions.js"; -import{ SnowFlake }from"./snowflake.js"; -import{ Contextmenu }from"./contextmenu.js"; -import { I18n } from "./i18n.js"; -import { Float, FormError } from "./settings.js"; +import {Guild} from "./guild.js"; +import {Channel} from "./channel.js"; +import {Message} from "./message.js"; +import {Localuser} from "./localuser.js"; +import {User} from "./user.js"; +import {channeljson, dirrectjson, memberjson, messagejson} from "./jsontypes.js"; +import {Permissions} from "./permissions.js"; +import {SnowFlake} from "./snowflake.js"; +import {Contextmenu} from "./contextmenu.js"; +import {I18n} from "./i18n.js"; +import {Float, FormError} from "./settings.js"; -class Direct extends Guild{ - declare channelids: { [key: string]: Group }; +class Direct extends Guild { + declare channelids: {[key: string]: Group}; channels: Group[]; - getUnixTime(): number{ + getUnixTime(): number { throw new Error("Do not call this for Direct, it does not make sense"); } - constructor(json: dirrectjson[], owner: Localuser){ + constructor(json: dirrectjson[], owner: Localuser) { super(-1, owner, null); this.message_notifications = 0; this.owner = owner; @@ -29,7 +29,7 @@ class Direct extends Guild{ this.roleids = new Map(); this.prevchannel = undefined; this.properties.name = I18n.getTranslation("DMs.name"); - for(const thing of json){ + for (const thing of json) { const temp = new Group(thing, this); this.channels.push(temp); this.channelids[temp.id] = temp; @@ -37,7 +37,7 @@ class Direct extends Guild{ } this.headchannels = this.channels; } - createChannelpac(json: any){ + createChannelpac(json: any) { const thischannel = new Group(json, this); this.channelids[thischannel.id] = thischannel; this.channels.push(thischannel); @@ -46,266 +46,270 @@ class Direct extends Guild{ this.printServers(); return thischannel; } - delChannel(json: channeljson){ + delChannel(json: channeljson) { const channel = this.channelids[json.id]; super.delChannel(json); - if(channel){ + if (channel) { channel.del(); } } - getHTML(){ - const ddiv=document.createElement("div"); - const build=super.getHTML(); - const freindDiv=document.createElement("div"); - freindDiv.classList.add("liststyle","flexltr","friendsbutton"); + getHTML() { + const ddiv = document.createElement("div"); + const build = super.getHTML(); + const freindDiv = document.createElement("div"); + freindDiv.classList.add("liststyle", "flexltr", "friendsbutton"); - const icon=document.createElement("span"); - icon.classList.add("svgicon","svg-friends","space"); + const icon = document.createElement("span"); + icon.classList.add("svgicon", "svg-friends", "space"); freindDiv.append(icon); freindDiv.append(I18n.getTranslation("friends.friends")); ddiv.append(freindDiv); - freindDiv.onclick=()=>{ + freindDiv.onclick = () => { this.loadChannel(null); - } + }; ddiv.append(build); return ddiv; } - noChannel(addstate:boolean){ - if(addstate){ - history.pushState([this.id,undefined], "", "/channels/" + this.id); + noChannel(addstate: boolean) { + if (addstate) { + history.pushState([this.id, undefined], "", "/channels/" + this.id); } this.localuser.pageTitle(I18n.getTranslation("friends.friendlist")); const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement; channelTopic.removeAttribute("hidden"); - channelTopic.textContent=""; + channelTopic.textContent = ""; const loading = document.getElementById("loadingdiv") as HTMLDivElement; loading.classList.remove("loading"); this.localuser.getSidePannel(); const messages = document.getElementById("channelw") as HTMLDivElement; - for(const thing of Array.from(messages.getElementsByClassName("messagecontainer"))){ + for (const thing of Array.from(messages.getElementsByClassName("messagecontainer"))) { thing.remove(); } - const container=document.createElement("div"); - container.classList.add("messagecontainer","flexttb","friendcontainer") + const container = document.createElement("div"); + container.classList.add("messagecontainer", "flexttb", "friendcontainer"); messages.append(container); - const checkVoid=()=>{ - if(this.localuser.channelfocus!==undefined||this.localuser.lookingguild!==this){ - this.localuser.relationshipsUpdate=()=>{}; + const checkVoid = () => { + if (this.localuser.channelfocus !== undefined || this.localuser.lookingguild !== this) { + this.localuser.relationshipsUpdate = () => {}; } - } - function genuserstrip(user:User,icons:HTMLElement):HTMLElement{ - const div=document.createElement("div"); - div.classList.add("flexltr","liststyle"); + }; + function genuserstrip(user: User, icons: HTMLElement): HTMLElement { + const div = document.createElement("div"); + div.classList.add("flexltr", "liststyle"); user.bind(div); div.append(user.buildpfp()); - const userinfos=document.createElement("div"); + const userinfos = document.createElement("div"); userinfos.classList.add("flexttb"); - const username=document.createElement("span"); - username.textContent=user.name; - userinfos.append(username,user.getStatus()); + const username = document.createElement("span"); + username.textContent = user.name; + userinfos.append(username, user.getStatus()); div.append(userinfos); - User.contextmenu.bindContextmenu(div,user,undefined); - userinfos.style.flexGrow="1"; + User.contextmenu.bindContextmenu(div, user, undefined); + userinfos.style.flexGrow = "1"; div.append(icons); return div; } { //TODO update on users coming online - const online=document.createElement("button"); - online.textContent=I18n.getTranslation("friends.online"); + const online = document.createElement("button"); + online.textContent = I18n.getTranslation("friends.online"); channelTopic.append(online); - const genOnline=()=>{ - this.localuser.relationshipsUpdate=genOnline; + const genOnline = () => { + this.localuser.relationshipsUpdate = genOnline; checkVoid(); - container.innerHTML=""; + container.innerHTML = ""; container.append(I18n.getTranslation("friends.online:")); - for(const user of this.localuser.inrelation){ - if(user.relationshipType===1&&user.online){ - const buttonc=document.createElement("div"); - const button1=document.createElement("span"); - button1.classList.add("svg-frmessage","svgicon"); + for (const user of this.localuser.inrelation) { + if (user.relationshipType === 1 && user.online) { + const buttonc = document.createElement("div"); + const button1 = document.createElement("span"); + button1.classList.add("svg-frmessage", "svgicon"); buttonc.append(button1); buttonc.classList.add("friendlyButton"); - buttonc.onclick=(e)=>{ + buttonc.onclick = (e) => { e.stopImmediatePropagation(); user.opendm(); - } - container.append(genuserstrip(user,buttonc)); + }; + container.append(genuserstrip(user, buttonc)); } } - } - online.onclick=genOnline; + }; + online.onclick = genOnline; genOnline(); } { - const all=document.createElement("button"); - all.textContent=I18n.getTranslation("friends.all"); - const genAll=()=>{ - this.localuser.relationshipsUpdate=genAll; + const all = document.createElement("button"); + all.textContent = I18n.getTranslation("friends.all"); + const genAll = () => { + this.localuser.relationshipsUpdate = genAll; checkVoid(); - container.innerHTML=""; + container.innerHTML = ""; container.append(I18n.getTranslation("friends.all:")); - for(const user of this.localuser.inrelation){ - if(user.relationshipType===1){ - const buttonc=document.createElement("div"); - const button1=document.createElement("span"); - button1.classList.add("svg-frmessage","svgicon"); + for (const user of this.localuser.inrelation) { + if (user.relationshipType === 1) { + const buttonc = document.createElement("div"); + const button1 = document.createElement("span"); + button1.classList.add("svg-frmessage", "svgicon"); buttonc.append(button1); buttonc.classList.add("friendlyButton"); - buttonc.onclick=(e)=>{ + buttonc.onclick = (e) => { e.stopImmediatePropagation(); user.opendm(); - } - container.append(genuserstrip(user,buttonc)); + }; + container.append(genuserstrip(user, buttonc)); } } - } - all.onclick=genAll; + }; + all.onclick = genAll; channelTopic.append(all); } { - const pending=document.createElement("button"); - pending.textContent=I18n.getTranslation("friends.pending"); - const genPending=()=>{ - this.localuser.relationshipsUpdate=genPending; + const pending = document.createElement("button"); + pending.textContent = I18n.getTranslation("friends.pending"); + const genPending = () => { + this.localuser.relationshipsUpdate = genPending; checkVoid(); - container.innerHTML=""; + container.innerHTML = ""; container.append(I18n.getTranslation("friends.pending:")); - for(const user of this.localuser.inrelation){ - if(user.relationshipType===3||user.relationshipType===4){ - const buttons=document.createElement("div"); + for (const user of this.localuser.inrelation) { + if (user.relationshipType === 3 || user.relationshipType === 4) { + const buttons = document.createElement("div"); buttons.classList.add("flexltr"); - const buttonc=document.createElement("div"); - const button1=document.createElement("span"); - button1.classList.add("svgicon","svg-x"); - if(user.relationshipType===3){ - const buttonc=document.createElement("div"); - const button2=document.createElement("span"); - button2.classList.add("svgicon","svg-x"); + const buttonc = document.createElement("div"); + const button1 = document.createElement("span"); + button1.classList.add("svgicon", "svg-x"); + if (user.relationshipType === 3) { + const buttonc = document.createElement("div"); + const button2 = document.createElement("span"); + button2.classList.add("svgicon", "svg-x"); button2.classList.add("svg-addfriend"); buttonc.append(button2); buttonc.classList.add("friendlyButton"); buttonc.append(button2); buttons.append(buttonc); - buttonc.onclick=(e)=>{ + buttonc.onclick = (e) => { e.stopImmediatePropagation(); user.changeRelationship(1); outerDiv.remove(); - } + }; } buttonc.append(button1); buttonc.classList.add("friendlyButton"); - buttonc.onclick=(e)=>{ + buttonc.onclick = (e) => { e.stopImmediatePropagation(); user.changeRelationship(0); outerDiv.remove(); - } + }; buttons.append(buttonc); - const outerDiv=genuserstrip(user,buttons); + const outerDiv = genuserstrip(user, buttons); container.append(outerDiv); } } - } - pending.onclick=genPending; + }; + pending.onclick = genPending; channelTopic.append(pending); } { - const blocked=document.createElement("button"); - blocked.textContent=I18n.getTranslation("friends.blocked"); + const blocked = document.createElement("button"); + blocked.textContent = I18n.getTranslation("friends.blocked"); - const genBlocked=()=>{ - this.localuser.relationshipsUpdate=genBlocked; + const genBlocked = () => { + this.localuser.relationshipsUpdate = genBlocked; checkVoid(); - container.innerHTML=""; + container.innerHTML = ""; container.append(I18n.getTranslation("friends.blockedusers")); - for(const user of this.localuser.inrelation){ - if(user.relationshipType===2){ - const buttonc=document.createElement("div"); - const button1=document.createElement("span"); - button1.classList.add("svg-x","svgicon"); + for (const user of this.localuser.inrelation) { + if (user.relationshipType === 2) { + const buttonc = document.createElement("div"); + const button1 = document.createElement("span"); + button1.classList.add("svg-x", "svgicon"); buttonc.append(button1); buttonc.classList.add("friendlyButton"); - buttonc.onclick=(e)=>{ + buttonc.onclick = (e) => { user.changeRelationship(0); e.stopImmediatePropagation(); outerDiv.remove(); - } - const outerDiv=genuserstrip(user,buttonc); + }; + const outerDiv = genuserstrip(user, buttonc); container.append(outerDiv); } } - } - blocked.onclick=genBlocked; + }; + blocked.onclick = genBlocked; channelTopic.append(blocked); } { - const add=document.createElement("button"); - add.textContent=I18n.getTranslation("friends.addfriend"); - add.onclick=()=>{ - this.localuser.relationshipsUpdate=()=>{}; - container.innerHTML=""; - const float=new Float(""); - const options=float.options; - const form=options.addForm("",(e:any)=>{ - console.log(e); - if(e.code===404){ - throw new FormError(text,I18n.getTranslation("friends.notfound")); - }else if(e.code===400){ - throw new FormError(text,e.message.split("Error: ")[1]); - }else{ - const box=text.input.deref(); - if(!box)return; - box.value=""; - } - },{ - method:"POST", - fetchURL:this.info.api+"/users/@me/relationships", - headers:this.headers - }); - const text=form.addTextInput(I18n.getTranslation("friends.addfriendpromt"),"username"); - form.addPreprocessor((obj:any)=>{ - const [username,discriminator]=obj.username.split("#"); - obj.username=username; - obj.discriminator=discriminator; - if(!discriminator){ - throw new FormError(text,I18n.getTranslation("friends.discnotfound")); + const add = document.createElement("button"); + add.textContent = I18n.getTranslation("friends.addfriend"); + add.onclick = () => { + this.localuser.relationshipsUpdate = () => {}; + container.innerHTML = ""; + const float = new Float(""); + const options = float.options; + const form = options.addForm( + "", + (e: any) => { + console.log(e); + if (e.code === 404) { + throw new FormError(text, I18n.getTranslation("friends.notfound")); + } else if (e.code === 400) { + throw new FormError(text, e.message.split("Error: ")[1]); + } else { + const box = text.input.deref(); + if (!box) return; + box.value = ""; + } + }, + { + method: "POST", + fetchURL: this.info.api + "/users/@me/relationships", + headers: this.headers, + }, + ); + const text = form.addTextInput(I18n.getTranslation("friends.addfriendpromt"), "username"); + form.addPreprocessor((obj: any) => { + const [username, discriminator] = obj.username.split("#"); + obj.username = username; + obj.discriminator = discriminator; + if (!discriminator) { + throw new FormError(text, I18n.getTranslation("friends.discnotfound")); } }); container.append(float.generateHTML()); - } + }; channelTopic.append(add); } } - get mentions(){ - let mentions=0; - for(const thing of this.localuser.inrelation){ - if(thing.relationshipType===3){ - mentions+=1; + get mentions() { + let mentions = 0; + for (const thing of this.localuser.inrelation) { + if (thing.relationshipType === 3) { + mentions += 1; } } return mentions; } - giveMember(_member: memberjson){ + giveMember(_member: memberjson) { throw new Error("not a real guild, can't give member object"); } - getRole(/* ID: string */){ + getRole(/* ID: string */) { return null; } - hasRole(/* r: string */){ + hasRole(/* r: string */) { return false; } - isAdmin(){ + isAdmin() { return false; } - unreaddms(){ - for(const thing of this.channels){ + unreaddms() { + for (const thing of this.channels) { (thing as Group).unreads(); } } @@ -335,34 +339,46 @@ dmPermissions.setPermission("STREAM", 1); dmPermissions.setPermission("USE_VAD", 1); // @ts-ignore I need to look into this lol -class Group extends Channel{ +class Group extends Channel { user: User; static contextmenu = new Contextmenu("channel menu"); - static setupcontextmenu(){ - this.contextmenu.addbutton(()=>I18n.getTranslation("DMs.copyId"), function(this: Group){ - navigator.clipboard.writeText(this.id); - }); + static setupcontextmenu() { + this.contextmenu.addbutton( + () => I18n.getTranslation("DMs.copyId"), + function (this: Group) { + navigator.clipboard.writeText(this.id); + }, + ); - this.contextmenu.addbutton(()=>I18n.getTranslation("DMs.markRead"), function(this: Group){ - this.readbottom(); - }); + this.contextmenu.addbutton( + () => I18n.getTranslation("DMs.markRead"), + function (this: Group) { + this.readbottom(); + }, + ); - this.contextmenu.addbutton(()=>I18n.getTranslation("DMs.close"), function(this: Group){ - this.deleteChannel(); - }); + this.contextmenu.addbutton( + () => I18n.getTranslation("DMs.close"), + function (this: Group) { + this.deleteChannel(); + }, + ); - this.contextmenu.addbutton(()=>I18n.getTranslation("user.copyId"), function(){ - navigator.clipboard.writeText(this.user.id); - }); + this.contextmenu.addbutton( + () => I18n.getTranslation("user.copyId"), + function () { + navigator.clipboard.writeText(this.user.id); + }, + ); } - constructor(json: dirrectjson, owner: Direct){ + constructor(json: dirrectjson, owner: Direct) { super(-1, owner, json.id); this.owner = owner; this.headers = this.guild.headers; this.name = json.recipients[0]?.username; - if(json.recipients[0]){ + if (json.recipients[0]) { this.user = new User(json.recipients[0], this.localuser); - }else{ + } else { this.user = this.localuser.user; } this.name ??= this.localuser.user.username; @@ -376,26 +392,26 @@ class Group extends Channel{ this.setUpInfiniteScroller(); this.updatePosition(); } - updatePosition(){ - if(this.lastmessageid){ + updatePosition() { + if (this.lastmessageid) { this.position = SnowFlake.stringToUnixTime(this.lastmessageid); - }else{ + } else { this.position = 0; } this.position = -Math.max(this.position, this.getUnixTime()); } - createguildHTML(){ + createguildHTML() { const div = document.createElement("div"); - Group.contextmenu.bindContextmenu(div, this,undefined); + Group.contextmenu.bindContextmenu(div, this, undefined); this.html = new WeakRef(div); - div.classList.add("flexltr","liststyle"); + div.classList.add("flexltr", "liststyle"); const myhtml = document.createElement("span"); myhtml.classList.add("ellipsis"); myhtml.textContent = this.name; div.appendChild(this.user.buildpfp()); div.appendChild(myhtml); (div as any).myinfo = this; - div.onclick = _=>{ + div.onclick = (_) => { this.getHTML(); const toggle = document.getElementById("maintoggle") as HTMLInputElement; toggle.checked = true; @@ -403,56 +419,55 @@ class Group extends Channel{ return div; } - async getHTML(addstate=true){ + async getHTML(addstate = true) { const id = ++Channel.genid; - if(this.localuser.channelfocus){ + if (this.localuser.channelfocus) { this.localuser.channelfocus.infinite.delete(); } - if(this.guild !== this.localuser.lookingguild){ + if (this.guild !== this.localuser.lookingguild) { this.guild.loadGuild(); } this.guild.prevchannel = this; this.localuser.channelfocus = this; const prom = this.infinite.delete(); - if(addstate){ - history.pushState([this.guild_id,this.id], "", "/channels/" + this.guild_id + "/" + this.id); + if (addstate) { + history.pushState([this.guild_id, this.id], "", "/channels/" + this.guild_id + "/" + this.id); } this.localuser.pageTitle("@" + this.name); - (document.getElementById("channelTopic") as HTMLElement).setAttribute("hidden",""); + (document.getElementById("channelTopic") as HTMLElement).setAttribute("hidden", ""); const loading = document.getElementById("loadingdiv") as HTMLDivElement; Channel.regenLoadingMessages(); loading.classList.add("loading"); this.rendertyping(); - (document.getElementById("typebox") as HTMLDivElement).contentEditable ="" + true; - (document.getElementById("upload") as HTMLElement).style.visibility="visible"; - (document.getElementById("typediv") as HTMLElement).style.visibility="visible"; + (document.getElementById("typebox") as HTMLDivElement).contentEditable = "" + true; + (document.getElementById("upload") as HTMLElement).style.visibility = "visible"; + (document.getElementById("typediv") as HTMLElement).style.visibility = "visible"; (document.getElementById("typebox") as HTMLDivElement).focus(); await this.putmessages(); await prom; this.localuser.getSidePannel(); - if(id !== Channel.genid){ + if (id !== Channel.genid) { return; } this.buildmessages(); - } - messageCreate(messagep: { d: messagejson }){ + messageCreate(messagep: {d: messagejson}) { this.mentions++; const messagez = new Message(messagep.d, this); - if(this.lastmessageid){ + if (this.lastmessageid) { this.idToNext.set(this.lastmessageid, messagez.id); this.idToPrev.set(messagez.id, this.lastmessageid); } this.lastmessageid = messagez.id; - if(messagez.author === this.localuser.user){ + if (messagez.author === this.localuser.user) { this.lastreadmessageid = messagez.id; - if(this.myhtml){ + if (this.myhtml) { this.myhtml.classList.remove("cunread"); } - }else{ - if(this.myhtml){ + } else { + if (this.myhtml) { this.myhtml.classList.add("cunread"); } } @@ -460,55 +475,55 @@ class Group extends Channel{ this.updatePosition(); this.infinite.addedBottom(); this.guild.sortchannels(); - if(this.myhtml){ + if (this.myhtml) { const parrent = this.myhtml.parentElement as HTMLElement; parrent.prepend(this.myhtml); } - if(this === this.localuser.channelfocus){ - if(!this.infinitefocus){ + if (this === this.localuser.channelfocus) { + if (!this.infinitefocus) { this.tryfocusinfinate(); } this.infinite.addedBottom(); } this.unreads(); - if(messagez.author === this.localuser.user){ - this.mentions=0; + if (messagez.author === this.localuser.user) { + this.mentions = 0; return; } - if(this.localuser.lookingguild?.prevchannel === this && document.hasFocus()){ + if (this.localuser.lookingguild?.prevchannel === this && document.hasFocus()) { return; } - if(this.notification === "all"){ + if (this.notification === "all") { this.notify(messagez); - }else if(this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)){ + } else if (this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)) { this.notify(messagez); } } - notititle(message: Message){ + notititle(message: Message) { return message.author.username; } - readbottom(){ + readbottom() { super.readbottom(); this.unreads(); } all: WeakRef = new WeakRef(document.createElement("div")); noti: WeakRef = new WeakRef(document.createElement("div")); - del(){ + del() { const all = this.all.deref(); - if(all){ + if (all) { all.remove(); } - if(this.myhtml){ + if (this.myhtml) { this.myhtml.remove(); } } - unreads(){ + unreads() { const sentdms = document.getElementById("sentdms") as HTMLDivElement; //Need to change sometime const current = this.all.deref(); - if(this.hasunreads){ + if (this.hasunreads) { { const noti = this.noti.deref(); - if(noti){ + if (noti) { noti.textContent = this.mentions + ""; return; } @@ -525,24 +540,24 @@ class Group extends Channel{ buildpfp.classList.add("mentioned"); div.append(buildpfp); sentdms.append(div); - div.onclick = _=>{ + div.onclick = (_) => { this.guild.loadGuild(); this.getHTML(); const toggle = document.getElementById("maintoggle") as HTMLInputElement; toggle.checked = true; }; - }else if(current){ + } else if (current) { current.remove(); - }else{ + } else { } } - isAdmin(): boolean{ + isAdmin(): boolean { return false; } - hasPermission(name: string): boolean{ + hasPermission(name: string): boolean { return dmPermissions.hasPermission(name); } } -export{ Direct, Group }; +export {Direct, Group}; -Group.setupcontextmenu() +Group.setupcontextmenu(); diff --git a/src/webpage/disimg.ts b/src/webpage/disimg.ts index a1d2a1d4..e37978e3 100644 --- a/src/webpage/disimg.ts +++ b/src/webpage/disimg.ts @@ -1,37 +1,37 @@ -class ImagesDisplay{ - images:string[]; - index=0; - constructor(srcs:string[],index=0){ - this.images=srcs; - this.index=index; +class ImagesDisplay { + images: string[]; + index = 0; + constructor(srcs: string[], index = 0) { + this.images = srcs; + this.index = index; } - weakbg=new WeakRef(document.createElement("div")); - get background():HTMLElement|undefined{ + weakbg = new WeakRef(document.createElement("div")); + get background(): HTMLElement | undefined { return this.weakbg.deref(); } - set background(e:HTMLElement){ - this.weakbg=new WeakRef(e); + set background(e: HTMLElement) { + this.weakbg = new WeakRef(e); } - makeHTML():HTMLElement{ + makeHTML(): HTMLElement { //TODO this should be able to display more than one image at a time lol - const image= document.createElement("img"); - image.src=this.images[this.index]; - image.classList.add("imgfit","centeritem"); + const image = document.createElement("img"); + image.src = this.images[this.index]; + image.classList.add("imgfit", "centeritem"); return image; } - show(){ + show() { this.background = document.createElement("div"); this.background.classList.add("background"); this.background.appendChild(this.makeHTML()); - this.background.onclick = _=>{ + this.background.onclick = (_) => { this.hide(); }; document.body.append(this.background); } - hide(){ - if(this.background){ + hide() { + if (this.background) { this.background.remove(); } } } -export{ImagesDisplay} +export {ImagesDisplay}; diff --git a/src/webpage/embed.ts b/src/webpage/embed.ts index 73bad4a2..50dd6816 100644 --- a/src/webpage/embed.ts +++ b/src/webpage/embed.ts @@ -1,94 +1,85 @@ -import{ Message }from"./message.js"; -import{ MarkDown }from"./markdown.js"; -import{ embedjson, invitejson }from"./jsontypes.js"; -import{ getapiurls, getInstances }from"./utils/utils.js"; -import{ Guild }from"./guild.js"; -import { I18n } from "./i18n.js"; -import { ImagesDisplay } from "./disimg.js"; +import {Message} from "./message.js"; +import {MarkDown} from "./markdown.js"; +import {embedjson, invitejson} from "./jsontypes.js"; +import {getapiurls, getInstances} from "./utils/utils.js"; +import {Guild} from "./guild.js"; +import {I18n} from "./i18n.js"; +import {ImagesDisplay} from "./disimg.js"; -class Embed{ +class Embed { type: string; owner: Message; json: embedjson; - constructor(json: embedjson, owner: Message){ + constructor(json: embedjson, owner: Message) { this.type = this.getType(json); this.owner = owner; this.json = json; } - getType(json: embedjson){ + getType(json: embedjson) { const instances = getInstances(); - if( - instances && -json.type === "link" && -json.url && -URL.canParse(json.url) - ){ + if (instances && json.type === "link" && json.url && URL.canParse(json.url)) { const Url = new URL(json.url); - for(const instance of instances){ - if(instance.url && URL.canParse(instance.url)){ + for (const instance of instances) { + if (instance.url && URL.canParse(instance.url)) { const IUrl = new URL(instance.url); const params = new URLSearchParams(Url.search); let host: string; - if(params.has("instance")){ + if (params.has("instance")) { const url = params.get("instance") as string; - if(URL.canParse(url)){ + if (URL.canParse(url)) { host = new URL(url).host; - }else{ + } else { host = Url.host; } - }else{ + } else { host = Url.host; } - if(IUrl.host === host){ - const code = -Url.pathname.split("/")[Url.pathname.split("/").length - 1]; + if (IUrl.host === host) { + const code = Url.pathname.split("/")[Url.pathname.split("/").length - 1]; json.invite = { url: instance.url, code, }; - return"invite"; + return "invite"; } } } } return json.type || "rich"; } - generateHTML(){ - switch(this.type){ - case"rich": - return this.generateRich(); - case"image": - return this.generateImage(); - case"invite": - return this.generateInvite(); - case"link": - return this.generateLink(); - case"video": - case"article": - return this.generateArticle(); - default: - console.warn( - `unsupported embed type ${this.type}, please add support dev :3`, - this.json - ); - return document.createElement("div"); //prevent errors by giving blank div + generateHTML() { + switch (this.type) { + case "rich": + return this.generateRich(); + case "image": + return this.generateImage(); + case "invite": + return this.generateInvite(); + case "link": + return this.generateLink(); + case "video": + case "article": + return this.generateArticle(); + default: + console.warn(`unsupported embed type ${this.type}, please add support dev :3`, this.json); + return document.createElement("div"); //prevent errors by giving blank div } } - get message(){ + get message() { return this.owner; } - get channel(){ + get channel() { return this.message.channel; } - get guild(){ + get guild() { return this.channel.guild; } - get localuser(){ + get localuser() { return this.guild.localuser; } - generateRich(){ + generateRich() { const div = document.createElement("div"); - if(this.json.color){ + if (this.json.color) { div.style.backgroundColor = "#" + this.json.color.toString(16); } div.classList.add("embed-color"); @@ -97,9 +88,9 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; embed.classList.add("embed"); div.append(embed); - if(this.json.author){ + if (this.json.author) { const authorline = document.createElement("div"); - if(this.json.author.icon_url){ + if (this.json.author.icon_url) { const img = document.createElement("img"); img.classList.add("embedimg"); img.src = this.json.author.icon_url; @@ -107,31 +98,31 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; } const a = document.createElement("a"); a.textContent = this.json.author.name as string; - if(this.json.author.url){ + if (this.json.author.url) { MarkDown.safeLink(a, this.json.author.url); } a.classList.add("username"); authorline.append(a); embed.append(authorline); } - if(this.json.title){ + if (this.json.title) { const title = document.createElement("a"); title.append(new MarkDown(this.json.title, this.channel).makeHTML()); - if(this.json.url){ + if (this.json.url) { MarkDown.safeLink(title, this.json.url); } title.classList.add("embedtitle"); embed.append(title); } - if(this.json.description){ + if (this.json.description) { const p = document.createElement("p"); p.append(new MarkDown(this.json.description, this.channel).makeHTML()); embed.append(p); } embed.append(document.createElement("br")); - if(this.json.fields){ - for(const thing of this.json.fields){ + if (this.json.fields) { + for (const thing of this.json.fields) { const div = document.createElement("div"); const b = document.createElement("b"); b.textContent = thing.name; @@ -141,31 +132,31 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; p.classList.add("embedp"); div.append(p); - if(thing.inline){ + if (thing.inline) { div.classList.add("inline"); } embed.append(div); } } - if(this.json.footer || this.json.timestamp){ + if (this.json.footer || this.json.timestamp) { const footer = document.createElement("div"); - if(this.json?.footer?.icon_url){ + if (this.json?.footer?.icon_url) { const img = document.createElement("img"); img.src = this.json.footer.icon_url; img.classList.add("embedicon"); footer.append(img); } - if(this.json?.footer?.text){ + if (this.json?.footer?.text) { const span = document.createElement("span"); span.textContent = this.json.footer.text; footer.append(span); } - if(this.json?.footer && this.json?.timestamp){ + if (this.json?.footer && this.json?.timestamp) { const span = document.createElement("span"); span.textContent = " • "; footer.append(span); } - if(this.json?.timestamp){ + if (this.json?.timestamp) { const span = document.createElement("span"); span.textContent = new Date(this.json.timestamp).toLocaleString(); footer.append(span); @@ -174,15 +165,15 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; } return div; } - generateImage(){ + generateImage() { const img = document.createElement("img"); img.classList.add("messageimg"); - img.onclick = function(){ + img.onclick = function () { const full = new ImagesDisplay([img.src]); full.show(); }; img.src = this.json.thumbnail.proxy_url; - if(this.json.thumbnail.width){ + if (this.json.thumbnail.width) { let scale = 1; const max = 96 * 3; scale = Math.max(scale, this.json.thumbnail.width / max); @@ -195,12 +186,12 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; console.log(this.json, "Image fix"); return img; } - generateLink(){ + generateLink() { const table = document.createElement("table"); table.classList.add("embed", "linkembed"); const trtop = document.createElement("tr"); table.append(trtop); - if(this.json.url && this.json.title){ + if (this.json.url && this.json.title) { const td = document.createElement("td"); const a = document.createElement("a"); MarkDown.safeLink(a, this.json.url); @@ -211,9 +202,9 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; { const td = document.createElement("td"); const img = document.createElement("img"); - if(this.json.thumbnail){ + if (this.json.thumbnail) { img.classList.add("embedimg"); - img.onclick = function(){ + img.onclick = function () { const full = new ImagesDisplay([img.src]); full.show(); }; @@ -224,7 +215,7 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; } const bottomtr = document.createElement("tr"); const td = document.createElement("td"); - if(this.json.description){ + if (this.json.description) { const span = document.createElement("span"); span.textContent = this.json.description; td.append(span); @@ -233,59 +224,62 @@ Url.pathname.split("/")[Url.pathname.split("/").length - 1]; table.append(bottomtr); return table; } - invcache: [invitejson, { cdn: string; api: string }] | undefined; - generateInvite(){ - if(this.invcache && (!this.json.invite || !this.localuser)){ + invcache: [invitejson, {cdn: string; api: string}] | undefined; + generateInvite() { + if (this.invcache && (!this.json.invite || !this.localuser)) { return this.generateLink(); } const div = document.createElement("div"); div.classList.add("embed", "inviteEmbed", "flexttb"); const json1 = this.json.invite; - (async ()=>{ + (async () => { let json: invitejson; - let info: { cdn: string; api: string }; - if(!this.invcache){ - if(!json1){ - div.classList.remove("embed", "inviteEmbed", "flexttb") + let info: {cdn: string; api: string}; + if (!this.invcache) { + if (!json1) { + div.classList.remove("embed", "inviteEmbed", "flexttb"); div.append(this.generateLink()); return; } const tempinfo = await getapiurls(json1.url); - if(!tempinfo){ - div.classList.remove("embed", "inviteEmbed", "flexttb") + if (!tempinfo) { + div.classList.remove("embed", "inviteEmbed", "flexttb"); div.append(this.generateLink()); return; } info = tempinfo; const res = await fetch(info.api + "/invites/" + json1.code); - if(!res.ok){ - div.classList.remove("embed", "inviteEmbed", "flexttb") + if (!res.ok) { + div.classList.remove("embed", "inviteEmbed", "flexttb"); div.append(this.generateLink()); return; } json = (await res.json()) as invitejson; this.invcache = [json, info]; - }else{ + } else { [json, info] = this.invcache; } - if(!json){ + if (!json) { div.append(this.generateLink()); - div.classList.remove("embed", "inviteEmbed", "flexttb") + div.classList.remove("embed", "inviteEmbed", "flexttb"); return; } - if(json.guild.banner){ + if (json.guild.banner) { const banner = document.createElement("img"); - banner.src = this.localuser.info.cdn + "/icons/" + json.guild.id + "/" + json.guild.banner + ".png?size=256"; + banner.src = + this.localuser.info.cdn + + "/icons/" + + json.guild.id + + "/" + + json.guild.banner + + ".png?size=256"; banner.classList.add("banner"); div.append(banner); } - const guild: invitejson["guild"] & { info?: { cdn: string } } = -json.guild; + const guild: invitejson["guild"] & {info?: {cdn: string}} = json.guild; guild.info = info; - const icon = Guild.generateGuildIcon( -guild as invitejson["guild"] & { info: { cdn: string } } - ); + const icon = Guild.generateGuildIcon(guild as invitejson["guild"] & {info: {cdn: string}}); const iconrow = document.createElement("div"); iconrow.classList.add("flexltr"); iconrow.append(icon); @@ -305,30 +299,30 @@ guild as invitejson["guild"] & { info: { cdn: string } } div.append(iconrow); const h2 = document.createElement("h2"); - h2.textContent = I18n.getTranslation("invite.invitedBy",json.inviter.username); + h2.textContent = I18n.getTranslation("invite.invitedBy", json.inviter.username); div.append(h2); const button = document.createElement("button"); button.textContent = I18n.getTranslation("invite.accept"); - if(this.localuser.info.api.startsWith(info.api) && this.localuser.guildids.has(guild.id)){ + if (this.localuser.info.api.startsWith(info.api) && this.localuser.guildids.has(guild.id)) { button.textContent = I18n.getTranslation("invite.alreadyJoined"); button.disabled = true; } button.classList.add("acceptinvbutton"); div.append(button); - button.onclick = _=>{ - if(this.localuser.info.api.startsWith(info.api)){ + button.onclick = (_) => { + if (this.localuser.info.api.startsWith(info.api)) { fetch(this.localuser.info.api + "/invites/" + json.code, { method: "POST", headers: this.localuser.headers, }) - .then(r=>r.json()) - .then(_=>{ - if(_.message){ + .then((r) => r.json()) + .then((_) => { + if (_.message) { alert(_.message); } }); - }else{ - if(this.json.invite){ + } else { + if (this.json.invite) { const params = new URLSearchParams(""); params.set("instance", this.json.invite.url); const encoded = params.toString(); @@ -340,33 +334,33 @@ guild as invitejson["guild"] & { info: { cdn: string } } })(); return div; } - generateArticle(){ + generateArticle() { const colordiv = document.createElement("div"); colordiv.style.backgroundColor = "#000000"; colordiv.classList.add("embed-color"); const div = document.createElement("div"); div.classList.add("embed"); - if(this.json.provider){ + if (this.json.provider) { const provider = document.createElement("p"); provider.classList.add("provider"); provider.textContent = this.json.provider.name; div.append(provider); } const a = document.createElement("a"); - if(this.json.url && this.json.url){ + if (this.json.url && this.json.url) { MarkDown.safeLink(a, this.json.url); a.textContent = this.json.url; div.append(a); } - if(this.json.description){ + if (this.json.description) { const description = document.createElement("p"); description.textContent = this.json.description; div.append(description); } - if(this.json.thumbnail){ + if (this.json.thumbnail) { const img = document.createElement("img"); - if(this.json.thumbnail.width && this.json.thumbnail.width){ + if (this.json.thumbnail.width && this.json.thumbnail.width) { let scale = 1; const inch = 96; scale = Math.max(scale, this.json.thumbnail.width / inch / 4); @@ -377,21 +371,21 @@ guild as invitejson["guild"] & { info: { cdn: string } } img.style.height = this.json.thumbnail.height + "px"; } img.classList.add("bigembedimg"); - if(this.json.video){ - img.onclick = async ()=>{ - if(this.json.video){ + if (this.json.video) { + img.onclick = async () => { + if (this.json.video) { img.remove(); const iframe = document.createElement("iframe"); iframe.src = this.json.video.url + "?autoplay=1"; - if(this.json.thumbnail.width && this.json.thumbnail.width){ + if (this.json.thumbnail.width && this.json.thumbnail.width) { iframe.style.width = this.json.thumbnail.width + "px"; iframe.style.height = this.json.thumbnail.height + "px"; } div.append(iframe); } }; - }else{ - img.onclick = async ()=>{ + } else { + img.onclick = async () => { const full = new ImagesDisplay([img.src]); full.show(); }; @@ -403,4 +397,4 @@ guild as invitejson["guild"] & { info: { cdn: string } } return colordiv; } } -export{ Embed }; +export {Embed}; diff --git a/src/webpage/emoji.ts b/src/webpage/emoji.ts index b6e04e82..bff6a99d 100644 --- a/src/webpage/emoji.ts +++ b/src/webpage/emoji.ts @@ -1,75 +1,73 @@ -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"; +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{ +class Emoji { static emojis: { name: string; emojis: { - name: string; - emoji: string; + name: string; + emoji: string; }[]; }[]; name: string; id?: string; - emoji?:string; + emoji?: string; animated: boolean; owner: Guild | Localuser; - get guild(){ - if(this.owner instanceof Guild){ + get guild() { + if (this.owner instanceof Guild) { return this.owner; } return null; } - get localuser(){ - if(this.owner instanceof Guild){ + get localuser() { + if (this.owner instanceof Guild) { return this.owner.localuser; - }else{ + } else { return this.owner; } } - get info(){ + get info() { return this.owner.info; } - constructor( - json: emojijson, - owner: Guild | Localuser - ){ + constructor(json: emojijson, owner: Guild | Localuser) { this.name = json.name; this.id = json.id; - this.animated = json.animated||false; + this.animated = json.animated || false; this.owner = owner; - this.emoji=json.emoji; + this.emoji = json.emoji; } - getHTML(bigemoji: boolean = false){ - if(this.id){ + getHTML(bigemoji: boolean = false) { + if (this.id) { const emojiElem = document.createElement("img"); emojiElem.classList.add("md-emoji"); emojiElem.classList.add(bigemoji ? "bigemoji" : "smallemoji"); emojiElem.crossOrigin = "anonymous"; - emojiElem.src =this.info.cdn+"/emojis/"+this.id+"."+(this.animated ? "gif" : "png")+"?size=32"; + emojiElem.src = + this.info.cdn + "/emojis/" + this.id + "." + (this.animated ? "gif" : "png") + "?size=32"; emojiElem.alt = this.name; emojiElem.loading = "lazy"; return emojiElem; - }else if(this.emoji){ + } else if (this.emoji) { const emojiElem = document.createElement("span"); emojiElem.classList.add("md-emoji"); emojiElem.classList.add(bigemoji ? "bigemoji" : "smallemoji"); - emojiElem.textContent=this.emoji; + emojiElem.textContent = this.emoji; return emojiElem; - }else{ + } else { throw new Error("This path should *never* be gone down, this means a malformed emoji"); } } - static decodeEmojiList(buffer: ArrayBuffer){ - const reader=new BinRead(buffer) - const build: { name: string; emojis: { name: string; emoji: string }[] }[] = []; + static decodeEmojiList(buffer: ArrayBuffer) { + const reader = new BinRead(buffer); + const build: {name: string; emojis: {name: string; emoji: string}[]}[] = []; let cats = reader.read16(); - for(; cats !== 0; cats--){ + for (; cats !== 0; cats--) { const name = reader.readString16(); const emojis: { name: string; @@ -77,7 +75,7 @@ class Emoji{ emoji: string; }[] = []; let emojinumber = reader.read16(); - for(; emojinumber !== 0; emojinumber--){ + for (; emojinumber !== 0; emojinumber--) { //console.log(emojis); const name = reader.readString8(); const len = reader.read8(); @@ -96,22 +94,18 @@ class Emoji{ } this.emojis = build; } - static grabEmoji(){ + static grabEmoji() { fetch("/emoji.bin") - .then(e=>{ + .then((e) => { return e.arrayBuffer(); }) - .then(e=>{ + .then((e) => { Emoji.decodeEmojiList(e); }); } - static async emojiPicker( - x: number, - y: number, - localuser: Localuser - ): Promise{ + static async emojiPicker(x: number, y: number, localuser: Localuser): Promise { let res: (r: Emoji | string) => void; - const promise: Promise = new Promise(r=>{ + const promise: Promise = new Promise((r) => { res = r; }); const menu = document.createElement("div"); @@ -130,33 +124,39 @@ class Emoji{ let isFirst = true; localuser.guilds - .filter(guild=>guild.id != "@me" && guild.emojis.length > 0) - .forEach(guild=>{ + .filter((guild) => guild.id != "@me" && guild.emojis.length > 0) + .forEach((guild) => { const select = document.createElement("div"); select.classList.add("emojiSelect"); - if(guild.properties.icon){ + if (guild.properties.icon) { const img = document.createElement("img"); img.classList.add("pfp", "servericon", "emoji-server"); img.crossOrigin = "anonymous"; - img.src = localuser.info.cdn+"/icons/"+guild.properties.id+"/"+guild.properties.icon+".png?size=48"; + img.src = + localuser.info.cdn + + "/icons/" + + guild.properties.id + + "/" + + guild.properties.icon + + ".png?size=48"; img.alt = "Server: " + guild.properties.name; select.appendChild(img); - }else{ + } else { const div = document.createElement("span"); div.textContent = guild.properties.name .replace(/'s /g, " ") - .replace(/\w+/g, word=>word[0]) + .replace(/\w+/g, (word) => word[0]) .replace(/\s/g, ""); select.append(div); } selection.append(select); - const clickEvent = ()=>{ + const clickEvent = () => { title.textContent = guild.properties.name; body.innerHTML = ""; - for(const emojit of guild.emojis){ + for (const emojit of guild.emojis) { const emojiElem = document.createElement("div"); emojiElem.classList.add("emojiSelect"); @@ -166,14 +166,14 @@ class Emoji{ name: emojit.name, animated: emojit.animated as boolean, }, - localuser + localuser, ); emojiElem.append(emojiClass.getHTML()); body.append(emojiElem); - emojiElem.addEventListener("click", ()=>{ + emojiElem.addEventListener("click", () => { res(emojiClass); - if(Contextmenu.currentmenu !== ""){ + if (Contextmenu.currentmenu !== "") { Contextmenu.currentmenu.remove(); } }); @@ -181,14 +181,14 @@ class Emoji{ }; select.addEventListener("click", clickEvent); - if(isFirst){ + if (isFirst) { clickEvent(); isFirst = false; } }); - setTimeout(()=>{ - if(Contextmenu.currentmenu != ""){ + setTimeout(() => { + if (Contextmenu.currentmenu != "") { Contextmenu.currentmenu.remove(); } document.body.append(menu); @@ -197,29 +197,29 @@ class Emoji{ }, 10); let i = 0; - for(const thing of Emoji.emojis){ + for (const thing of Emoji.emojis) { const select = document.createElement("div"); select.textContent = thing.emojis[0].emoji; select.classList.add("emojiSelect"); selection.append(select); - const clickEvent = ()=>{ + const clickEvent = () => { title.textContent = thing.name; body.innerHTML = ""; - for(const emojit of thing.emojis){ + for (const emojit of thing.emojis) { const emoji = document.createElement("div"); emoji.classList.add("emojiSelect"); emoji.textContent = emojit.emoji; body.append(emoji); - emoji.onclick = _=>{ + emoji.onclick = (_) => { res(emojit.emoji); - if(Contextmenu.currentmenu !== ""){ + if (Contextmenu.currentmenu !== "") { Contextmenu.currentmenu.remove(); } }; } }; select.onclick = clickEvent; - if(i === 0){ + if (i === 0) { clickEvent(); } i++; @@ -228,40 +228,39 @@ class Emoji{ menu.append(body); return promise; } - static searchEmoji(search:string,localuser:Localuser,results=50):[Emoji,number][]{ - const ranked:[emojijson,number][]=[]; - function similar(json:emojijson){ - if(json.name.includes(search)){ - ranked.push([json,search.length/json.name.length]); + static searchEmoji(search: string, localuser: Localuser, results = 50): [Emoji, number][] { + const ranked: [emojijson, number][] = []; + function similar(json: emojijson) { + if (json.name.includes(search)) { + ranked.push([json, search.length / json.name.length]); return true; - }else if(json.name.toLowerCase().includes(search.toLowerCase())){ - ranked.push([json,search.length/json.name.length/1.4]); + } else if (json.name.toLowerCase().includes(search.toLowerCase())) { + ranked.push([json, search.length / json.name.length / 1.4]); return true; - }else{ + } else { return false; } } - for(const group of this.emojis){ - for(const emoji of group.emojis){ - similar(emoji) + for (const group of this.emojis) { + for (const emoji of group.emojis) { + similar(emoji); } } - const weakGuild=new WeakMap(); - for(const guild of localuser.guilds){ - if(guild.id!=="@me"&&guild.emojis.length!==0){ - for(const emoji of guild.emojis){ - if(similar(emoji)){ - weakGuild.set(emoji,guild); - }; + const weakGuild = new WeakMap(); + for (const guild of localuser.guilds) { + if (guild.id !== "@me" && guild.emojis.length !== 0) { + for (const emoji of guild.emojis) { + if (similar(emoji)) { + weakGuild.set(emoji, guild); + } } } } - ranked.sort((a,b)=>b[1]-a[1]); - return ranked.splice(0,results).map(a=>{ - return [new Emoji(a[0],weakGuild.get(a[0])||localuser),a[1]]; - - }) + ranked.sort((a, b) => b[1] - a[1]); + return ranked.splice(0, results).map((a) => { + return [new Emoji(a[0], weakGuild.get(a[0]) || localuser), a[1]]; + }); } } Emoji.grabEmoji(); -export{ Emoji }; +export {Emoji}; diff --git a/src/webpage/file.ts b/src/webpage/file.ts index a16dcb57..f394ad48 100644 --- a/src/webpage/file.ts +++ b/src/webpage/file.ts @@ -1,8 +1,8 @@ -import{ Message }from"./message.js"; -import{ filejson }from"./jsontypes.js"; -import { ImagesDisplay } from "./disimg.js"; +import {Message} from "./message.js"; +import {filejson} from "./jsontypes.js"; +import {ImagesDisplay} from "./disimg.js"; -class File{ +class File { owner: Message | null; id: string; filename: string; @@ -12,7 +12,7 @@ class File{ proxy_url: string | undefined; url: string; size: number; - constructor(fileJSON: filejson, owner: Message | null){ + constructor(fileJSON: filejson, owner: Message | null) { this.owner = owner; this.id = fileJSON.id; this.filename = fileJSON.filename; @@ -24,9 +24,9 @@ class File{ this.content_type = fileJSON.content_type; this.size = fileJSON.size; } - getHTML(temp: boolean = false): HTMLElement{ + getHTML(temp: boolean = false): HTMLElement { const src = this.proxy_url || this.url; - if(this.width && this.height){ + if (this.width && this.height) { let scale = 1; const max = 96 * 3; scale = Math.max(scale, this.width / max); @@ -34,35 +34,35 @@ class File{ this.width /= scale; this.height /= scale; } - if(this.content_type.startsWith("image/")){ + if (this.content_type.startsWith("image/")) { const div = document.createElement("div"); const img = document.createElement("img"); img.classList.add("messageimg"); div.classList.add("messageimgdiv"); - img.onclick = function(){ + img.onclick = function () { const full = new ImagesDisplay([img.src]); full.show(); }; img.src = src; div.append(img); - if(this.width){ + if (this.width) { div.style.width = this.width + "px"; div.style.height = this.height + "px"; } return div; - }else if(this.content_type.startsWith("video/")){ + } else if (this.content_type.startsWith("video/")) { const video = document.createElement("video"); const source = document.createElement("source"); source.src = src; video.append(source); source.type = this.content_type; video.controls = !temp; - if(this.width && this.height){ + if (this.width && this.height) { video.width = this.width; video.height = this.height; } return video; - }else if(this.content_type.startsWith("audio/")){ + } else if (this.content_type.startsWith("audio/")) { const audio = document.createElement("audio"); const source = document.createElement("source"); source.src = src; @@ -70,11 +70,11 @@ class File{ source.type = this.content_type; audio.controls = !temp; return audio; - }else{ + } else { return this.createunknown(); } } - upHTML(files: Blob[], file: globalThis.File): HTMLElement{ + upHTML(files: Blob[], file: globalThis.File): HTMLElement { const div = document.createElement("div"); const contained = this.getHTML(true); div.classList.add("containedFile"); @@ -82,9 +82,9 @@ class File{ const controls = document.createElement("div"); const garbage = document.createElement("button"); const icon = document.createElement("span"); - icon.classList.add("svgicon","svg-delete"); + icon.classList.add("svgicon", "svg-delete"); garbage.append(icon); - garbage.onclick = _=>{ + garbage.onclick = (_) => { div.remove(); files.splice(files.indexOf(file), 1); }; @@ -93,7 +93,7 @@ class File{ controls.append(garbage); return div; } - static initFromBlob(file: globalThis.File){ + static initFromBlob(file: globalThis.File) { return new File( { filename: file.name, @@ -105,10 +105,10 @@ class File{ url: URL.createObjectURL(file), proxy_url: undefined, }, - null + null, ); } - createunknown(): HTMLElement{ + createunknown(): HTMLElement { console.log("🗎"); const src = this.proxy_url || this.url; const div = document.createElement("table"); @@ -121,12 +121,12 @@ class File{ fileicon.classList.add("fileicon"); fileicon.rowSpan = 2; const nametd = document.createElement("td"); - if(src){ + if (src) { const a = document.createElement("a"); a.href = src; a.textContent = this.filename; nametd.append(a); - }else{ + } else { nametd.textContent = this.filename; } @@ -140,11 +140,13 @@ class File{ div.appendChild(sizetr); return div; } - static filesizehuman(fsize: number){ + static filesizehuman(fsize: number) { const i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024)); - return( - Number((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + " " + ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "Terabytes"][i] // I don't think this changes across languages, correct me if I'm wrong + return ( + Number((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + + " " + + ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "Terabytes"][i] // I don't think this changes across languages, correct me if I'm wrong ); } } -export{ File }; +export {File}; diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index c217cb7a..1cd544fa 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -1,17 +1,24 @@ -import{ Channel }from"./channel.js"; -import{ Localuser }from"./localuser.js"; -import{ Contextmenu }from"./contextmenu.js"; -import{ Role, RoleList }from"./role.js"; -import{ Member }from"./member.js"; -import{ Dialog, Options, Settings }from"./settings.js"; -import{ Permissions }from"./permissions.js"; -import{ SnowFlake }from"./snowflake.js"; -import{channeljson,guildjson,emojijson,memberjson,invitejson,rolesjson, emojipjson,}from"./jsontypes.js"; -import{ User }from"./user.js"; -import { I18n } from "./i18n.js"; -import { Emoji } from "./emoji.js"; - -class Guild extends SnowFlake{ +import {Channel} from "./channel.js"; +import {Localuser} from "./localuser.js"; +import {Contextmenu} from "./contextmenu.js"; +import {Role, RoleList} from "./role.js"; +import {Member} from "./member.js"; +import {Dialog, Options, Settings} from "./settings.js"; +import {Permissions} from "./permissions.js"; +import {SnowFlake} from "./snowflake.js"; +import { + channeljson, + guildjson, + memberjson, + invitejson, + rolesjson, + emojipjson, +} from "./jsontypes.js"; +import {User} from "./user.js"; +import {I18n} from "./i18n.js"; +import {Emoji} from "./emoji.js"; + +class Guild extends SnowFlake { owner!: Localuser; headers!: Localuser["headers"]; channels!: Channel[]; @@ -29,68 +36,82 @@ class Guild extends SnowFlake{ html!: HTMLElement; emojis!: emojipjson[]; large!: boolean; - members=new Set(); + members = new Set(); static contextmenu = new Contextmenu("guild menu"); - static setupcontextmenu(){ - Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.copyId"), function(this: Guild){ - navigator.clipboard.writeText(this.id); - }); + static setupcontextmenu() { + Guild.contextmenu.addbutton( + () => I18n.getTranslation("guild.copyId"), + function (this: Guild) { + navigator.clipboard.writeText(this.id); + }, + ); - Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.markRead"), function(this: Guild){ - this.markAsRead(); - }); + Guild.contextmenu.addbutton( + () => I18n.getTranslation("guild.markRead"), + function (this: Guild) { + this.markAsRead(); + }, + ); - Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.notifications"), function(this: Guild){ - this.setnotifcation(); - }); + Guild.contextmenu.addbutton( + () => I18n.getTranslation("guild.notifications"), + function (this: Guild) { + this.setnotifcation(); + }, + ); this.contextmenu.addbutton( - ()=>I18n.getTranslation("user.editServerProfile"), - function(){ + () => I18n.getTranslation("user.editServerProfile"), + function () { this.member.showEditProfile(); - } + }, ); Guild.contextmenu.addbutton( - ()=>I18n.getTranslation("guild.leave"), - function(this: Guild){ + () => I18n.getTranslation("guild.leave"), + function (this: Guild) { this.confirmleave(); }, null, - function(_){ + function (_) { return this.properties.owner_id !== this.member.user.id; - } + }, ); Guild.contextmenu.addbutton( - ()=>I18n.getTranslation("guild.delete"), - function(this: Guild){ + () => I18n.getTranslation("guild.delete"), + function (this: Guild) { this.confirmDelete(); }, null, - function(_){ + function (_) { return this.properties.owner_id === this.member.user.id; - } + }, ); Guild.contextmenu.addbutton( - ()=>I18n.getTranslation("guild.makeInvite"), - function(this: Guild){ - const d=new Dialog(""); + () => I18n.getTranslation("guild.makeInvite"), + function (this: Guild) { + const d = new Dialog(""); this.makeInviteMenu(d.options); d.show(); }, null, - _=>true, - function(){ + (_) => true, + function () { return this.member.hasPermission("CREATE_INSTANT_INVITE"); - } + }, + ); + Guild.contextmenu.addbutton( + () => I18n.getTranslation("guild.settings"), + function (this: Guild) { + this.generateSettings(); + }, + null, + function () { + return this.member.hasPermission("MANAGE_GUILD"); + }, ); - Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.settings"), function(this: Guild){ - this.generateSettings(); - },null,function(){ - return this.member.hasPermission("MANAGE_GUILD"); - }); /* -----things left for later----- guild.contextmenu.addbutton("Leave Guild",function(){ console.log(this) @@ -102,162 +123,178 @@ class Guild extends SnowFlake{ },null,_=>{return thisuser.isAdmin()}) */ } - generateSettings(){ - const settings = new Settings(I18n.getTranslation("guild.settingsFor",this.properties.name)); - const textChannels=this.channels.filter(e=>{ + generateSettings() { + const settings = new Settings(I18n.getTranslation("guild.settingsFor", this.properties.name)); + const textChannels = this.channels.filter((e) => { //TODO there are almost certainly more types. is Voice valid? - return new Set([0,5]).has(e.type); + return new Set([0, 5]).has(e.type); }); { const overview = settings.addButton(I18n.getTranslation("guild.overview")); - const form = overview.addForm("", _=>{}, { + const form = overview.addForm("", (_) => {}, { headers: this.headers, traditionalSubmit: true, fetchURL: this.info.api + "/guilds/" + this.id, method: "PATCH", }); - form.addTextInput(I18n.getTranslation("guild.name:"), "name", { initText: this.properties.name }); + form.addTextInput(I18n.getTranslation("guild.name:"), "name", { + initText: this.properties.name, + }); form.addMDInput(I18n.getTranslation("guild.description:"), "description", { initText: this.properties.description, }); - form.addFileInput(I18n.getTranslation("guild.banner:"), "banner", { clear: true }); - form.addFileInput(I18n.getTranslation("guild.icon:"), "icon", { clear: true }); + form.addFileInput(I18n.getTranslation("guild.banner:"), "banner", {clear: true}); + form.addFileInput(I18n.getTranslation("guild.icon:"), "icon", {clear: true}); form.addHR(); - const sysmap=[null,...textChannels.map(e=>e.id)]; - form.addSelect(I18n.getTranslation("guild.systemSelect:"), "system_channel_id", - ["No system messages",...textChannels.map(e=>e.name)],{defaultIndex:sysmap.indexOf(this.properties.system_channel_id)} - ,sysmap); + const sysmap = [null, ...textChannels.map((e) => e.id)]; + form.addSelect( + I18n.getTranslation("guild.systemSelect:"), + "system_channel_id", + ["No system messages", ...textChannels.map((e) => e.name)], + {defaultIndex: sysmap.indexOf(this.properties.system_channel_id)}, + sysmap, + ); - form.addCheckboxInput(I18n.getTranslation("guild.sendrandomwelcome?"),"s1",{ - initState:!(this.properties.system_channel_flags&1) + form.addCheckboxInput(I18n.getTranslation("guild.sendrandomwelcome?"), "s1", { + initState: !(this.properties.system_channel_flags & 1), }); - form.addCheckboxInput(I18n.getTranslation("guild.stickWelcomeReact?"),"s4",{ - initState:!(this.properties.system_channel_flags&8) + form.addCheckboxInput(I18n.getTranslation("guild.stickWelcomeReact?"), "s4", { + initState: !(this.properties.system_channel_flags & 8), }); - form.addCheckboxInput(I18n.getTranslation("guild.boostMessage?"),"s2",{ - initState:!(this.properties.system_channel_flags&2) + form.addCheckboxInput(I18n.getTranslation("guild.boostMessage?"), "s2", { + initState: !(this.properties.system_channel_flags & 2), }); - form.addCheckboxInput(I18n.getTranslation("guild.helpTips?"),"s3",{ - initState:!(this.properties.system_channel_flags&4) + form.addCheckboxInput(I18n.getTranslation("guild.helpTips?"), "s3", { + initState: !(this.properties.system_channel_flags & 4), }); - form.addPreprocessor((e:any)=>{ - let bits=0; - bits+=(1-e.s1)*1; + form.addPreprocessor((e: any) => { + let bits = 0; + bits += (1 - e.s1) * 1; delete e.s1; - bits+=(1-e.s2)*2; + bits += (1 - e.s2) * 2; delete e.s2; - bits+=(1-e.s3)*4; + bits += (1 - e.s3) * 4; delete e.s3; - bits+= (1-e.s4)*8; + bits += (1 - e.s4) * 8; delete e.s4; - e.system_channel_flags=bits; - }) + e.system_channel_flags = bits; + }); form.addHR(); - form.addSelect(I18n.getTranslation("guild.defaultNoti"),"default_message_notifications", - [I18n.getTranslation("guild.onlyMentions"),I18n.getTranslation("guild.all")], - { - defaultIndex:[1,0].indexOf(this.properties.default_message_notifications), - radio:true - },[1,0]); + form.addSelect( + I18n.getTranslation("guild.defaultNoti"), + "default_message_notifications", + [I18n.getTranslation("guild.onlyMentions"), I18n.getTranslation("guild.all")], + { + defaultIndex: [1, 0].indexOf(this.properties.default_message_notifications), + radio: true, + }, + [1, 0], + ); form.addHR(); let region = this.properties.region; - if(!region){ + if (!region) { region = ""; } - form.addTextInput(I18n.getTranslation("guild.region:"), "region", { initText: region }); + form.addTextInput(I18n.getTranslation("guild.region:"), "region", {initText: region}); } - this.makeInviteMenu(settings.addButton(I18n.getTranslation("invite.inviteMaker")),textChannels); + this.makeInviteMenu( + settings.addButton(I18n.getTranslation("invite.inviteMaker")), + textChannels, + ); const s1 = settings.addButton(I18n.getTranslation("guild.roles")); const permlist: [Role, Permissions][] = []; - for(const thing of this.roles){ + for (const thing of this.roles) { permlist.push([thing, thing.permissions]); } - s1.options.push( - new RoleList(permlist, this, this.updateRolePermissions.bind(this),false) - ); + s1.options.push(new RoleList(permlist, this, this.updateRolePermissions.bind(this), false)); { - const emoji=settings.addButton("Emojis"); - emoji.addButtonInput("","Upload Emoji",()=>{ - const popup=new Dialog("Upload emoji"); - const form=popup.options.addForm("",()=>{ - popup.hide(); - },{ - fetchURL:`${this.info.api}/guilds/${this.id}/emojis`, - method:"POST", - headers:this.headers - }); - form.addFileInput("Image:","image",{required:true}); - form.addTextInput("Name:","name",{required:true}); + const emoji = settings.addButton("Emojis"); + emoji.addButtonInput("", "Upload Emoji", () => { + const popup = new Dialog("Upload emoji"); + const form = popup.options.addForm( + "", + () => { + popup.hide(); + }, + { + fetchURL: `${this.info.api}/guilds/${this.id}/emojis`, + method: "POST", + headers: this.headers, + }, + ); + form.addFileInput("Image:", "image", {required: true}); + form.addTextInput("Name:", "name", {required: true}); popup.show(); }); - const containdiv=document.createElement("div"); - const genDiv=()=>{ - containdiv.innerHTML=""; - for(const emoji of this.emojis){ - const div=document.createElement("div"); - div.classList.add("flexltr","emojiOption"); - const emojic=new Emoji(emoji,this); - - const text=document.createElement("input"); - text.type="text"; - text.value=emoji.name; - text.addEventListener("change",()=>{ - fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`,{ - method:"PATCH", - headers:this.headers, - body:JSON.stringify({name:text.value}) - }).then(e=>{if(!e.ok)text.value=emoji.name;})//if not ok, undo + const containdiv = document.createElement("div"); + const genDiv = () => { + containdiv.innerHTML = ""; + for (const emoji of this.emojis) { + const div = document.createElement("div"); + div.classList.add("flexltr", "emojiOption"); + const emojic = new Emoji(emoji, this); + + const text = document.createElement("input"); + text.type = "text"; + text.value = emoji.name; + text.addEventListener("change", () => { + fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`, { + method: "PATCH", + headers: this.headers, + body: JSON.stringify({name: text.value}), + }).then((e) => { + if (!e.ok) text.value = emoji.name; + }); //if not ok, undo }); - const del=document.createElement("span"); - del.classList.add("svgicon", "svg-x","deleteEmoji"); - del.onclick=()=>{ - const diaolog=new Dialog(""); + const del = document.createElement("span"); + del.classList.add("svgicon", "svg-x", "deleteEmoji"); + del.onclick = () => { + const diaolog = new Dialog(""); diaolog.options.addTitle("Are you sure you want to delete this emoji?"); - const options=diaolog.options.addOptions("",{ltr:true}); - options.addButtonInput("",I18n.getTranslation("yes"),()=>{ - fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`,{ - method:"DELETE", - headers:this.headers - }) + const options = diaolog.options.addOptions("", {ltr: true}); + options.addButtonInput("", I18n.getTranslation("yes"), () => { + fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`, { + method: "DELETE", + headers: this.headers, + }); diaolog.hide(); }); - options.addButtonInput("",I18n.getTranslation("no"),()=>{ + options.addButtonInput("", I18n.getTranslation("no"), () => { diaolog.hide(); - }) + }); diaolog.show(); - } - + }; - div.append(emojic.getHTML(true),":",text,":",del); + div.append(emojic.getHTML(true), ":", text, ":", del); containdiv.append(div); } - } - this.onEmojiUpdate=()=>{ - if(!document.body.contains(containdiv)){ - this.onEmojiUpdate=()=>{}; + }; + this.onEmojiUpdate = () => { + if (!document.body.contains(containdiv)) { + this.onEmojiUpdate = () => {}; return; } genDiv(); - } + }; genDiv(); emoji.addHTMLArea(containdiv); } settings.show(); } - makeInviteMenu(options:Options,valid:void|(Channel[])){ - if(!valid){ - valid=this.channels.filter(e=>{ + makeInviteMenu(options: Options, valid: void | Channel[]) { + if (!valid) { + valid = this.channels.filter((e) => { //TODO there are almost certainly more types. is Voice valid? - return new Set([0,5]).has(e.type); + return new Set([0, 5]).has(e.type); }); } - let channel=valid[0]; + let channel = valid[0]; const div = document.createElement("div"); div.classList.add("invitediv"); const text = document.createElement("span"); @@ -270,13 +307,13 @@ class Guild extends SnowFlake{ const copy = document.createElement("span"); copy.classList.add("copybutton", "svgicon", "svg-copy"); copycontainer.append(copy); - copycontainer.onclick = _=>{ - if(text.textContent){ + copycontainer.onclick = (_) => { + if (text.textContent) { navigator.clipboard.writeText(text.textContent); } }; div.append(copycontainer); - const update = ()=>{ + const update = () => { fetch(`${this.info.api}/channels/${channel.id}/invites`, { method: "POST", headers: this.headers, @@ -286,11 +323,11 @@ class Guild extends SnowFlake{ target_user_id: null, max_age: expires + "", max_uses: uses, - temporary: uses !== 0 + temporary: uses !== 0, }), }) - .then(_=>_.json()) - .then(json=>{ + .then((_) => _.json()) + .then((json) => { const params = new URLSearchParams(""); params.set("instance", this.info.wellknown); const encoded = params.toString(); @@ -299,91 +336,102 @@ class Guild extends SnowFlake{ }; options.addTitle(I18n.getTranslation("inviteOptions.title")); - const text2=options.addText(""); - options.addSelect(I18n.getTranslation("invite.channel:"),()=>{},valid.map(e=>e.name)) - .watchForChange((e)=>{ - channel=valid[e]; - text2.setText(I18n.getTranslation("invite.subtext",channel.name,this.properties.name)); - }) - + const text2 = options.addText(""); + options + .addSelect( + I18n.getTranslation("invite.channel:"), + () => {}, + valid.map((e) => e.name), + ) + .watchForChange((e) => { + channel = valid[e]; + text2.setText(I18n.getTranslation("invite.subtext", channel.name, this.properties.name)); + }); - options.addSelect(I18n.getTranslation("invite.expireAfter"),()=>{}, - ["30m","1h","6h","12h","1d","7d","30d","never"].map((e)=>I18n.getTranslation("inviteOptions."+e)) - ).onchange=(e)=>{expires=[1800, 3600, 21600, 43200, 86400, 604800, 2592000, 0][e];}; + options.addSelect( + I18n.getTranslation("invite.expireAfter"), + () => {}, + ["30m", "1h", "6h", "12h", "1d", "7d", "30d", "never"].map((e) => + I18n.getTranslation("inviteOptions." + e), + ), + ).onchange = (e) => { + expires = [1800, 3600, 21600, 43200, 86400, 604800, 2592000, 0][e]; + }; - const timeOptions=["1","5","10","25","50","100"].map((e)=>I18n.getTranslation("inviteOptions.limit",e)) - timeOptions.unshift(I18n.getTranslation("inviteOptions.noLimit")) - options.addSelect(I18n.getTranslation("invite.expireAfter"),()=>{},timeOptions) - .onchange=(e)=>{uses=[0, 1, 5, 10, 25, 50, 100][e];}; + const timeOptions = ["1", "5", "10", "25", "50", "100"].map((e) => + I18n.getTranslation("inviteOptions.limit", e), + ); + timeOptions.unshift(I18n.getTranslation("inviteOptions.noLimit")); + options.addSelect(I18n.getTranslation("invite.expireAfter"), () => {}, timeOptions).onchange = ( + e, + ) => { + uses = [0, 1, 5, 10, 25, 50, 100][e]; + }; - options.addButtonInput("",I18n.getTranslation("invite.createInvite"),()=>{ + options.addButtonInput("", I18n.getTranslation("invite.createInvite"), () => { update(); - }) + }); options.addHTMLArea(div); } - roleUpdate:(role:Role,added:-1|0|1)=>unknown=()=>{}; - sortRoles(){ - this.roles.sort((a,b)=>(b.position-a.position)); + roleUpdate: (role: Role, added: -1 | 0 | 1) => unknown = () => {}; + sortRoles() { + this.roles.sort((a, b) => b.position - a.position); } - async recalcRoles(){ - let position=this.roles.length; - const map=this.roles.map(_=>{ + async recalcRoles() { + let position = this.roles.length; + const map = this.roles.map((_) => { position--; - return {id:_.id,position}; - }) - await fetch(this.info.api+"/guilds/"+this.id+"/roles",{ - method:"PATCH", - body:JSON.stringify(map), - headers:this.headers - }) - } - newRole(rolej:rolesjson){ - const role=new Role(rolej,this); + return {id: _.id, position}; + }); + await fetch(this.info.api + "/guilds/" + this.id + "/roles", { + method: "PATCH", + body: JSON.stringify(map), + headers: this.headers, + }); + } + newRole(rolej: rolesjson) { + const role = new Role(rolej, this); this.roles.push(role); this.roleids.set(role.id, role); this.sortRoles(); - this.roleUpdate(role,1); + this.roleUpdate(role, 1); } - updateRole(rolej:rolesjson){ - const role=this.roleids.get(rolej.id) as Role; + updateRole(rolej: rolesjson) { + const role = this.roleids.get(rolej.id) as Role; role.newJson(rolej); - this.roleUpdate(role,0); + this.roleUpdate(role, 0); } - memberupdate(json:memberjson){ - let member:undefined|Member=undefined; - for(const thing of this.members){ - if(thing.id===json.id){ - member=thing; + memberupdate(json: memberjson) { + let member: undefined | Member = undefined; + for (const thing of this.members) { + if (thing.id === json.id) { + member = thing; break; } } - if(!member) return; + if (!member) return; member.update(json); - if(member===this.member){ + if (member === this.member) { console.log(member); this.loadGuild(); } } - deleteRole(id:string){ + deleteRole(id: string) { const role = this.roleids.get(id); - if(!role) return; + if (!role) return; this.roleids.delete(id); - this.roles.splice(this.roles.indexOf(role),1); - this.roleUpdate(role,-1); - } - onEmojiUpdate=(_:emojipjson[])=>{}; - constructor( - json: guildjson | -1, - owner: Localuser, - member: memberjson | User | null - ){ - if(json === -1 || member === null){ + this.roles.splice(this.roles.indexOf(role), 1); + this.roleUpdate(role, -1); + } + onEmojiUpdate = (_: emojipjson[]) => {}; + constructor(json: guildjson | -1, owner: Localuser, member: memberjson | User | null) { + if (json === -1 || member === null) { super("@me"); return; } - if(json.stickers.length){ + if (json.stickers.length) { console.log(json.stickers, ":3"); } super(json.id); @@ -398,52 +446,57 @@ class Guild extends SnowFlake{ this.roleids = new Map(); this.message_notifications = 0; - for(const roley of json.roles){ + for (const roley of json.roles) { const roleh = new Role(roley, this); this.roles.push(roleh); this.roleids.set(roleh.id, roleh); } this.sortRoles(); - if(member instanceof User){ + if (member instanceof User) { console.warn(member); - Member.resolveMember(member, this).then(_=>{ - if(_){ + Member.resolveMember(member, this).then((_) => { + if (_) { this.member = _; - }else{ + } else { console.error("Member was unable to resolve"); } }); - }else{ - Member.new(member, this).then(_=>{ - if(_){ + } else { + Member.new(member, this).then((_) => { + if (_) { this.member = _; } }); } - this.perminfo ??= { channels: {} }; - for(const thing of json.channels){ + this.perminfo ??= {channels: {}}; + for (const thing of json.channels) { const temp = new Channel(thing, this); this.channels.push(temp); this.localuser.channelids.set(temp.id, temp); } this.headchannels = []; - for(const thing of this.channels){ + for (const thing of this.channels) { const parent = thing.resolveparent(this); - if(!parent){ + if (!parent) { this.headchannels.push(thing); } } this.prevchannel = this.localuser.channelids.get(this.perminfo.prevchannel); } - get perminfo(){ + get perminfo() { return this.localuser.perminfo.guilds[this.id]; } - set perminfo(e){ + set perminfo(e) { this.localuser.perminfo.guilds[this.id] = e; } notisetting(settings: { - channel_overrides: {message_notifications: number,muted: boolean,mute_config: {selected_time_window: number,end_time: number},channel_id: string}[]; + channel_overrides: { + message_notifications: number; + muted: boolean; + mute_config: {selected_time_window: number; end_time: number}; + channel_id: string; + }[]; message_notifications: any; flags?: number; hide_muted_channels?: boolean; @@ -456,103 +509,112 @@ class Guild extends SnowFlake{ suppress_roles?: boolean; version?: number; guild_id?: string; - }){ + }) { this.message_notifications = settings.message_notifications; - for(const override of settings.channel_overrides){ - const channel=this.localuser.channelids.get(override.channel_id); - if(!channel) continue; + for (const override of settings.channel_overrides) { + const channel = this.localuser.channelids.get(override.channel_id); + if (!channel) continue; channel.handleUserOverrides(override); } } - setnotifcation(){ - - const options=["all", "onlyMentions", "none"].map(e=>I18n.getTranslation("guild."+e)); - const notiselect=new Dialog(""); - const form=notiselect.options.addForm("",(_,sent:any)=>{ - notiselect.hide(); - this.message_notifications = sent.message_notifications; - },{ - fetchURL:`${this.info.api}/users/@me/guilds/${this.id}/settings/`, - method:"PATCH", - headers:this.headers - }); - form.addSelect(I18n.getTranslation("guild.selectnoti"),"message_notifications",options,{ - radio:true, - defaultIndex:this.message_notifications - },[0,1,2]); + setnotifcation() { + const options = ["all", "onlyMentions", "none"].map((e) => I18n.getTranslation("guild." + e)); + const notiselect = new Dialog(""); + const form = notiselect.options.addForm( + "", + (_, sent: any) => { + notiselect.hide(); + this.message_notifications = sent.message_notifications; + }, + { + fetchURL: `${this.info.api}/users/@me/guilds/${this.id}/settings/`, + method: "PATCH", + headers: this.headers, + }, + ); + form.addSelect( + I18n.getTranslation("guild.selectnoti"), + "message_notifications", + options, + { + radio: true, + defaultIndex: this.message_notifications, + }, + [0, 1, 2], + ); notiselect.show(); } - confirmleave(){ + confirmleave() { const full = new Dialog(""); - full.options.addTitle(I18n.getTranslation("guild.confirmLeave")) - const options=full.options.addOptions("",{ltr:true}); - options.addButtonInput("",I18n.getTranslation("guild.yesLeave"),()=>{ - this.leave().then(_=>{ + full.options.addTitle(I18n.getTranslation("guild.confirmLeave")); + const options = full.options.addOptions("", {ltr: true}); + options.addButtonInput("", I18n.getTranslation("guild.yesLeave"), () => { + this.leave().then((_) => { full.hide(); }); }); - options.addButtonInput("",I18n.getTranslation("guild.noLeave"),()=>{ + options.addButtonInput("", I18n.getTranslation("guild.noLeave"), () => { full.hide(); }); full.show(); } - async leave(){ + async leave() { return fetch(this.info.api + "/users/@me/guilds/" + this.id, { method: "DELETE", headers: this.headers, }); } - printServers(){ + printServers() { let build = ""; - for(const thing of this.headchannels){ + for (const thing of this.headchannels) { build += thing.name + ":" + thing.position + "\n"; - for(const thingy of thing.children){ + for (const thingy of thing.children) { build += " " + thingy.name + ":" + thingy.position + "\n"; } } console.log(build); } - calculateReorder(){ + calculateReorder() { let position = -1; const build: { id: string; position: number | undefined; parent_id: string | undefined; }[] = []; - for(const thing of this.headchannels){ + for (const thing of this.headchannels) { const thisthing: { - id: string; - position: number | undefined; - parent_id: string | undefined; - } = { id: thing.id, position: undefined, parent_id: undefined }; - if(thing.position <= position){ + id: string; + position: number | undefined; + parent_id: string | undefined; + } = {id: thing.id, position: undefined, parent_id: undefined}; + if (thing.position <= position) { thing.position = thisthing.position = position + 1; } position = thing.position; console.log(position); - if(thing.move_id && thing.move_id !== thing.parent_id){ + if (thing.move_id && thing.move_id !== thing.parent_id) { thing.parent_id = thing.move_id; thisthing.parent_id = thing.parent?.id; thing.move_id = undefined; } - if(thisthing.position || thisthing.parent_id){ + if (thisthing.position || thisthing.parent_id) { build.push(thisthing); } - if(thing.children.length > 0){ + if (thing.children.length > 0) { const things = thing.calculateReorder(); - for(const thing of things){ + for (const thing of things) { build.push(thing); } } } console.log(build); this.printServers(); - if(build.length === 0){ + if (build.length === 0) { return; } const serverbug = false; - if(serverbug){ - for(const thing of build){ + if (serverbug) { + for (const thing of build) { console.log(build, thing); fetch(this.info.api + "/guilds/" + this.id + "/channels", { method: "PATCH", @@ -560,7 +622,7 @@ class Guild extends SnowFlake{ body: JSON.stringify([thing]), }); } - }else{ + } else { fetch(this.info.api + "/guilds/" + this.id + "/channels", { method: "PATCH", headers: this.headers, @@ -568,174 +630,175 @@ class Guild extends SnowFlake{ }); } } - get localuser(){ + get localuser() { return this.owner; } - get info(){ + get info() { return this.owner.info; } - sortchannels(){ - this.headchannels.sort((a, b)=>{ + sortchannels() { + this.headchannels.sort((a, b) => { return a.position - b.position; }); } - static generateGuildIcon(guild: Guild | (invitejson["guild"] & { info: { cdn: string } })){ + static generateGuildIcon(guild: Guild | (invitejson["guild"] & {info: {cdn: string}})) { const divy = document.createElement("div"); divy.classList.add("servernoti"); const noti = document.createElement("div"); noti.classList.add("unread"); divy.append(noti); - if(guild instanceof Guild){ + if (guild instanceof Guild) { guild.localuser.guildhtml.set(guild.id, divy); - guild.html=divy; + guild.html = divy; } let icon: string | null; - if(guild instanceof Guild){ + if (guild instanceof Guild) { icon = guild.properties.icon; - }else{ + } else { icon = guild.icon; } - if(icon !== null){ + if (icon !== null) { const img = document.createElement("img"); img.classList.add("pfp", "servericon"); img.src = guild.info.cdn + "/icons/" + guild.id + "/" + icon + ".png"; divy.appendChild(img); - if(guild instanceof Guild){ - img.onclick = ()=>{ + if (guild instanceof Guild) { + img.onclick = () => { console.log(guild.loadGuild); guild.loadGuild(); guild.loadChannel(); }; - Guild.contextmenu.bindContextmenu(img, guild,undefined); + Guild.contextmenu.bindContextmenu(img, guild, undefined); } - }else{ + } else { const div = document.createElement("div"); let name: string; - if(guild instanceof Guild){ + if (guild instanceof Guild) { name = guild.properties.name; - }else{ + } else { name = guild.name; } const build = name .replace(/'s /g, " ") - .replace(/\w+/g, word=>word[0]) + .replace(/\w+/g, (word) => word[0]) .replace(/\s/g, ""); div.textContent = build; div.classList.add("blankserver", "servericon"); divy.appendChild(div); - if(guild instanceof Guild){ - div.onclick = ()=>{ + if (guild instanceof Guild) { + div.onclick = () => { guild.loadGuild(); guild.loadChannel(); }; - Guild.contextmenu.bindContextmenu(div, guild,undefined); + Guild.contextmenu.bindContextmenu(div, guild, undefined); } } return divy; } - generateGuildIcon(){ + generateGuildIcon() { return Guild.generateGuildIcon(this); } - confirmDelete(){ + confirmDelete() { let confirmname = ""; const full = new Dialog(""); - full.options.addTitle(I18n.getTranslation("guild.confirmDelete",this.properties.name)); - full.options.addTextInput(I18n.getTranslation("guild.serverName"),()=>{}).onchange=(e)=>confirmname=e; + full.options.addTitle(I18n.getTranslation("guild.confirmDelete", this.properties.name)); + full.options.addTextInput(I18n.getTranslation("guild.serverName"), () => {}).onchange = (e) => + (confirmname = e); - const options=full.options.addOptions("",{ltr:true}); - options.addButtonInput("",I18n.getTranslation("guild.yesDelete"),()=>{ - if(confirmname !== this.properties.name){ + const options = full.options.addOptions("", {ltr: true}); + options.addButtonInput("", I18n.getTranslation("guild.yesDelete"), () => { + if (confirmname !== this.properties.name) { //TODO maybe some sort of form error? idk alert("names don't match"); return; } - this.delete().then(_=>{ + this.delete().then((_) => { full.hide(); }); }); - options.addButtonInput("",I18n.getTranslation("guild.noDelete"),()=>{ + options.addButtonInput("", I18n.getTranslation("guild.noDelete"), () => { full.hide(); }); full.show(); } - async delete(){ + async delete() { return fetch(this.info.api + "/guilds/" + this.id + "/delete", { method: "POST", headers: this.headers, }); } - get mentions(){ - let mentions=0; - for(const thing of this.channels){ - mentions+=thing.mentions; + get mentions() { + let mentions = 0; + for (const thing of this.channels) { + mentions += thing.mentions; } return mentions; } - unreads(html?: HTMLElement | undefined){ - if(html){ + unreads(html?: HTMLElement | undefined) { + if (html) { this.html = html; - }else{ + } else { html = this.html; } - if(!html){ + if (!html) { return; } let read = true; - let mentions=this.mentions; - for(const thing of this.channels){ - if(thing.hasunreads){ + let mentions = this.mentions; + for (const thing of this.channels) { + if (thing.hasunreads) { read = false; break; } } - const noti=html.children[0]; - if(mentions!==0){ + const noti = html.children[0]; + if (mentions !== 0) { noti.classList.add("pinged"); - noti.textContent=""+mentions; - }else{ - noti.textContent=""; + noti.textContent = "" + mentions; + } else { + noti.textContent = ""; noti.classList.remove("pinged"); } - if(read){ + if (read) { noti.classList.remove("notiunread"); - }else{ + } else { noti.classList.add("notiunread"); } } - getHTML(){ + getHTML() { //this.printServers(); this.sortchannels(); this.printServers(); const build = document.createElement("div"); - for(const thing of this.headchannels){ + for (const thing of this.headchannels) { build.appendChild(thing.createguildHTML(this.isAdmin())); } return build; } - isAdmin(){ + isAdmin() { return this.member.isAdmin(); } - async markAsRead(){ + async markAsRead() { const build: { - read_states: { - channel_id: string; - message_id: string | null | undefined; - read_state_type: number; - }[]; - } = { read_states: [] }; - for(const thing of this.channels){ - if(thing.hasunreads){ + read_states: { + channel_id: string; + message_id: string | null | undefined; + read_state_type: number; + }[]; + } = {read_states: []}; + for (const thing of this.channels) { + if (thing.hasunreads) { build.read_states.push({ channel_id: thing.id, message_id: thing.lastmessageid, read_state_type: 0, }); thing.lastreadmessageid = thing.lastmessageid; - if(!thing.myhtml)continue; + if (!thing.myhtml) continue; thing.myhtml.classList.remove("cunread"); } } @@ -746,29 +809,29 @@ class Guild extends SnowFlake{ body: JSON.stringify(build), }); } - hasRole(r: Role | string){ + hasRole(r: Role | string) { console.log("this should run"); - if(r instanceof Role){ + if (r instanceof Role) { r = r.id; } return this.member.hasRole(r); } - loadChannel(ID?: string | undefined| null,addstate=true){ - if(ID){ + loadChannel(ID?: string | undefined | null, addstate = true) { + if (ID) { const channel = this.localuser.channelids.get(ID); - if(channel){ + if (channel) { channel.getHTML(addstate); return; } } - if(this.prevchannel&&ID!==null){ + if (this.prevchannel && ID !== null) { console.log(this.prevchannel); this.prevchannel.getHTML(addstate); return; } - if(this.id!=="@me"){ - for(const thing of this.channels){ - if(thing.type!==4){ + if (this.id !== "@me") { + for (const thing of this.channels) { + if (thing.type !== 4) { thing.getHTML(addstate); return; } @@ -777,14 +840,14 @@ class Guild extends SnowFlake{ this.removePrevChannel(); this.noChannel(addstate); } - removePrevChannel(){ - if(this.localuser.channelfocus){ + removePrevChannel() { + if (this.localuser.channelfocus) { this.localuser.channelfocus.infinite.delete(); } - if(this !== this.localuser.lookingguild){ + if (this !== this.localuser.lookingguild) { this.loadGuild(); } - if(this.localuser.channelfocus && this.localuser.channelfocus.myhtml){ + if (this.localuser.channelfocus && this.localuser.channelfocus.myhtml) { this.localuser.channelfocus.myhtml.classList.remove("viewChannel"); } this.prevchannel = undefined; @@ -793,14 +856,14 @@ class Guild extends SnowFlake{ const typebox = document.getElementById("typebox") as HTMLElement; replybox.classList.add("hideReplyBox"); typebox.classList.remove("typeboxreplying"); - (document.getElementById("typebox") as HTMLDivElement).contentEditable ="false"; - (document.getElementById("upload") as HTMLElement).style.visibility="hidden"; - (document.getElementById("typediv") as HTMLElement).style.visibility="hidden"; - (document.getElementById("sideDiv") as HTMLElement).innerHTML=""; + (document.getElementById("typebox") as HTMLDivElement).contentEditable = "false"; + (document.getElementById("upload") as HTMLElement).style.visibility = "hidden"; + (document.getElementById("typediv") as HTMLElement).style.visibility = "hidden"; + (document.getElementById("sideDiv") as HTMLElement).innerHTML = ""; } - noChannel(addstate:boolean){ - if(addstate){ - history.pushState([this.id,undefined], "", "/channels/" + this.id); + noChannel(addstate: boolean) { + if (addstate) { + history.pushState([this.id, undefined], "", "/channels/" + this.id); } this.localuser.pageTitle(I18n.getTranslation("guild.emptytitle")); const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement; @@ -811,82 +874,90 @@ class Guild extends SnowFlake{ this.localuser.getSidePannel(); const messages = document.getElementById("channelw") as HTMLDivElement; - for(const thing of Array.from(messages.getElementsByClassName("messagecontainer"))){ + for (const thing of Array.from(messages.getElementsByClassName("messagecontainer"))) { thing.remove(); } - const h1=document.createElement("h1"); - h1.classList.add("messagecontainer") - h1.textContent=I18n.getTranslation("guild.emptytext"); + const h1 = document.createElement("h1"); + h1.classList.add("messagecontainer"); + h1.textContent = I18n.getTranslation("guild.emptytext"); messages.append(h1); } - loadGuild(){ + loadGuild() { this.localuser.loadGuild(this.id); } - updateChannel(json: channeljson){ + updateChannel(json: channeljson) { const channel = this.localuser.channelids.get(json.id); - if(channel){ + if (channel) { channel.updateChannel(json); this.headchannels = []; - for(const thing of this.channels){ + for (const thing of this.channels) { thing.children = []; } this.headchannels = []; - for(const thing of this.channels){ + for (const thing of this.channels) { const parent = thing.resolveparent(this); - if(!parent){ + if (!parent) { this.headchannels.push(thing); } } this.printServers(); } } - createChannelpac(json: channeljson){ + createChannelpac(json: channeljson) { const thischannel = new Channel(json, this); this.localuser.channelids.set(json.id, thischannel); this.channels.push(thischannel); thischannel.resolveparent(this); - if(!thischannel.parent){ + if (!thischannel.parent) { this.headchannels.push(thischannel); } this.calculateReorder(); this.printServers(); return thischannel; } - createchannels(func = this.createChannel){ - const options=["text", "announcement","voice"].map(e=>I18n.getTranslation("channel."+e)); + createchannels(func = this.createChannel) { + const options = ["text", "announcement", "voice"].map((e) => + I18n.getTranslation("channel." + e), + ); - const channelselect=new Dialog(""); - const form=channelselect.options.addForm("",(e:any)=>{ - func(e.name,e.type); + const channelselect = new Dialog(""); + const form = channelselect.options.addForm("", (e: any) => { + func(e.name, e.type); channelselect.hide(); }); - form.addSelect(I18n.getTranslation("channel.selectType"),"type",options,{radio:true},[0,5,2]); - form.addTextInput(I18n.getTranslation("channel.selectName"),"name"); + form.addSelect( + I18n.getTranslation("channel.selectType"), + "type", + options, + {radio: true}, + [0, 5, 2], + ); + form.addTextInput(I18n.getTranslation("channel.selectName"), "name"); channelselect.show(); } - createcategory(){ + createcategory() { const category = 4; - const channelselect=new Dialog(""); - const options=channelselect.options; - const form=options.addForm("",(e:any)=>{ + const channelselect = new Dialog(""); + const options = channelselect.options; + const form = options.addForm("", (e: any) => { this.createChannel(e.name, category); channelselect.hide(); }); - form.addTextInput(I18n.getTranslation("channel.selectCatName"),"name"); + form.addTextInput(I18n.getTranslation("channel.selectCatName"), "name"); channelselect.show(); } - delChannel(json: channeljson){ + delChannel(json: channeljson) { const channel = this.localuser.channelids.get(json.id); this.localuser.channelids.delete(json.id); - if(!channel)return; + if (!channel) return; this.channels.splice(this.channels.indexOf(channel), 1); const indexy = this.headchannels.indexOf(channel); - if(indexy !== -1){ + if (indexy !== -1) { this.headchannels.splice(indexy, 1); } - if(channel===this.prevchannel){ - this.prevchannel=undefined; + if (channel === this.prevchannel) { + this.prevchannel = undefined; } /* const build=[]; @@ -905,35 +976,32 @@ class Guild extends SnowFlake{ */ this.printServers(); } - createChannel(name: string, type: number){ + createChannel(name: string, type: number) { fetch(this.info.api + "/guilds/" + this.id + "/channels", { method: "POST", headers: this.headers, - body: JSON.stringify({ name, type }), + body: JSON.stringify({name, type}), }); } - async createRole(name: string){ - const fetched = await fetch( - this.info.api + "/guilds/" + this.id + "roles", - { - method: "POST", - headers: this.headers, - body: JSON.stringify({ - name, - color: 0, - permissions: "0", - }), - } - ); + async createRole(name: string) { + const fetched = await fetch(this.info.api + "/guilds/" + this.id + "roles", { + method: "POST", + headers: this.headers, + body: JSON.stringify({ + name, + color: 0, + permissions: "0", + }), + }); const json = await fetched.json(); const role = new Role(json, this); this.roleids.set(role.id, role); this.roles.push(role); return role; } - async updateRolePermissions(id: string, perms: Permissions){ + async updateRolePermissions(id: string, perms: Permissions) { const role = this.roleids.get(id); - if(!role){ + if (!role) { return; } role.permissions.allow = perms.allow; @@ -955,4 +1023,4 @@ class Guild extends SnowFlake{ } } Guild.setupcontextmenu(); -export{ Guild }; +export {Guild}; diff --git a/src/webpage/home.html b/src/webpage/home.html index 34347044..c1aa873e 100644 --- a/src/webpage/home.html +++ b/src/webpage/home.html @@ -1,39 +1,44 @@ - + - - - + + Jank Client - - - - - - - + + + + + + + - +
-

Welcome to Jank Client

-

Jank Client is a Spacebar-compatible client seeking to be as good as it can be with many features including:

+

+ Jank Client is a Spacebar-compatible client seeking to be as good as it can be with many + features including: +

  • Direct Messaging
  • Reactions support
  • @@ -47,18 +52,18 @@

    Welcome to Jank Client

Spacebar-Compatible Instances:

-
-
+

Contribute to Jank Client

-

We always appreciate some help, whether that be in the form of bug reports, code, help translate, or even just pointing out some typos.


- - Github - +

+ We always appreciate some help, whether that be in the form of bug reports, code, help + translate, or even just pointing out some typos. +

+
+ Github
- diff --git a/src/webpage/home.ts b/src/webpage/home.ts index 20cac876..7be581b7 100644 --- a/src/webpage/home.ts +++ b/src/webpage/home.ts @@ -1,40 +1,56 @@ -import { I18n } from "./i18n.js"; -import{ mobile }from"./utils/utils.js"; +import {I18n} from "./i18n.js"; +import {mobile} from "./utils/utils.js"; console.log(mobile); const serverbox = document.getElementById("instancebox") as HTMLDivElement; -(async ()=>{ +(async () => { await I18n.done; - const openClient=document.getElementById("openClient") - const welcomeJank=document.getElementById("welcomeJank") - const box1title=document.getElementById("box1title") - const box1Items=document.getElementById("box1Items") - const compatableInstances=document.getElementById("compatableInstances") - const box3title=document.getElementById("box3title") - const box3description=document.getElementById("box3description") - if(openClient&&welcomeJank&&compatableInstances&&box3title&&box3description&&box1title&&box1Items){ - openClient.textContent=I18n.getTranslation("htmlPages.openClient"); - welcomeJank.textContent=I18n.getTranslation("htmlPages.welcomeJank"); - box1title.textContent=I18n.getTranslation("htmlPages.box1title"); + const openClient = document.getElementById("openClient"); + const welcomeJank = document.getElementById("welcomeJank"); + const box1title = document.getElementById("box1title"); + const box1Items = document.getElementById("box1Items"); + const compatableInstances = document.getElementById("compatableInstances"); + const box3title = document.getElementById("box3title"); + const box3description = document.getElementById("box3description"); + if ( + openClient && + welcomeJank && + compatableInstances && + box3title && + box3description && + box1title && + box1Items + ) { + openClient.textContent = I18n.getTranslation("htmlPages.openClient"); + welcomeJank.textContent = I18n.getTranslation("htmlPages.welcomeJank"); + box1title.textContent = I18n.getTranslation("htmlPages.box1title"); - compatableInstances.textContent=I18n.getTranslation("htmlPages.compatableInstances"); - box3title.textContent=I18n.getTranslation("htmlPages.box3title"); - box3description.textContent=I18n.getTranslation("htmlPages.box3description"); + compatableInstances.textContent = I18n.getTranslation("htmlPages.compatableInstances"); + box3title.textContent = I18n.getTranslation("htmlPages.box3title"); + box3description.textContent = I18n.getTranslation("htmlPages.box3description"); - const items=I18n.getTranslation("htmlPages.box1Items").split("|"); - let i=0; + const items = I18n.getTranslation("htmlPages.box1Items").split("|"); + let i = 0; //@ts-ignore ts is being dumb here - for(const item of box1Items.children){ - (item as HTMLElement).textContent=items[i]; + for (const item of box1Items.children) { + (item as HTMLElement).textContent = items[i]; i++; } - }else{ - console.error(openClient,welcomeJank,compatableInstances,box3title,box3description,box1title,box1Items) + } else { + console.error( + openClient, + welcomeJank, + compatableInstances, + box3title, + box3description, + box1title, + box1Items, + ); } -})() +})(); fetch("/instances.json") - .then(_=>_.json()) + .then((_) => _.json()) .then( async ( json: { @@ -45,76 +61,77 @@ fetch("/instances.json") url?: string; display?: boolean; online?: boolean; - uptime: { alltime: number; daytime: number; weektime: number }; + uptime: {alltime: number; daytime: number; weektime: number}; urls: { - wellknown: string; - api: string; - cdn: string; - gateway: string; - login?: string; + wellknown: string; + api: string; + cdn: string; + gateway: string; + login?: string; }; - }[] - )=>{ + }[], + ) => { await I18n.done; console.warn(json); - for(const instance of json){ - if(instance.display === false){ + for (const instance of json) { + if (instance.display === false) { continue; } const div = document.createElement("div"); div.classList.add("flexltr", "instance"); - if(instance.image){ + if (instance.image) { const img = document.createElement("img"); img.src = instance.image; div.append(img); } const statbox = document.createElement("div"); - statbox.classList.add("flexttb","flexgrow"); + statbox.classList.add("flexttb", "flexgrow"); { const textbox = document.createElement("div"); textbox.classList.add("flexttb", "instancetextbox"); const title = document.createElement("h2"); title.innerText = instance.name; - if(instance.online !== undefined){ + 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){ + if (instance.description || instance.descriptionLong) { const p = document.createElement("p"); - if(instance.descriptionLong){ + if (instance.descriptionLong) { p.innerText = instance.descriptionLong; - }else if(instance.description){ + } else if (instance.description) { p.innerText = instance.description; } textbox.append(p); } statbox.append(textbox); } - if(instance.uptime){ + if (instance.uptime) { const stats = document.createElement("div"); stats.classList.add("flexltr"); const span = document.createElement("span"); - span.innerText = I18n.getTranslation("home.uptimeStats",Math.round( - instance.uptime.alltime * 100 - )+"",Math.round( - instance.uptime.weektime * 100 - )+"",Math.round(instance.uptime.daytime * 100)+"") + span.innerText = I18n.getTranslation( + "home.uptimeStats", + Math.round(instance.uptime.alltime * 100) + "", + Math.round(instance.uptime.weektime * 100) + "", + Math.round(instance.uptime.daytime * 100) + "", + ); stats.append(span); statbox.append(stats); } div.append(statbox); - div.onclick = _=>{ - if(instance.online){ + div.onclick = (_) => { + if (instance.online) { window.location.href = "/register.html?instance=" + encodeURI(instance.name); - }else{ + } else { alert(I18n.getTranslation("home.warnOffiline")); } }; serverbox.append(div); } - } + }, ); diff --git a/src/webpage/hover.ts b/src/webpage/hover.ts index aa02bbd1..30f53a62 100644 --- a/src/webpage/hover.ts +++ b/src/webpage/hover.ts @@ -1,57 +1,58 @@ -import { Contextmenu } from "./contextmenu.js"; -import { MarkDown } from "./markdown.js"; +import {Contextmenu} from "./contextmenu.js"; +import {MarkDown} from "./markdown.js"; -class Hover{ - str:string|MarkDown|(()=>Promise|MarkDown|string); - constructor(txt:string|MarkDown|(()=>Promise|MarkDown|string)){ - this.str=txt; - } - addEvent(elm:HTMLElement){ - let timeOut=setTimeout(()=>{},0); - let elm2=document.createElement("div"); - elm.addEventListener("mouseover",()=>{ - timeOut=setTimeout(async ()=>{ - elm2=await this.makeHover(elm); - },750) - }); - elm.addEventListener("mouseout",()=>{ - clearTimeout(timeOut); - elm2.remove(); - }); - new MutationObserver(function (e) { - if (e[0].removedNodes) { - clearTimeout(timeOut); - elm2.remove(); - }; - }).observe(elm,{ childList: true }); - } - async makeHover(elm:HTMLElement){ - if(!document.contains(elm)) return document.createDocumentFragment() as unknown as HTMLDivElement; - const div=document.createElement("div"); - if(this.str instanceof MarkDown){ - div.append(this.str.makeHTML()) - }else if(this.str instanceof Function){ - const hover=await this.str(); - if(hover instanceof MarkDown){ - div.append(hover.makeHTML()); - }else{ - div.innerText=hover; - } - }else{ - div.innerText=this.str; - } - const box=elm.getBoundingClientRect(); - div.style.top=(box.bottom+4)+"px"; - div.style.left=Math.floor(box.left+box.width/2)+"px"; - div.classList.add("hoverthing"); - div.style.opacity="0"; - setTimeout(()=>{ - div.style.opacity="1"; - },10) - document.body.append(div); - Contextmenu.keepOnScreen(div); - console.log(div,elm); - return div; - } +class Hover { + str: string | MarkDown | (() => Promise | MarkDown | string); + constructor(txt: string | MarkDown | (() => Promise | MarkDown | string)) { + this.str = txt; + } + addEvent(elm: HTMLElement) { + let timeOut = setTimeout(() => {}, 0); + let elm2 = document.createElement("div"); + elm.addEventListener("mouseover", () => { + timeOut = setTimeout(async () => { + elm2 = await this.makeHover(elm); + }, 750); + }); + elm.addEventListener("mouseout", () => { + clearTimeout(timeOut); + elm2.remove(); + }); + new MutationObserver(function (e) { + if (e[0].removedNodes) { + clearTimeout(timeOut); + elm2.remove(); + } + }).observe(elm, {childList: true}); + } + async makeHover(elm: HTMLElement) { + if (!document.contains(elm)) + return document.createDocumentFragment() as unknown as HTMLDivElement; + const div = document.createElement("div"); + if (this.str instanceof MarkDown) { + div.append(this.str.makeHTML()); + } else if (this.str instanceof Function) { + const hover = await this.str(); + if (hover instanceof MarkDown) { + div.append(hover.makeHTML()); + } else { + div.innerText = hover; + } + } else { + div.innerText = this.str; + } + const box = elm.getBoundingClientRect(); + div.style.top = box.bottom + 4 + "px"; + div.style.left = Math.floor(box.left + box.width / 2) + "px"; + div.classList.add("hoverthing"); + div.style.opacity = "0"; + setTimeout(() => { + div.style.opacity = "1"; + }, 10); + document.body.append(div); + Contextmenu.keepOnScreen(div); + console.log(div, elm); + return div; + } } -export{Hover} +export {Hover}; diff --git a/src/webpage/i18n.ts b/src/webpage/i18n.ts index 742ba328..8ae5f204 100644 --- a/src/webpage/i18n.ts +++ b/src/webpage/i18n.ts @@ -1,122 +1,118 @@ //@ts-ignore import {langs} from "./translations/langs.js"; -const langmap=new Map(); -for(const lang of Object.keys(langs) as string[]){ - langmap.set(lang,langs[lang]); +const langmap = new Map(); +for (const lang of Object.keys(langs) as string[]) { + langmap.set(lang, langs[lang]); } console.log(langs); -type translation={ - [key:string]:string|translation +type translation = { + [key: string]: string | translation; }; -let res:()=>unknown=()=>{}; -class I18n{ - static lang:string; - static translations:translation[]=[]; - static done=new Promise((res2,_reject)=>{ - res=res2; - }); - static async create(lang:string){ +let res: () => unknown = () => {}; +class I18n { + static lang: string; + static translations: translation[] = []; + static done = new Promise((res2, _reject) => { + res = res2; + }); + static async create(lang: string) { + const json = (await (await fetch("/translations/" + lang + ".json")).json()) as translation; + const translations: translation[] = []; + translations.push(json); + if (lang !== "en") { + translations.push((await (await fetch("/translations/en.json")).json()) as translation); + } + this.lang = lang; + this.translations = translations; - const json=await (await fetch("/translations/"+lang+".json")).json() as translation; - const translations:translation[]=[]; - translations.push(json); - if(lang!=="en"){ - translations.push(await (await fetch("/translations/en.json")).json() as translation); - } - this.lang=lang; - this.translations=translations; + res(); + } + static getTranslation(msg: string, ...params: string[]): string { + let str: string | undefined; + const path = msg.split("."); + for (const json of this.translations) { + let jsont: string | translation = json; + for (const thing of path) { + if (typeof jsont !== "string" && jsont !== undefined) { + jsont = jsont[thing]; + } else { + jsont = json; + break; + } + } - res(); - } - static getTranslation(msg:string,...params:string[]):string{ - let str:string|undefined; - const path=msg.split("."); - for(const json of this.translations){ - let jsont:string|translation=json; - for(const thing of path){ - if(typeof jsont !== "string" && jsont!==undefined){ - jsont=jsont[thing]; + if (typeof jsont === "string") { + str = jsont; + break; + } + } + if (str) { + return this.fillInBlanks(str, params); + } else { + throw new Error(msg + " not found"); + } + } + static fillInBlanks(msg: string, params: string[]): string { + //thanks to geotale for the regex + msg = msg.replace(/\$\d+/g, (match) => { + const number = Number(match.slice(1)); + if (params[number - 1]) { + return params[number - 1]; + } else { + return match; + } + }); + msg = msg.replace(/{{(.+?)}}/g, (str, match: string) => { + const [op, strsSplit] = this.fillInBlanks(match, params).split(":"); + const [first, ...strs] = strsSplit.split("|"); + switch (op.toUpperCase()) { + case "PLURAL": { + const numb = Number(first); + if (numb === 0) { + return strs[strs.length - 1]; + } + return strs[Math.min(strs.length - 1, numb - 1)]; + } + case "GENDER": { + if (first === "male") { + return strs[0]; + } else if (first === "female") { + return strs[1]; + } else if (first === "neutral") { + if (strs[2]) { + return strs[2]; + } else { + return strs[0]; + } + } + } + } + return str; + }); - }else{ - jsont=json; - break; - } - } - - if(typeof jsont === "string"){ - str=jsont; - break; - } - } - if(str){ - return this.fillInBlanks(str,params); - }else{ - throw new Error(msg+" not found") - } - } - static fillInBlanks(msg:string,params:string[]):string{ - //thanks to geotale for the regex - msg=msg.replace(/\$\d+/g,(match) => { - const number=Number(match.slice(1)); - if(params[number-1]){ - return params[number-1]; - }else{ - return match; - } - }); - msg=msg.replace(/{{(.+?)}}/g, - (str, match:string) => { - const [op,strsSplit]=this.fillInBlanks(match,params).split(":"); - const [first,...strs]=strsSplit.split("|"); - switch(op.toUpperCase()){ - case "PLURAL":{ - const numb=Number(first); - if(numb===0){ - return strs[strs.length-1]; - } - return strs[Math.min(strs.length-1,numb-1)]; - } - case "GENDER":{ - if(first==="male"){ - return strs[0]; - }else if(first==="female"){ - return strs[1]; - }else if(first==="neutral"){ - if(strs[2]){ - return strs[2]; - }else{ - return strs[0]; - } - } - } - } - return str; - } - ); - - return msg; - } - static options(){ - return [...langmap.keys()].map(e=>e.replace(".json","")); - } - static setLanguage(lang:string){ - if(this.options().indexOf(userLocale)!==-1){ - localStorage.setItem("lang",lang); - I18n.create(lang); - } - } + return msg; + } + static options() { + return [...langmap.keys()].map((e) => e.replace(".json", "")); + } + static setLanguage(lang: string) { + if (this.options().indexOf(userLocale) !== -1) { + localStorage.setItem("lang", lang); + I18n.create(lang); + } + } } console.log(langmap); -let userLocale = navigator.language.slice(0,2) || "en"; -if(I18n.options().indexOf(userLocale)===-1){ - userLocale="en"; +let userLocale = navigator.language.slice(0, 2) || "en"; +if (I18n.options().indexOf(userLocale) === -1) { + userLocale = "en"; } -const storage=localStorage.getItem("lang"); -if(storage){ - userLocale=storage; -}else{ - localStorage.setItem("lang",userLocale) +const storage = localStorage.getItem("lang"); +if (storage) { + userLocale = storage; +} else { + localStorage.setItem("lang", userLocale); } I18n.create(userLocale); -export{I18n,langmap}; +export {I18n, langmap}; diff --git a/src/webpage/index.html b/src/webpage/index.html index 114e9177..584d0275 100644 --- a/src/webpage/index.html +++ b/src/webpage/index.html @@ -1,23 +1,37 @@ - + - - + + Jank Client - - - - - - - - + + + + + + + +
- +

Jank Client is loading

This shouldn't take long

Switch Accounts

@@ -36,7 +50,7 @@

Server Name

- +

USERNAME

@@ -55,8 +69,8 @@

Server Name

- - + + Channel name @@ -64,15 +78,14 @@

Server Name

- +
-
-
+
-
+
@@ -81,7 +94,7 @@

Server Name

-
+