From 1a3ce1e3ff2b3d1c8e393760c422b866819ce2c0 Mon Sep 17 00:00:00 2001 From: TomatoCake <60300461+DEVTomatoCake@users.noreply.github.com> Date: Sat, 20 Jul 2024 19:19:23 +0200 Subject: [PATCH 1/2] implement very basic connections & applications --- webpage/index.html | 7 +- webpage/index.ts | 11 ++ webpage/localuser.ts | 260 ++++++++++++++++++++++++++++++++++++++++++- webpage/style.css | 39 +++++-- 4 files changed, 303 insertions(+), 14 deletions(-) diff --git a/webpage/index.html b/webpage/index.html index 07b70b1..c970952 100644 --- a/webpage/index.html +++ b/webpage/index.html @@ -37,7 +37,12 @@

STATUS

-

+ +
+

+

🔗

+

🤖

+
diff --git a/webpage/index.ts b/webpage/index.ts index a5d367e..3c21fa6 100644 --- a/webpage/index.ts +++ b/webpage/index.ts @@ -245,6 +245,17 @@ function userSettings(){ thisuser.usersettings.show(); } document.getElementById("settings").onclick=userSettings; + +function userConnections(){ + thisuser.userConnections.show(); +} +document.getElementById("connections").onclick=userConnections; + +function devPortal(){ + thisuser.devPortal.show(); +} +document.getElementById("dev-portal").onclick=devPortal; + let triggered=false; document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{ const messagecontainer=document.getElementById("messagecontainer") diff --git a/webpage/localuser.ts b/webpage/localuser.ts index 9ca8b11..87cf0c5 100644 --- a/webpage/localuser.ts +++ b/webpage/localuser.ts @@ -19,6 +19,8 @@ class Localuser{ info; headers:{"Content-type":string,Authorization:string}; usersettings:Fullscreen; + userConnections:Fullscreen; + devPortal:Fullscreen; ready; guilds:Guild[]; guildids:{ [key: string]: Guild }; @@ -671,6 +673,262 @@ class Localuser{ newprouns=null; newbio=null; }.bind(this)) - } + + const connectionContainer=document.createElement("div"); + connectionContainer.id="connection-container"; + this.userConnections=new Fullscreen( + ["html", + connectionContainer + ], () => {}, async () => { + connectionContainer.innerHTML=""; + + const res=await fetch(this.info.api.toString()+"/v9/connections", { + headers: this.headers + }); + const json=await res.json(); + + Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => { + const connection=json[key]; + + const container=document.createElement("div"); + container.textContent=key.charAt(0).toUpperCase() + key.slice(1); + + if (connection.enabled) { + container.addEventListener("click", async () => { + const connectionRes=await fetch(this.info.api.toString()+"/v9/connections/" + key + "/authorize", { + headers: this.headers + }); + const connectionJSON=await connectionRes.json(); + window.open(connectionJSON.url, "_blank", "noopener noreferrer"); + }) + } else { + container.classList.add("disabled") + container.title="This connection has been disabled server-side." + } + + connectionContainer.appendChild(container); + }) + } + ); + + let appName=""; + const appListContainer=document.createElement("div"); + appListContainer.id="app-list-container"; + this.devPortal=new Fullscreen( + ["vdiv", + ["hdiv", + ["textbox", "Name:", appName, event => { + appName=event.target.value; + }], + ["button", + "", + "Create application", + async () => { + if (appName.trim().length == 0) return alert("Please enter a name for the application."); + + const res=await fetch(this.info.api.toString()+"/v9/applications", { + method: "POST", + headers: this.headers, + body: JSON.stringify({ + name: appName + }) + }); + const json=await res.json(); + this.manageApplication(json.id); + this.devPortal.hide(); + } + ] + ], + ["html", + appListContainer + ] + ], () => {}, async () => { + appListContainer.innerHTML=""; + + const res=await fetch(this.info.api.toString()+"/v9/applications", { + headers: this.headers + }); + const json=await res.json(); + + json.forEach(application => { + const container=document.createElement("div"); + + if (application.cover_image) { + const cover=document.createElement("img"); + cover.crossOrigin="anonymous"; + cover.src=this.info.cdn.toString()+"/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256"; + cover.alt=""; + cover.loading="lazy"; + container.appendChild(cover); + } + + const name=document.createElement("h2"); + name.textContent=application.name + (application.bot ? " (Bot)" : ""); + container.appendChild(name); + + container.addEventListener("click", async () => { + this.devPortal.hide(); + this.manageApplication(application.id); + }); + appListContainer.appendChild(container); + }) + } + ) + } + async manageApplication(appId="") { + const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, { + headers: this.headers + }); + const json=await res.json(); + + const fields: any={}; + const appDialog=new Fullscreen( + ["vdiv", + ["title", + "Editing " + json.name + ], + ["hdiv", + ["textbox", "Application name:", json.name, event => { + fields.name=event.target.value; + }], + ["mdbox", "Description:", json.description, event => { + fields.description=event.target.value; + }], + ["vdiv", + json.icon ? ["img", this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"], + ["fileupload", "Application icon:", event => { + const reader=new FileReader(); + reader.readAsDataURL(event.target.files[0]); + reader.onload=() => { + fields.icon=reader.result; + } + }] + ] + ], + ["hdiv", + ["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => { + fields.privacy_policy_url=event.target.value; + }], + ["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => { + fields.terms_of_service_url=event.target.value; + }] + ], + ["hdiv", + ["checkbox", "Make bot publicly inviteable?", json.bot_public, event => { + fields.bot_public=event.target.checked; + }], + ["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => { + fields.bot_require_code_grant=event.target.checked; + }] + ], + ["hdiv", + ["button", + "", + "Save changes", + async () => { + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId, { + method: "PATCH", + headers: this.headers, + body: JSON.stringify(fields) + }); + if (updateRes.ok) appDialog.hide(); + else { + const updateJSON=await updateRes.json(); + alert("An error occurred: " + updateJSON.message); + } + } + ], + ["button", + "", + (json.bot ? "Manage" : "Add") + " bot", + async () => { + if (!json.bot) { + if (!confirm("Are you sure you want to add a bot to this application? There's no going back.")) return; + + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", { + method: "POST", + headers: this.headers + }); + const updateJSON=await updateRes.json(); + alert("Bot token:\n" + updateJSON.token); + } + + appDialog.hide(); + this.manageBot(appId); + } + ] + ] + ] + ) + appDialog.show(); + } + async manageBot(appId="") { + const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, { + headers: this.headers + }); + const json=await res.json(); + if (!json.bot) return alert("For some reason, this application doesn't have a bot (yet)."); + + const fields: any={ + username: json.bot.username, + avatar: json.bot.avatar ? (this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : "" + }; + const botDialog=new Fullscreen( + ["vdiv", + ["title", + "Editing bot: " + json.bot.username + ], + ["hdiv", + ["textbox", "Bot username:", json.bot.username, event => { + fields.username=event.target.value + }], + ["vdiv", + fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"], + ["fileupload", "Bot avatar:", event => { + const reader=new FileReader(); + reader.readAsDataURL(event.target.files[0]); + reader.onload=() => { + fields.avatar=reader.result; + } + }] + ] + ], + ["hdiv", + ["button", + "", + "Save changes", + async () => { + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", { + method: "PATCH", + headers: this.headers, + body: JSON.stringify(fields) + }); + if (updateRes.ok) botDialog.hide(); + else { + const updateJSON=await updateRes.json(); + alert("An error occurred: " + updateJSON.message); + } + } + ], + ["button", + "", + "Reset token", + async () => { + if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")) return; + + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot/reset", { + method: "POST", + headers: this.headers + }); + const updateJSON=await updateRes.json(); + alert("New token:\n" + updateJSON.token); + botDialog.hide(); + } + ] + ] + ] + ); + botDialog.show(); + } } export {Localuser}; diff --git a/webpage/style.css b/webpage/style.css index b92af19..d3d03c7 100644 --- a/webpage/style.css +++ b/webpage/style.css @@ -699,22 +699,20 @@ textarea { flex-shrink: 1; } -#settings { +#user-actions { + display: flex; + flex-wrap: wrap; +} +#user-actions h2 { cursor: pointer; user-select: none; - border-radius: .3in; - transition: background 1s; + border-radius: .1in; + transition: color .5s; text-align: center; - font-size: .25in; - width: .3in; - height: .3in; overflow: visible; } - -#settings:hover { - background-color: var(--settings-hover); - cursor: pointer; - user-select: none; +#user-actions h2:hover, #user-actions h2:focus { + color: var(--timestamp-color); } #userinfo { @@ -1352,4 +1350,21 @@ span { width: 100%; flex-direction: row; max-height:100in; -} \ No newline at end of file +} + +#connection-container, #app-list-container { + display: flex; + flex-wrap: wrap; + gap: 10px; + max-width: 700px; +} +#connection-container div, #app-list-container div { + padding: 5px 10px; + border-radius: 5px; + background-color: var(--textarea-bg); + cursor: pointer; +} +#connection-container .disabled { + background-color: var(--embed-fallback); + cursor: not-allowed; +} From f2ce41d48aa671ca6a401b93ac024b9aeb40f1ba Mon Sep 17 00:00:00 2001 From: TomatoCake <60300461+DEVTomatoCake@users.noreply.github.com> Date: Sun, 21 Jul 2024 10:59:38 +0200 Subject: [PATCH 2/2] thanks git for yeeting my changes --- webpage/index.ts | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/webpage/index.ts b/webpage/index.ts index b3db4ee..6f37235 100644 --- a/webpage/index.ts +++ b/webpage/index.ts @@ -183,26 +183,15 @@ function userSettings(){ thisuser.usersettings.show(); } document.getElementById("settings").onclick=userSettings; -let triggered=false; -document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{ - const messagecontainer=document.getElementById("messagecontainer") - if(messagecontainer.scrollTop<2000){ - if(!triggered){ - thisuser.lookingguild.prevchannel.grabmoremessages().then(()=>{ - triggered=false; - if(messagecontainer.scrollTop===0){ - messagecontainer.scrollTop=1; - } - }); - } - triggered=true; - }else{ - if(Math.abs(messagecontainer.scrollHeight-messagecontainer.scrollTop-messagecontainer.clientHeight) < 3){ - thisuser.lookingguild.prevchannel.readbottom(); - } - } - // -}) +function userConnections(){ + thisuser.userConnections.show(); +} +document.getElementById("connections").onclick=userConnections; +function devPortal(){ + thisuser.devPortal.show(); +} +document.getElementById("dev-portal").onclick=devPortal; + if(mobile){ document.getElementById("channelw").onclick=function(){ (document.getElementById("channels").parentNode as HTMLElement).classList.add("collapse");