discord.ts 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { Request as ExpressRequest, Response as ExpressResponse } from "express";
  2. import { DiscordAPI } from "src/utils/util";
  3. import { Option, tryDo } from "@shared/common/async_utils";
  4. import { eventLogger, logger } from "src/utils/logging";
  5. import { rpcClient } from "src/utils/rpc";
  6. import { ENV } from "src/utils/environment";
  7. export const get = async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
  8. eventLogger.info("Login attempt from %s; UA: %s", req.ip, req.get("user-agent"));
  9. res.redirect(DiscordAPI.getAuthUrl({
  10. client_id: ENV.BOT_CLIENT_ID,
  11. redirect_url: ENV.WEB_AUTH_URI,
  12. response_type: "code",
  13. scope: "identify",
  14. }));
  15. };
  16. type AuthResult = Option<unknown, {error: string}>;
  17. export const post = async (req: ExpressRequest, res: ExpressResponse):
  18. Promise<ExpressResponse<AuthResult>> => {
  19. if (!req.session) {
  20. logger.warn("WEB: req.session is not set up correctly!");
  21. return res.json({
  22. ok: false,
  23. error: "No session is set up. This is a server error!",
  24. });
  25. }
  26. if (!req.session.authTokenCode) {
  27. logger.warn("WEB: attempted to join with no authTokenCode set!");
  28. eventLogger.warn("IP %s attempted to join with no authTokenCode set", req.ip);
  29. return res.json({
  30. ok: false,
  31. error: "Authentication token is missing. Please try logging in again.",
  32. });
  33. }
  34. const tokenResult = await DiscordAPI.getToken({
  35. client_id: ENV.BOT_CLIENT_ID,
  36. client_secret: ENV.BOT_CLIENT_SECRET,
  37. grant_type: "authorization_code",
  38. code: req.session.authTokenCode,
  39. scope: "identify",
  40. redirect_uri: ENV.WEB_AUTH_URI,
  41. });
  42. if (!tokenResult.ok) {
  43. return res.json(tokenResult);
  44. }
  45. const userResult = await DiscordAPI.getCurrentUser(tokenResult.access_token);
  46. if (!userResult.ok) {
  47. return res.json(userResult);
  48. }
  49. const userInServerResult = await tryDo(rpcClient.userInServer({ userId: userResult.id }));
  50. if (!userInServerResult.ok) {
  51. logger.error("WEB: failed to auth user %s: %s", userResult.id, userInServerResult.error);
  52. return res.json({ ok: false, error: "Couldn't determine if user joined the server, please try again later" });
  53. }
  54. eventLogger.info("%s#%s authed from %s", userResult.username, userResult.discriminator, req.ip);
  55. logger.verbose("Logged in as %s#%s (%s); user in server: (%s)", userResult.username, userResult.discriminator, userResult.id, userInServerResult.result.exists);
  56. if (!userInServerResult.result.exists) {
  57. return res.json({ ok: false, error: "You haven't joined any servers NoctBot manages! Please join first and try again!" });
  58. }
  59. req.session.authTokenCode = undefined;
  60. req.session.userId = userResult.id;
  61. req.session.avatarId = userResult.avatar;
  62. req.session.username = `${userResult.username}#${userResult.discriminator}`;
  63. req.sessionOptions.maxAge = tokenResult.expires_in;
  64. return res.json({
  65. ok: true,
  66. });
  67. };