dashboard-core/Routes/discord.js
Jonny_Bro (Nikita) 849a93887a
2023-06-22 19:36:52 +05:00

397 lines
No EOL
8.8 KiB
JavaScript

const router = require("express").Router();
const RL = require("express-rate-limit");
const safeStorage = require("assistants-safe-storage");
const DiscordOauth2 = require("discord-oauth2");
const oauth = new DiscordOauth2();
module.exports = (app, config, themeConfig) => {
const storage = new safeStorage(config.bot.config.token);
const scopes = config.guildAfterAuthorization?.use ? ["identify", "guilds", "guilds.join"] : ["identify", "guilds"];
const RateLimits = config.rateLimits || {};
const RateFunctions = {};
const NoRL = (req, res, next) => next();
if (RateLimits.discordOAuth2) {
RateFunctions.discordOAuth2 = RL.rateLimit({
windowMs: RateLimits.discordOAuth2.windowMs,
max: RateLimits.discordOAuth2.max,
message: RateLimits.discordOAuth2.message,
store: RateLimits.discordOAuth2.store || new RL.MemoryStore(),
});
}
router.get("/", (req, res) => {
const clientId = req.client.id;
const redirectUri = req.redirectUri;
let newPage = "/";
if (themeConfig.landingPage?.enabled) newPage = "/dash";
req.session.r = req.query.r || newPage;
const authorizeUrl = `https://discord.com/api/oauth2/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&scope=${scopes.join("%20")}`;
res.redirect(authorizeUrl);
});
router.get("/status", async (req, res) => {
res.send(req.session?.discordAuthStatus);
});
router.get("/callback", RateFunctions.discordOAuth2 ? RateFunctions.discordOAuth2 : NoRL, async (req, res) => {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: null,
},
};
const clientId = req.client.id;
const clientSecret = req.client.secret;
const redirectUri = req.redirectUri;
const accessCode = req.query.code;
if (!accessCode) return res.redirect("/?error=NoAccessCodeReturnedFromDiscord");
res.redirect("/loading");
let OAuth2Response;
let OAuth2UserResponse;
let OAuth2GuildsResponse;
try {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Requesting token...",
},
};
req.session.save(function () {});
OAuth2Response = await oauth.tokenRequest({
clientId,
clientSecret,
code: accessCode,
scope: scopes.join(" "),
grantType: "authorization_code",
redirectUri,
});
} catch (err) {
console.log("Discord.js Route - OAuth2Response (line 88)\n" + err);
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
return;
}
/*
Get User from Discord OAuth2 API using gained access_token and update its values with tag and avatarURL
*/
try {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Getting User...",
},
};
req.session.save(function () {});
OAuth2UserResponse = await oauth.getUser(OAuth2Response.access_token);
} catch (err) {
console.log("Discord.js Route - OAuth2UserResponse (line 122)\n" + err);
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
return;
}
OAuth2UserResponse.tag = `${OAuth2UserResponse.username}#${OAuth2UserResponse.discriminator}`;
OAuth2UserResponse.avatarURL = OAuth2UserResponse.avatar ? `https://cdn.discordapp.com/avatars/${OAuth2UserResponse.id}/${OAuth2UserResponse.avatar}.png?size=1024` : null;
/*
Save user token in Assistants Secure Storage
*/
try {
storage.SaveUser(OAuth2UserResponse.id, OAuth2Response.access_token);
} catch (err) {
console.log("Discord.js Route - Assistants Secure Storage (line 147)\n" + err);
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
return;
}
/*
Save user in session
*/
req.session.user = OAuth2UserResponse;
req.session.loggedInLastTime = true;
/*
Register user to DBD Stats and emit userLoggedIn event
*/
try {
req.DBDEvents.emit("userLoggedIn", OAuth2UserResponse);
} catch (err) {
console.log("Discord.js Route - DBDStats register and DBDEvent emit userLoggedIn (line 173)\n" + err);
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
return;
}
/*
Gain and update session with user guilds
*/
try {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Getting List of User Guilds...",
},
};
req.session.save(function () {});
OAuth2GuildsResponse = await oauth.getUserGuilds(OAuth2Response.access_token);
} catch (err) {
req.config.reportError("Discord.js Route - OAuth2GuildsResponse (line 205)\n" + err);
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
return;
}
req.session.guilds = OAuth2GuildsResponse || [];
/*
Loop and fetch each guild into bots cache
*/
if (!req.config.disableResolvingGuildCache) {
try {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Resolving guilds cache...",
},
};
req.session.save(function () {});
for (const g of OAuth2GuildsResponse) {
try {
await req.bot.guilds.fetch(g.id);
} catch (e) { /* ... */ }
}
} catch (err) {
console.log("Discord.js Route - OAuth2GuildsResponse Whole Loop (line 244)" + err);
req.session.discordAuthStatus = {
loading: false,
success: false,
state: {
error: err,
data: null,
},
};
req.session.save(function () {});
return;
}
}
/*
If joining specific guild after authorization is enabled, do it
*/
if (req.guildAfterAuthorization.use == true) {
req.session.discordAuthStatus = {
loading: true,
success: null,
state: {
error: null,
data: "Authorizing user with guild...",
},
};
req.session.save(function () {});
try {
await oauth.addMember({
accessToken: OAuth2Response.access_token,
botToken: req.botToken,
guildId: req.guildAfterAuthorization.guildId,
userId: OAuth2UserResponse.id,
...(req.guildAfterAuthorization.options || {}),
/*
options?: {
nickname?: string,
roles?: [string],
mute?: boolean,
deaf?: boolean,
}
*/
});
} catch (err) {
req.config.reportError("Discord.js Route - guildAfterAuthorization (line 295)" + err);
}
}
req.session.discordAuthStatus = {
loading: false,
success: true,
state: {
error: null,
data: null,
},
};
req.session.save(function () {});
return;
});
router.get("/logout", (req, res) => {
const r = req.query.r || "/";
req.session.destroy();
res.redirect(r);
});
router.get("/guilds/reload", async (req, res) => {
if (!req.session.user) return res.redirect("/discord");
/*
Fetch user token
*/
const access_token = storage.GetUser(req.session.user.id);
if (!access_token)
return res.send({
error: true,
message: "You don't have any access_token saved.",
login_again_text: true,
});
/*
Gain and update session with user guilds
*/
let OAuth2GuildsResponse;
try {
OAuth2GuildsResponse = await oauth.getUserGuilds(access_token);
} catch (err) {
req.config.reportError("Discord.js Route - OAuth2GuildsResponse for ReloadGuilds (line 342)" + err);
return res.send({
error: true,
message: "An error occured. Access_token is wrong or you're being rate limited.",
login_again_text: true,
});
}
req.session.guilds = OAuth2GuildsResponse || [];
/*
Loop and fetch each guild into bots cache
*/
try {
const Promises = [];
for (const g of OAuth2GuildsResponse) {
Promises.push(
// eslint-disable-next-line no-unused-vars, no-async-promise-executor
new Promise(async (resolve, reject) => {
try {
await req.bot.guilds.fetch(g.id);
} catch (e) { /* ... */ }
resolve(1);
}),
);
try {
await Promises.all(Promises);
} catch (e) { /* ... */ }
}
} catch (err) {
console.log("Discord.js Route - OAuth2GuildsResponse Whole Loop for ReloadGuilds (line 375)" + err);
return res.send({
error: true,
message: "An error occured. Access_token is wrong or you're being rate limited.",
login_again_text: true,
});
}
/*
Success
*/
return res.send({
error: false,
message: null,
login_again_text: false,
});
});
return router;
};