adding invites
This commit is contained in:
parent
3e5435668e
commit
3af371e6ab
16 changed files with 670 additions and 30 deletions
|
@ -60,6 +60,62 @@ class Channel {
|
||||||
this.contextmenu.addbutton("Edit channel", function () {
|
this.contextmenu.addbutton("Edit channel", function () {
|
||||||
this.editChannel(this);
|
this.editChannel(this);
|
||||||
}, null, _ => { return _.isAdmin(); });
|
}, 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() {
|
generateSettings() {
|
||||||
this.sortPerms();
|
this.sortPerms();
|
||||||
|
|
116
.dist/invite.js
Normal file
116
.dist/invite.js
Normal 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);
|
|
@ -1,11 +1,12 @@
|
||||||
import { Dialog } from "./dialog.js";
|
import { Dialog } from "./dialog.js";
|
||||||
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
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() {
|
function setTheme() {
|
||||||
const name = localStorage.getItem("theme");
|
let name = localStorage.getItem("theme");
|
||||||
if (!name) {
|
if (!name) {
|
||||||
document.body.className = "Dark-theme";
|
document.body.className = "Dark-theme";
|
||||||
localStorage.setItem("theme", "Dark");
|
localStorage.setItem("theme", "Dark");
|
||||||
|
name = "Dark";
|
||||||
}
|
}
|
||||||
document.body.className = name + "-theme";
|
document.body.className = name + "-theme";
|
||||||
}
|
}
|
||||||
|
@ -116,13 +117,38 @@ function adduser(user) {
|
||||||
info.users[user.uid] = user;
|
info.users[user.uid] = user;
|
||||||
info.currentuser = user.uid;
|
info.currentuser = user.uid;
|
||||||
localStorage.setItem("userinfos", JSON.stringify(info));
|
localStorage.setItem("userinfos", JSON.stringify(info));
|
||||||
|
return user;
|
||||||
}
|
}
|
||||||
const instancein = document.getElementById("instancein");
|
const instancein = document.getElementById("instancein");
|
||||||
let timeout;
|
let timeout;
|
||||||
let instanceinfo;
|
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) {
|
async function checkInstance(e) {
|
||||||
const verify = document.getElementById("verify");
|
const verify = document.getElementById("verify");
|
||||||
;
|
|
||||||
try {
|
try {
|
||||||
verify.textContent = "Checking Instance";
|
verify.textContent = "Checking Instance";
|
||||||
const instanceinfo = await setInstance(instancein.value);
|
const instanceinfo = await setInstance(instancein.value);
|
||||||
|
@ -219,16 +245,30 @@ async function login(username, password, captcha) {
|
||||||
alert(response.message);
|
alert(response.message);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
|
console.warn(response);
|
||||||
window.location.href = '/channels/@me';
|
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();
|
}]]).show();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
|
console.warn(response);
|
||||||
window.location.href = '/channels/@me';
|
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token }).username = username;
|
||||||
return response.token;
|
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 };
|
export { checkInstance };
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { checkInstance } from "./login.js";
|
import { checkInstance, adduser } from "./login.js";
|
||||||
if (document.getElementById("register")) {
|
if (document.getElementById("register")) {
|
||||||
document.getElementById("register").addEventListener("submit", registertry);
|
document.getElementById("register").addEventListener("submit", registertry);
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,15 @@ async function registertry(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: email, token: e.token }).username = username;
|
||||||
localStorage.setItem("token", e.token);
|
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';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -46,7 +46,7 @@ class User {
|
||||||
static contextmenu = new Contextmenu("User Menu");
|
static contextmenu = new Contextmenu("User Menu");
|
||||||
static setUpContextMenu() {
|
static setUpContextMenu() {
|
||||||
this.contextmenu.addbutton("Copy user id", function () {
|
this.contextmenu.addbutton("Copy user id", function () {
|
||||||
navigator.clipboard.writeText(this.id.id);
|
navigator.clipboard.writeText(this.id);
|
||||||
});
|
});
|
||||||
this.contextmenu.addbutton("Message user", function () {
|
this.contextmenu.addbutton("Message user", function () {
|
||||||
fetch(this.info.api + "/users/@me/channels", { method: "POST",
|
fetch(this.info.api + "/users/@me/channels", { method: "POST",
|
||||||
|
|
91
index.js
91
index.js
|
@ -18,11 +18,100 @@ app.use("/getupdates",(req, res) => {
|
||||||
res.send(out.mtimeMs+"");
|
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
|
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, '<')
|
||||||
|
.replaceAll(/>/g, '>')
|
||||||
|
.replaceAll(/'/g, ''')
|
||||||
|
.replaceAll(/"/g, '"');
|
||||||
|
}
|
||||||
|
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")){
|
if(debugging&&req.path.startsWith("/service.js")){
|
||||||
res.send("console.log(\"Hi :3\");");
|
res.send("console.log(\"Hi :3\");");
|
||||||
return;
|
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}`)) {
|
if(fs.existsSync(`${__dirname}/webpage${req.path}`)) {
|
||||||
res.sendFile(`./webpage${req.path}`, {root: __dirname});
|
res.sendFile(`./webpage${req.path}`, {root: __dirname});
|
||||||
}else if(req.path.endsWith(".js") && fs.existsSync(`${__dirname}/.dist${req.path}`)){
|
}else if(req.path.endsWith(".js") && fs.existsSync(`${__dirname}/.dist${req.path}`)){
|
||||||
|
|
|
@ -73,6 +73,63 @@ class Channel{
|
||||||
this.contextmenu.addbutton("Edit channel",function(){
|
this.contextmenu.addbutton("Edit channel",function(){
|
||||||
this.editChannel(this);
|
this.editChannel(this);
|
||||||
},null,_=>{return _.isAdmin()});
|
},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(){
|
generateSettings(){
|
||||||
this.sortPerms();
|
this.sortPerms();
|
||||||
|
|
1
webpage/icons/copy.svg
Normal file
1
webpage/icons/copy.svg
Normal 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
22
webpage/invite.html
Normal 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
118
webpage/invite.ts
Normal 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);
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">Login</button>
|
<button type="submit">Login</button>
|
||||||
</form>
|
</form>
|
||||||
<a href="/register.html">Don't have an account?</a>
|
<a href="/register.html" id="switch">Don't have an account?</a>
|
||||||
</div>
|
</div>
|
||||||
<script src="/login.js" type="module"></script>
|
<script src="/login.js" type="module" ></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { Dialog } from "./dialog.js";
|
import { Dialog } from "./dialog.js";
|
||||||
|
|
||||||
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
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(){
|
function setTheme(){
|
||||||
const name=localStorage.getItem("theme");
|
let name=localStorage.getItem("theme");
|
||||||
if(!name){
|
if(!name){
|
||||||
document.body.className="Dark-theme";
|
document.body.className="Dark-theme";
|
||||||
localStorage.setItem("theme","Dark");
|
localStorage.setItem("theme","Dark");
|
||||||
|
name="Dark";
|
||||||
}
|
}
|
||||||
document.body.className=name+"-theme";
|
document.body.className=name+"-theme";
|
||||||
}
|
}
|
||||||
|
@ -18,6 +19,7 @@ function getBulkUsers(){
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBulkInfo(){
|
function getBulkInfo(){
|
||||||
return JSON.parse(localStorage.getItem("userinfos"));
|
return JSON.parse(localStorage.getItem("userinfos"));
|
||||||
}
|
}
|
||||||
|
@ -115,12 +117,39 @@ function adduser(user){
|
||||||
info.users[user.uid]=user;
|
info.users[user.uid]=user;
|
||||||
info.currentuser=user.uid;
|
info.currentuser=user.uid;
|
||||||
localStorage.setItem("userinfos",JSON.stringify(info));
|
localStorage.setItem("userinfos",JSON.stringify(info));
|
||||||
|
return user;
|
||||||
}
|
}
|
||||||
const instancein=document.getElementById("instancein");
|
const instancein=document.getElementById("instancein") as HTMLInputElement;
|
||||||
let timeout;
|
let timeout;
|
||||||
let instanceinfo;
|
let instanceinfo;
|
||||||
async function checkInstance(e){
|
async function getapiurls(str:string):Promise<{api:string,cdn:string,gateway:string,wellknown:string}|false>{
|
||||||
const verify=document.getElementById("verify");;
|
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{
|
try{
|
||||||
verify.textContent="Checking Instance";
|
verify.textContent="Checking Instance";
|
||||||
const instanceinfo=await setInstance((instancein as HTMLInputElement).value);
|
const instanceinfo=await setInstance((instancein as HTMLInputElement).value);
|
||||||
|
@ -150,8 +179,8 @@ if(instancein){
|
||||||
}else{
|
}else{
|
||||||
checkInstance("https://spacebar.chat/");
|
checkInstance("https://spacebar.chat/");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
async function login(username:string, password:string, captcha:string){
|
async function login(username:string, password:string, captcha:string){
|
||||||
if(captcha===""){
|
if(captcha===""){
|
||||||
|
@ -215,15 +244,27 @@ async function login(username:string, password:string, captcha:string){
|
||||||
if(response.message){
|
if(response.message){
|
||||||
alert(response.message)
|
alert(response.message)
|
||||||
}else{
|
}else{
|
||||||
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token});
|
console.warn(response);
|
||||||
window.location.href = '/channels/@me';
|
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();
|
}]]).show();
|
||||||
}else{
|
}else{
|
||||||
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token});
|
console.warn(response);
|
||||||
window.location.href = '/channels/@me';
|
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token}).username=username;
|
||||||
return response.token;
|
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};
|
export {checkInstance};
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="dontgrow">Create account</button>
|
<button type="submit" class="dontgrow">Create account</button>
|
||||||
</form>
|
</form>
|
||||||
<a href="/login.html">Already have an account?</a>
|
<a href="/login.html" id="switch">Already have an account?</a>
|
||||||
</div>
|
</div>
|
||||||
<script src="/register.js" type="module"></script>
|
<script src="/register.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {checkInstance} from "./login.js";
|
import {checkInstance, adduser} from "./login.js";
|
||||||
if(document.getElementById("register")){
|
if(document.getElementById("register")){
|
||||||
document.getElementById("register").addEventListener("submit", registertry);
|
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;
|
document.getElementById("wrong").textContent=e.errors[Object.keys(e.errors)[0]]._errors[0].message;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:email,token:e.token}).username=username;
|
||||||
localStorage.setItem("token",e.token);
|
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';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1751,4 +1751,71 @@ form div{
|
||||||
}
|
}
|
||||||
.reactiondiv{
|
.reactiondiv{
|
||||||
margin-left: .45in;
|
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;
|
||||||
}
|
}
|
|
@ -49,8 +49,8 @@ class User{
|
||||||
}
|
}
|
||||||
static contextmenu:Contextmenu=new Contextmenu("User Menu");
|
static contextmenu:Contextmenu=new Contextmenu("User Menu");
|
||||||
static setUpContextMenu(){
|
static setUpContextMenu(){
|
||||||
this.contextmenu.addbutton("Copy user id",function(){
|
this.contextmenu.addbutton("Copy user id",function(this:User){
|
||||||
navigator.clipboard.writeText(this.id.id);
|
navigator.clipboard.writeText(this.id);
|
||||||
});
|
});
|
||||||
this.contextmenu.addbutton("Message user",function(){
|
this.contextmenu.addbutton("Message user",function(){
|
||||||
fetch(this.info.api+"/users/@me/channels",
|
fetch(this.info.api+"/users/@me/channels",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue