128 lines
3 KiB
TypeScript
128 lines
3 KiB
TypeScript
import {Request, Response} from "express";
|
|
import {instace} from "./index.js";
|
|
interface ApiUrls {
|
|
api: string;
|
|
gateway: string;
|
|
cdn: string;
|
|
wellknown: string;
|
|
}
|
|
|
|
interface Invite {
|
|
guild: {
|
|
name: string;
|
|
description?: string;
|
|
icon?: string;
|
|
id: string;
|
|
};
|
|
inviter?: {
|
|
username: string;
|
|
};
|
|
}
|
|
|
|
export async function getApiUrls(
|
|
url: string,
|
|
instances: instace[],
|
|
check = true,
|
|
): Promise<ApiUrls | null> {
|
|
if (!url.endsWith("/")) {
|
|
url += "/";
|
|
}
|
|
if (check) {
|
|
let valid = false;
|
|
for (const instace of instances) {
|
|
const urlstr = instace.url || instace.urls?.api;
|
|
if (!urlstr) {
|
|
continue;
|
|
}
|
|
try {
|
|
if (new URL(urlstr).host === new URL(url).host) {
|
|
valid = true;
|
|
break;
|
|
}
|
|
} catch (e) {
|
|
//console.log(e);
|
|
}
|
|
}
|
|
if (!valid) {
|
|
throw new Error("Invalid instance");
|
|
}
|
|
}
|
|
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: policies.apiEndpoint,
|
|
gateway: policies.gateway,
|
|
cdn: policies.cdn,
|
|
wellknown: url,
|
|
};
|
|
} catch (error) {
|
|
console.error("Error fetching API URLs:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function inviteResponse(
|
|
req: Request,
|
|
res: Response,
|
|
instances: instace[],
|
|
): Promise<void> {
|
|
let url: URL;
|
|
try {
|
|
url = new URL(req.query.url as string);
|
|
} catch {
|
|
const scheme = req.secure ? "https" : "http";
|
|
const host = `${scheme}://${req.get("Host")}`;
|
|
url = new URL(host);
|
|
}
|
|
|
|
try {
|
|
if (!url.pathname.startsWith("invite") && !url.pathname.startsWith("/invite")) {
|
|
throw new Error("Invalid invite URL");
|
|
}
|
|
|
|
const code = url.pathname.split("/")[2];
|
|
const instance = url.searchParams.get("instance");
|
|
if (!instance) {
|
|
throw new Error("Instance not specified");
|
|
}
|
|
|
|
const urls = await getApiUrls(instance, instances);
|
|
if (!urls) {
|
|
throw new Error("Failed to get API URLs");
|
|
}
|
|
|
|
const invite = await fetch(`${urls.api}/invites/${code}`).then(
|
|
(json) => json.json() as Promise<Invite>,
|
|
);
|
|
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}` : ""}`
|
|
: `You've been invited to ${invite.guild.name}${invite.guild.description ? `\n${invite.guild.description}` : ""}`;
|
|
const thumbnail = invite.guild.icon
|
|
? `${urls.cdn}/icons/${invite.guild.id}/${invite.guild.icon}.png`
|
|
: "";
|
|
|
|
res.json({
|
|
type: "link",
|
|
version: "1.0",
|
|
title,
|
|
thumbnail,
|
|
description,
|
|
});
|
|
} catch (error) {
|
|
//console.error("Error processing invite response:", error);
|
|
res.json({
|
|
type: "link",
|
|
version: "1.0",
|
|
title: "Jank Client",
|
|
thumbnail: "/logo.webp",
|
|
description: "A spacebar client that has DMs, replying and more",
|
|
url: url.toString(),
|
|
});
|
|
}
|
|
}
|