mirror of
https://github.com/spacebarchat/server.git
synced 2026-09-16 19:22:49 +00:00
Move src-slowcord to own repo https://github.com/MaddyUnderStars/slowcord-services
This commit is contained in:
@@ -25,6 +25,8 @@ export const NO_AUTHORIZATION_ROUTES = [
|
||||
"/track",
|
||||
// Public policy pages
|
||||
"/policies/instance",
|
||||
// Oauth callback
|
||||
"/oauth2/callback",
|
||||
// Asset delivery
|
||||
/\/guilds\/\d+\/widget\.(json|png)/,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route, OauthCallbackHandlers } from "@fosscord/api";
|
||||
import { FieldErrors, generateToken, User } from "@fosscord/util";
|
||||
const router = Router();
|
||||
|
||||
router.get("/:type", route({}), async (req: Request, res: Response) => {
|
||||
const { type } = req.params;
|
||||
const handler = OauthCallbackHandlers[type];
|
||||
if (!handler) throw FieldErrors({
|
||||
type: {
|
||||
code: "BASE_TYPE_CHOICES",
|
||||
message: `Value must be one of (${Object.keys(OauthCallbackHandlers).join(", ")}).`,
|
||||
}
|
||||
});
|
||||
|
||||
const { code } = req.query;
|
||||
if (!code || typeof code !== "string") throw FieldErrors({ code: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED"), } });
|
||||
const access = await handler.getAccessToken(code);
|
||||
|
||||
const oauthUser = await handler.getUserDetals(access.access_token);
|
||||
|
||||
let user = await User.findOne({ where: { email: oauthUser.email } });
|
||||
if (!user) {
|
||||
user = await User.register({
|
||||
email: oauthUser.email,
|
||||
username: oauthUser.username,
|
||||
req
|
||||
});
|
||||
|
||||
// TODO: upload pfp, banner?
|
||||
}
|
||||
|
||||
const token = await generateToken(user.id);
|
||||
|
||||
return { token };
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Attachment, Config, Guild, Message, RateLimit, Session, User } from "@fosscord/util";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
res.json({
|
||||
all_time: {
|
||||
users: await User.count(),
|
||||
guilds: await Guild.count(),
|
||||
messages: await Message.count(),
|
||||
attachments: await Attachment.count(),
|
||||
},
|
||||
now: {
|
||||
sessions: await Session.count(),
|
||||
rate_limits: await RateLimit.count(),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,83 @@
|
||||
// TODO: Puyo's connections PR would replace this file
|
||||
|
||||
import { Config } from "@fosscord/util";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
export interface OauthAccessToken {
|
||||
access_token: string;
|
||||
token_type: string;
|
||||
expires_in: string;
|
||||
refresh_token: string;
|
||||
scope: string;
|
||||
};
|
||||
|
||||
export interface OauthUserDetails {
|
||||
id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
avatar_url: string | null;
|
||||
}
|
||||
|
||||
interface Connection {
|
||||
getAccessToken: (code: string) => Promise<OauthAccessToken>;
|
||||
getUserDetals: (token: string) => Promise<OauthUserDetails>;
|
||||
}
|
||||
|
||||
const DiscordConnection: Connection = {
|
||||
getAccessToken: async (code) => {
|
||||
const { external } = Config.get();
|
||||
const { discord } = external;
|
||||
|
||||
if (!discord.id || !discord.secret || !discord.redirect)
|
||||
throw new Error("Discord Oauth has not been configured.")
|
||||
|
||||
const body = new URLSearchParams(
|
||||
Object.entries({
|
||||
client_id: discord.id as string,
|
||||
client_secret: discord.secret as string,
|
||||
redirect_uri: discord.redirect as string,
|
||||
code: code as string,
|
||||
grant_type: "authorization_code",
|
||||
})
|
||||
).toString();
|
||||
|
||||
const resp = await fetch("https://discord.com/api/oauth2/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: body,
|
||||
});
|
||||
if (resp.status !== 200) throw new Error(`Failed to get access token.`,);
|
||||
|
||||
const json = await resp.json();
|
||||
|
||||
return json;
|
||||
},
|
||||
|
||||
getUserDetals: async (token) => {
|
||||
const resp = await fetch("https://discord.com/api/users/@me", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
});
|
||||
|
||||
const json = await resp.json();
|
||||
if (!json.username || !json.email) throw new Error("Failed to get user details via oauth");
|
||||
|
||||
return {
|
||||
id: json.id,
|
||||
email: json.email,
|
||||
username: json.username,
|
||||
avatar_url: json.avatar
|
||||
? `https://cdn.discordapp.com/avatars/${json.id}/${json.avatar}?size=2048`
|
||||
: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const OauthCallbackHandlers: { [key: string]: Connection; } = {
|
||||
discord: DiscordConnection
|
||||
};
|
||||
|
||||
export { OauthCallbackHandlers };
|
||||
@@ -7,4 +7,5 @@ export * from "./handlers/route";
|
||||
export * from "./utility/String";
|
||||
export * from "./handlers/Voice";
|
||||
export * from "./utility/captcha";
|
||||
export * from "./utility/EmbedHandlers";
|
||||
export * from "./utility/EmbedHandlers";
|
||||
export * from "./handlers/Oauth";
|
||||
@@ -211,7 +211,12 @@ export interface ConfigValue {
|
||||
};
|
||||
external: {
|
||||
twitter: string | null;
|
||||
}
|
||||
discord: {
|
||||
id: string | null;
|
||||
secret: string | null;
|
||||
redirect: string | null;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export const DefaultConfigOptions: ConfigValue = {
|
||||
@@ -423,5 +428,10 @@ export const DefaultConfigOptions: ConfigValue = {
|
||||
},
|
||||
external: {
|
||||
twitter: null,
|
||||
discord: {
|
||||
id: null,
|
||||
secret: null,
|
||||
redirect: null,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
import { PublicUser, User, UserSettings } from "../entities/User";
|
||||
import { Channel } from "../entities/Channel";
|
||||
import { Guild } from "../entities/Guild";
|
||||
import { Member, PublicMember, UserGuildSettings } from "../entities/Member";
|
||||
import { Emoji } from "../entities/Emoji";
|
||||
import { Role } from "../entities/Role";
|
||||
import { Invite } from "../entities/Invite";
|
||||
import { Message, PartialEmoji } from "../entities/Message";
|
||||
import { VoiceState } from "../entities/VoiceState";
|
||||
import { ApplicationCommand } from "../entities/Application";
|
||||
import { Interaction } from "./Interaction";
|
||||
import { ConnectedAccount } from "../entities/ConnectedAccount";
|
||||
import { Relationship, RelationshipType } from "../entities/Relationship";
|
||||
import { Presence } from "./Presence";
|
||||
import { Sticker } from "..";
|
||||
import { Activity, Status } from ".";
|
||||
import {
|
||||
RelationshipType,
|
||||
ConnectedAccount,
|
||||
Interaction,
|
||||
ApplicationCommand,
|
||||
VoiceState,
|
||||
Message,
|
||||
PartialEmoji,
|
||||
Invite,
|
||||
Role,
|
||||
Emoji,
|
||||
PublicMember,
|
||||
UserGuildSettings,
|
||||
Guild,
|
||||
Channel,
|
||||
PublicUser,
|
||||
User,
|
||||
Sticker,
|
||||
Activity,
|
||||
Status,
|
||||
Presence,
|
||||
UserSettings,
|
||||
} from "@fosscord/util";
|
||||
|
||||
export interface Event {
|
||||
guild_id?: string;
|
||||
@@ -73,9 +80,9 @@ export interface ReadyEventData {
|
||||
number,
|
||||
null,
|
||||
number,
|
||||
[[number, { e: number; s: number }[]]],
|
||||
[[number, { e: number; s: number; }[]]],
|
||||
[number, [[number, [number, number]]]],
|
||||
{ b: number; k: bigint[] }[],
|
||||
{ b: number; k: bigint[]; }[],
|
||||
][];
|
||||
guild_join_requests?: any[]; // ? what is this? this is new
|
||||
shard?: [number, number];
|
||||
@@ -473,7 +480,7 @@ export interface SessionsReplace extends Event {
|
||||
export interface GuildMemberListUpdate extends Event {
|
||||
event: "GUILD_MEMBER_LIST_UPDATE";
|
||||
data: {
|
||||
groups: { id: string; count: number }[];
|
||||
groups: { id: string; count: number; }[];
|
||||
guild_id: string;
|
||||
id: string;
|
||||
member_count: number;
|
||||
@@ -481,8 +488,8 @@ export interface GuildMemberListUpdate extends Event {
|
||||
ops: {
|
||||
index: number;
|
||||
item: {
|
||||
member?: PublicMember & { presence: Presence };
|
||||
group?: { id: string; count: number }[];
|
||||
member?: PublicMember & { presence: Presence; };
|
||||
group?: { id: string; count: number; }[];
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user