adding invites

This commit is contained in:
MathMan05 2024-08-15 17:05:14 -05:00
parent 3e5435668e
commit 3af371e6ab
16 changed files with 670 additions and 30 deletions

View file

@ -60,6 +60,62 @@ class Channel {
this.contextmenu.addbutton("Edit channel", function () {
this.editChannel(this);
}, null, _ => { return _.isAdmin(); });
this.contextmenu.addbutton("Make invite", function () {
this.createInvite();
}, null, (_) => {
return _.hasPermission("CREATE_INSTANT_INVITE") && _.type !== 4;
});
}
createInvite() {
const div = document.createElement("div");
div.classList.add("invitediv");
const text = document.createElement("span");
div.append(text);
let uses = 0;
let expires = 1800;
const copycontainer = document.createElement("div");
copycontainer.classList.add("copycontainer");
const copy = document.createElement("img");
copy.src = "/icons/copy.svg";
copy.classList.add("copybutton", "svgtheme");
copycontainer.append(copy);
copycontainer.onclick = _ => {
navigator.clipboard.writeText(text.textContent);
};
div.append(copycontainer);
const update = () => {
fetch(`${this.info.api}/channels/${this.id}/invites`, {
method: "POST",
headers: this.headers,
body: JSON.stringify({
flags: 0,
target_type: null,
target_user_id: null,
max_age: expires + "",
max_uses: uses,
temporary: uses !== 0
})
}).then(_ => _.json()).then(json => {
const params = new URLSearchParams("");
params.set("instance", this.info.wellknown);
const encoded = params.toString();
text.textContent = `${window.location.protocol}//${window.location.host}/invite/${json.code}?${encoded}`;
});
};
update();
new Dialog(["vdiv",
["title", "Invite people"],
["text", `to #${this.name} in ${this.guild.properties.name}`],
["select", "Expire after:", ["30 Minutes", "1 Hour", "6 Hours", "12 Hours", "1 Day", "7 Days", "30 Days", "Never"], function (e) {
expires = [1800, 3600, 21600, 43200, 86400, 604800, 2592000, 0][e.srcElement.selectedIndex];
update();
}, 0],
["select", "Max uses:", ["No limit", "1 use", "5 uses", "10 uses", "25 uses", "50 uses", "100 uses"], function (e) {
uses = [0, 1, 5, 10, 25, 50, 100][e.srcElement.selectedIndex];
update();
}, 0],
["html", div]
]).show();
}
generateSettings() {
this.sortPerms();

116
.dist/invite.js Normal file
View file

@ -0,0 +1,116 @@
import { getBulkUsers, getapiurls } from "./login.js";
const users = getBulkUsers();
const well = new URLSearchParams(window.location.search).get("instance");
const joinable = [];
for (const thing in users.users) {
const user = users.users[thing];
if (user.serverurls.wellknown.includes(well)) {
joinable.push(user);
}
console.log(users.users[thing]);
}
let urls;
if (!joinable.length) {
const out = await getapiurls(well);
if (out) {
urls = out;
for (const thing in users.users) {
const user = users.users[thing];
if (user.serverurls.api.includes(out.api)) {
joinable.push(user);
}
console.log(users.users[thing]);
}
}
else {
throw Error("someone needs to handle the case where the servers don't exist");
}
}
else {
urls = joinable[0].serverurls;
}
if (!joinable.length) {
document.getElementById("AcceptInvite").textContent = "Create an account to accept the invite";
}
const code = window.location.pathname.split("/")[2];
let guildinfo;
fetch(`${urls.api}/invites/${code}`, {
method: "GET"
}).then(_ => _.json()).then(json => {
const guildjson = json.guild;
guildinfo = guildjson;
document.getElementById("invitename").textContent = guildjson.name;
document.getElementById("invitedescription").textContent =
`${json.inviter.username} invited you to join ${guildjson.name}`;
if (guildjson.icon) {
const img = document.createElement("img");
img.src = `${urls.cdn}/icons/${guildjson.id}/${guildjson.icon}.png`;
img.classList.add("inviteGuild");
document.getElementById("inviteimg").append(img);
}
else {
const txt = guildjson.name.replace(/'s /g, " ").replace(/\w+/g, word => word[0]).replace(/\s/g, "");
const div = document.createElement("div");
div.textContent = txt;
div.classList.add("inviteGuild");
document.getElementById("inviteimg").append(div);
}
});
function showAccounts() {
const table = document.createElement("dialog");
for (const thing of Object.values(joinable)) {
const specialuser = thing;
console.log(specialuser.pfpsrc);
const userinfo = document.createElement("div");
userinfo.classList.add("flexltr", "switchtable");
const pfp = document.createElement("img");
userinfo.append(pfp);
const user = document.createElement("div");
userinfo.append(user);
user.append(specialuser.username);
user.append(document.createElement("br"));
const span = document.createElement("span");
span.textContent = specialuser.serverurls.wellknown.replace("https://", "").replace("http://", "");
user.append(span);
user.classList.add("userinfo");
span.classList.add("serverURL");
pfp.src = specialuser.pfpsrc;
pfp.classList.add("pfp");
table.append(userinfo);
userinfo.addEventListener("click", _ => {
console.log(thing);
fetch(`${urls.api}/invites/${code}`, {
method: "POST",
headers: {
Authorization: thing.token
}
}).then(_ => {
users["currentuser"] = specialuser.uid;
localStorage.setItem("userinfos", JSON.stringify(users));
window.location.href = "/channels/" + guildinfo.id;
});
});
}
{
const td = document.createElement("div");
td.classList.add("switchtable");
td.append("Login or create an account ⇌");
td.addEventListener("click", _ => {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well);
window.location.href = "/login?" + l.toString();
});
if (!joinable.length) {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well);
window.location.href = "/login?" + l.toString();
}
table.append(td);
}
table.classList.add("accountSwitcher");
console.log(table);
document.body.append(table);
}
document.getElementById("AcceptInvite").addEventListener("click", showAccounts);

View file

@ -1,11 +1,12 @@
import { Dialog } from "./dialog.js";
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
export { mobile, getBulkUsers, getBulkInfo, setTheme, Specialuser };
export { mobile, getBulkUsers, getBulkInfo, setTheme, Specialuser, getapiurls, adduser };
function setTheme() {
const name = localStorage.getItem("theme");
let name = localStorage.getItem("theme");
if (!name) {
document.body.className = "Dark-theme";
localStorage.setItem("theme", "Dark");
name = "Dark";
}
document.body.className = name + "-theme";
}
@ -116,13 +117,38 @@ function adduser(user) {
info.users[user.uid] = user;
info.currentuser = user.uid;
localStorage.setItem("userinfos", JSON.stringify(info));
return user;
}
const instancein = document.getElementById("instancein");
let timeout;
let instanceinfo;
async function getapiurls(str) {
if (str[str.length - 1] !== "/") {
str += "/";
}
let api;
try {
const info = await fetch(`${str}/.well-known/spacebar`).then((x) => x.json());
api = info.api;
}
catch {
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());
return {
api: info.apiEndpoint,
gateway: info.gateway,
cdn: info.cdn,
wellknown: str,
};
}
catch {
}
}
async function checkInstance(e) {
const verify = document.getElementById("verify");
;
try {
verify.textContent = "Checking Instance";
const instanceinfo = await setInstance(instancein.value);
@ -219,16 +245,30 @@ async function login(username, password, captcha) {
alert(response.message);
}
else {
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
window.location.href = '/channels/@me';
console.warn(response);
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token }).username = username;
const redir = new URLSearchParams(window.location.search).get("goback");
if (redir) {
window.location.href = redir;
}
else {
window.location.href = '/channels/@me';
}
}
});
}]]).show();
}
else {
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
window.location.href = '/channels/@me';
return response.token;
console.warn(response);
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token }).username = username;
const redir = new URLSearchParams(window.location.search).get("goback");
if (redir) {
window.location.href = redir;
}
else {
window.location.href = '/channels/@me';
}
return "";
}
}
});
@ -296,4 +336,14 @@ if ("serviceWorker" in navigator){
})
}
*/
const switchurl = document.getElementById("switch");
if (switchurl) {
switchurl.href += window.location.search;
const instance = new URLSearchParams(window.location.search).get("instance");
console.log(instance);
if (instance) {
instancein.value = instance;
checkInstance("");
}
}
export { checkInstance };

View file

@ -1,4 +1,4 @@
import { checkInstance } from "./login.js";
import { checkInstance, adduser } from "./login.js";
if (document.getElementById("register")) {
document.getElementById("register").addEventListener("submit", registertry);
}
@ -67,8 +67,15 @@ async function registertry(e) {
}
}
else {
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: email, token: e.token }).username = username;
localStorage.setItem("token", e.token);
window.location.href = '/channels/@me';
const redir = new URLSearchParams(window.location.search).get("goback");
if (redir) {
window.location.href = redir;
}
else {
window.location.href = '/channels/@me';
}
}
});
});

View file

@ -46,7 +46,7 @@ class User {
static contextmenu = new Contextmenu("User Menu");
static setUpContextMenu() {
this.contextmenu.addbutton("Copy user id", function () {
navigator.clipboard.writeText(this.id.id);
navigator.clipboard.writeText(this.id);
});
this.contextmenu.addbutton("Message user", function () {
fetch(this.info.api + "/users/@me/channels", { method: "POST",

View file

@ -18,11 +18,100 @@ app.use("/getupdates",(req, res) => {
res.send(out.mtimeMs+"");
});
let debugging=true;//Do not turn this off, the service worker is all kinds of jank as is, it'll really mess your day up if you disable this
app.use('/', (req, res) => {
function isembed(str){
return str===("Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)")||str===("Mozilla/5.0 (compatible; Spacebar/1.0; +https://github.com/spacebarchat/server)");
}
async function getapiurls(str){
if(str[str.length-1]!=="/"){
str+="/"
}
let api;
try{
const info=await fetch(`${str}/.well-known/spacebar`).then((x) => x.json());
api=info.api;
}catch{
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());
return {
api: info.apiEndpoint,
gateway: info.gateway,
cdn: info.cdn,
wellknown: str,
};
}catch{
return false;
}
}
async function inviteres(req,res){
//console.log(req.rawHeaders);
try{
let embed=false;
for(const i in req.rawHeaders){
if(req.rawHeaders[i]==="User-Agent"){
embed=isembed(req.rawHeaders[1+ +i]);
}
}
if(!embed){return false};
const code=req.path.split("/")[2];
let title="";
let description="";
let icon="";
const urls=await getapiurls(req.query.instance);
await fetch(`${urls.api}/invites/${code}`,{
method:"GET"
}).then(_=>_.json()).then(json=>{
title=json.guild.name;
description=json.inviter.username+" Has invited you to "+json.guild.name+(json.guild.description?json.guild.description+"\n":"");
if(json.guild.icon){
icon=`${urls.cdn}/icons/${json.guild.id}/${json.guild.icon}.png`;
}
});
function htmlEnc(s) {//https://stackoverflow.com/a/11561642
return s.replaceAll(/&/g, '&')
.replaceAll(/</g, '&lt;')
.replaceAll(/>/g, '&gt;')
.replaceAll(/'/g, '&#39;')
.replaceAll(/"/g, '&#34;');
}
function strEscape(s){
return JSON.stringify(s);
}
html=`
<body>
<head>
<title>${htmlEnc(title)}</title>
<meta content=${strEscape(title)} property="og:title" />
<meta content=${strEscape(description)} property="og:description" />
<meta content=${strEscape(icon)} property="og:image" />
</head>
</body>
`
res.send(html);
return true;
}catch(e){
console.error(e);
}
return false;
}
app.use('/', async (req, res) => {
if(debugging&&req.path.startsWith("/service.js")){
res.send("console.log(\"Hi :3\");");
return;
}
if(req.path.startsWith("/invite/")){
const condition=await inviteres(req,res);
if(!condition){
res.sendFile(`./webpage/invite.html`, {root: __dirname});
}
return;
}
if(fs.existsSync(`${__dirname}/webpage${req.path}`)) {
res.sendFile(`./webpage${req.path}`, {root: __dirname});
}else if(req.path.endsWith(".js") && fs.existsSync(`${__dirname}/.dist${req.path}`)){

View file

@ -73,6 +73,63 @@ class Channel{
this.contextmenu.addbutton("Edit channel",function(){
this.editChannel(this);
},null,_=>{return _.isAdmin()});
this.contextmenu.addbutton("Make invite",function(){
this.createInvite();
},null,(_:Channel)=>{
return _.hasPermission("CREATE_INSTANT_INVITE")&&_.type!==4
});
}
createInvite(){
const div=document.createElement("div");
div.classList.add("invitediv");
const text=document.createElement("span");
div.append(text);
let uses=0;
let expires=1800;
const copycontainer=document.createElement("div");
copycontainer.classList.add("copycontainer")
const copy=document.createElement("img");
copy.src="/icons/copy.svg";
copy.classList.add("copybutton","svgtheme");
copycontainer.append(copy);
copycontainer.onclick=_=>{
navigator.clipboard.writeText(text.textContent);
}
div.append(copycontainer);
const update=()=>{
fetch(`${this.info.api}/channels/${this.id}/invites`,{
method:"POST",
headers:this.headers,
body:JSON.stringify({
flags: 0,
target_type: null,
target_user_id: null,
max_age: expires+"",
max_uses: uses,
temporary: uses!==0
})
}).then(_=>_.json()).then(json=>{
const params=new URLSearchParams("");
params.set("instance",this.info.wellknown)
const encoded=params.toString();
text.textContent=`${window.location.protocol}//${window.location.host}/invite/${json.code}?${encoded}`
})
}
update();
new Dialog(["vdiv",
["title","Invite people"],
["text",`to #${this.name} in ${this.guild.properties.name}`],
["select","Expire after:",["30 Minutes","1 Hour","6 Hours","12 Hours","1 Day","7 Days","30 Days","Never"],function(e){
expires=[1800,3600,21600,43200,86400,604800,2592000,0][e.srcElement.selectedIndex];
update();
},0],
["select","Max uses:",["No limit","1 use","5 uses","10 uses","25 uses","50 uses","100 uses"],function(e){
uses=[0,1,5,10,25,50,100][e.srcElement.selectedIndex];
update();
},0],
["html",div]
]).show()
}
generateSettings(){
this.sortPerms();

1
webpage/icons/copy.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180"><g fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round" stroke-width="21.9"><path d="m64 44.5 85.7.3-.5 124.3-85.2-.4.5-124.2Z"/><path d="M31.5 141.6 32 11.5h-.5l89.6.3"/></g></svg>

After

Width:  |  Height:  |  Size: 262 B

22
webpage/invite.html Normal file
View file

@ -0,0 +1,22 @@
<body>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jank Client</title>
<meta content="Invite" property="og:title" />
<meta content="You shouldn't see this, but this is an invite URL'" property="og:description" />
<meta content="/logo.webp" property="og:image" />
<meta content="#4b458c" data-react-helmet="true" name="theme-color" />
<link href="/style.css" rel="stylesheet" type="text/css" />
<link href="/themes.css" rel="stylesheet" type="text/css" id="lightcss"/>
</head>
<div>
<div id="invitebody">
<div id="inviteimg"></div>
<h1 id="invitename">Server Name</h1>
<p id="invitedescription">Someone invited you to Server Name</p>
<button id="AcceptInvite">Accept Invite</button>
</div>
</div>
<script type="module" src="/invite.js"></script>
</body>

118
webpage/invite.ts Normal file
View file

@ -0,0 +1,118 @@
import {getBulkUsers, Specialuser, getapiurls} from "./login.js";
const users=getBulkUsers();
const well=new URLSearchParams(window.location.search).get("instance");
const joinable:Specialuser[]=[];
for(const thing in users.users){
const user:Specialuser = users.users[thing]
if(user.serverurls.wellknown.includes(well)){
joinable.push(user);
}
console.log(users.users[thing]);
}
let urls:{api:string,cdn:string};
if(!joinable.length){
const out=await getapiurls(well);
if(out){
urls=out;
for(const thing in users.users){
const user:Specialuser = users.users[thing]
if(user.serverurls.api.includes(out.api)){
joinable.push(user);
}
console.log(users.users[thing]);
}
}else{
throw Error("someone needs to handle the case where the servers don't exist")
}
}else{
urls=joinable[0].serverurls;
}
if(!joinable.length){
document.getElementById("AcceptInvite").textContent="Create an account to accept the invite"
}
const code=window.location.pathname.split("/")[2];
let guildinfo;
fetch(`${urls.api}/invites/${code}`,{
method:"GET"
}).then(_=>_.json()).then(json=>{
const guildjson=json.guild;
guildinfo=guildjson;
document.getElementById("invitename").textContent=guildjson.name;
document.getElementById("invitedescription").textContent=
`${json.inviter.username} invited you to join ${guildjson.name}`;
if(guildjson.icon){
const img=document.createElement("img");
img.src=`${urls.cdn}/icons/${guildjson.id}/${guildjson.icon}.png`;
img.classList.add("inviteGuild");
document.getElementById("inviteimg").append(img);
}else{
const txt=guildjson.name.replace(/'s /g, " ").replace(/\w+/g, word => word[0]).replace(/\s/g, "");
const div=document.createElement("div");
div.textContent=txt;
div.classList.add("inviteGuild");
document.getElementById("inviteimg").append(div);
}
})
function showAccounts(){
const table=document.createElement("dialog");
for(const thing of Object.values(joinable)){
const specialuser=thing as Specialuser;
console.log(specialuser.pfpsrc)
const userinfo=document.createElement("div");
userinfo.classList.add("flexltr","switchtable");
const pfp=document.createElement("img");
userinfo.append(pfp);
const user=document.createElement("div");
userinfo.append(user);
user.append(specialuser.username);
user.append(document.createElement("br"));
const span=document.createElement("span");
span.textContent=specialuser.serverurls.wellknown.replace("https://","").replace("http://","");
user.append(span);
user.classList.add("userinfo")
span.classList.add("serverURL")
pfp.src=specialuser.pfpsrc;
pfp.classList.add("pfp");
table.append(userinfo);
userinfo.addEventListener("click",_=>{
console.log(thing);
fetch(`${urls.api}/invites/${code}`,{
method:"POST",
headers:{
Authorization:thing.token
}
}).then(_=>{
users["currentuser"]=specialuser.uid;
localStorage.setItem("userinfos",JSON.stringify(users));
window.location.href="/channels/"+guildinfo.id;
})
})
}
{
const td=document.createElement("div");
td.classList.add("switchtable")
td.append("Login or create an account ⇌");
td.addEventListener("click",_=>{
const l=new URLSearchParams("?")
l.set("goback",window.location.href);
l.set("instance",well);
window.location.href="/login?"+l.toString();
})
if(!joinable.length){
const l=new URLSearchParams("?")
l.set("goback",window.location.href);
l.set("instance",well);
window.location.href="/login?"+l.toString();
}
table.append(td);
}
table.classList.add("accountSwitcher");
console.log(table);
document.body.append(table);
}
document.getElementById("AcceptInvite").addEventListener("click",showAccounts);

View file

@ -29,7 +29,7 @@
</div>
<button type="submit">Login</button>
</form>
<a href="/register.html">Don't have an account?</a>
<a href="/register.html" id="switch">Don't have an account?</a>
</div>
<script src="/login.js" type="module"></script>
<script src="/login.js" type="module" ></script>
</body>

View file

@ -1,12 +1,13 @@
import { Dialog } from "./dialog.js";
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
export {mobile, getBulkUsers,getBulkInfo,setTheme,Specialuser}
export {mobile, getBulkUsers,getBulkInfo,setTheme,Specialuser,getapiurls,adduser}
function setTheme(){
const name=localStorage.getItem("theme");
let name=localStorage.getItem("theme");
if(!name){
document.body.className="Dark-theme";
localStorage.setItem("theme","Dark");
name="Dark";
}
document.body.className=name+"-theme";
}
@ -18,6 +19,7 @@ function getBulkUsers(){
}
return json;
}
function getBulkInfo(){
return JSON.parse(localStorage.getItem("userinfos"));
}
@ -115,12 +117,39 @@ function adduser(user){
info.users[user.uid]=user;
info.currentuser=user.uid;
localStorage.setItem("userinfos",JSON.stringify(info));
return user;
}
const instancein=document.getElementById("instancein");
const instancein=document.getElementById("instancein") as HTMLInputElement;
let timeout;
let instanceinfo;
async function checkInstance(e){
const verify=document.getElementById("verify");;
async function getapiurls(str:string):Promise<{api:string,cdn:string,gateway:string,wellknown:string}|false>{
if(str[str.length-1]!=="/"){
str+="/"
}
let api:string;
try{
const info=await fetch(`${str}/.well-known/spacebar`).then((x) => x.json());
api=info.api;
}catch{
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());
return {
api: info.apiEndpoint,
gateway: info.gateway,
cdn: info.cdn,
wellknown: str,
};
}catch{
}
}
async function checkInstance(e:string){
const verify=document.getElementById("verify");
try{
verify.textContent="Checking Instance";
const instanceinfo=await setInstance((instancein as HTMLInputElement).value);
@ -150,8 +179,8 @@ if(instancein){
}else{
checkInstance("https://spacebar.chat/");
}
}
}
async function login(username:string, password:string, captcha:string){
if(captcha===""){
@ -215,15 +244,27 @@ async function login(username:string, password:string, captcha:string){
if(response.message){
alert(response.message)
}else{
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token});
window.location.href = '/channels/@me';
console.warn(response);
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token}).username=username;
const redir=new URLSearchParams(window.location.search).get("goback");
if(redir){
window.location.href = redir;
}else{
window.location.href = '/channels/@me';
}
}
})
}]]).show();
}else{
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token});
window.location.href = '/channels/@me';
return response.token;
console.warn(response);
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token}).username=username;
const redir=new URLSearchParams(window.location.search).get("goback");
if(redir){
window.location.href = redir;
}else{
window.location.href = '/channels/@me';
}
return "";
}
}
})
@ -292,4 +333,14 @@ if ("serviceWorker" in navigator){
})
}
*/
const switchurl=document.getElementById("switch") as HTMLAreaElement;
if(switchurl){
switchurl.href+=window.location.search;
const instance=new URLSearchParams(window.location.search).get("instance");
console.log(instance);
if(instance){
instancein.value=instance;
checkInstance("");
}
}
export {checkInstance};

View file

@ -53,7 +53,7 @@
</div>
<button type="submit" class="dontgrow">Create account</button>
</form>
<a href="/login.html">Already have an account?</a>
<a href="/login.html" id="switch">Already have an account?</a>
</div>
<script src="/register.js" type="module"></script>
</body>

View file

@ -1,4 +1,4 @@
import {checkInstance} from "./login.js";
import {checkInstance, adduser} from "./login.js";
if(document.getElementById("register")){
document.getElementById("register").addEventListener("submit", registertry);
}
@ -63,8 +63,14 @@ async function registertry(e){
document.getElementById("wrong").textContent=e.errors[Object.keys(e.errors)[0]]._errors[0].message;
}
}else{
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:email,token:e.token}).username=username;
localStorage.setItem("token",e.token);
window.location.href = '/channels/@me';
const redir=new URLSearchParams(window.location.search).get("goback");
if(redir){
window.location.href = redir;
}else{
window.location.href = '/channels/@me';
}
}
})
})

View file

@ -1751,4 +1751,71 @@ form div{
}
.reactiondiv{
margin-left: .45in;
}
#invitebody{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: var(--dialog-bg);
border-radius: .1in;
border: solid .03in var(--black);
padding:.2in;
box-sizing:border-box;
display:flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: .5in .2in;
gap: .1in;
width: 5.in;
}
#AcceptInvite{
padding: .1in .2in;
width: 100%;
text-align: center;
margin-top: .5in;
}
.invitediv{
height: .35in;
width: 3in;
border: solid .03in var(--black);
border-radius: .1in;
background: var(--textarea-bg);
span{
text-wrap:nowrap;
}
;
display: flex;
flex-direction: column;
justify-content: center;
overflow: hidden;
}
.inviteGuild{
width: .75in;
height:.75in;
background-color:var(--blank-bg);
display:flex;
justify-content: center;
align-items: center;
user-select: none;
font-size:.3in;
border-radius:.2in;
border:solid .03in var(--black);
}
.copybutton{
width:.25in;
}
.copycontainer{
position:absolute;
right:0;
background:var(--blank-bg);
padding:.05in;
border-radius:.1in;
border:solid .03in var(--black);
box-sizing:border-box;
box-shadow: .02in 0 .03in var(--black);
cursor:pointer;
}

View file

@ -49,8 +49,8 @@ class User{
}
static contextmenu:Contextmenu=new Contextmenu("User Menu");
static setUpContextMenu(){
this.contextmenu.addbutton("Copy user id",function(){
navigator.clipboard.writeText(this.id.id);
this.contextmenu.addbutton("Copy user id",function(this:User){
navigator.clipboard.writeText(this.id);
});
this.contextmenu.addbutton("Message user",function(){
fetch(this.info.api+"/users/@me/channels",