rpc.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import express from "express";
  2. import { createServer } from "http";
  3. import { ModuleRpcServer } from "rpc_ts/lib/server";
  4. import { ModuleRpcProtocolServer } from "rpc_ts/lib/protocol/server";
  5. import { NoctBotService } from "@shared/rpc/backend";
  6. import { eventLogger, logger } from "./logging";
  7. import { client } from "./client";
  8. import { tryDo } from "@shared/common/async_utils";
  9. import { getRepository } from "typeorm";
  10. import { GuildVerification } from "@shared/db/entity/GuildVerification";
  11. import { isAuthorisedAsync } from "./util";
  12. import { GuildMember } from "discord.js";
  13. const PORT = +(process.env.RPC_PORT ?? "8181");
  14. const app = express();
  15. async function checkUser(action: string, userId: string, check: (user: GuildMember, verification: GuildVerification) => Promise<boolean>): Promise<boolean> {
  16. const verificationGuildRepo = getRepository(GuildVerification);
  17. const guilds = await verificationGuildRepo.find({
  18. select: [
  19. "guildId",
  20. "verifiedRoleId",
  21. ]
  22. });
  23. for (const guild of guilds) {
  24. const guildInstance = await tryDo(client.bot.guilds.fetch(guild.guildId));
  25. if (!guildInstance.ok) {
  26. logger.error("Failed to fetch guild instance for guild %s: %s", guild.guildId, guildInstance.error);
  27. continue;
  28. }
  29. const user = await tryDo(guildInstance.result.members.fetch(userId));
  30. if (!user.ok) {
  31. const userInfo = await tryDo(client.bot.users.fetch(userId));
  32. const userName = userInfo.ok ? `${userInfo.result.username}#${userInfo.result.discriminator}` : "???";
  33. logger.warn("Couldn't %s for user %s (%s) on server %s because: %s", action, userId, userName, guild.guildId, user.error);
  34. }
  35. if (user.ok && await check(user.result, guild)) {
  36. return true;
  37. }
  38. }
  39. return false;
  40. }
  41. const handler: ModuleRpcServer.ServiceHandlerFor<typeof NoctBotService> = {
  42. async getPing({ ping }): Promise<{ text: string }> {
  43. return { text: `pong: ${ping}` };
  44. },
  45. async userInServer({ userId }): Promise<{ exists: boolean }> {
  46. return { exists: await checkUser("check access" ,userId, async () => true) };
  47. },
  48. async userAuthorised({ userId }): Promise<{ authorised: boolean }> {
  49. return { authorised: await checkUser("check auth", userId, (user) => isAuthorisedAsync(user)) };
  50. },
  51. async userVerified({ userId }): Promise<{ verified: boolean }> {
  52. return { verified: await checkUser("check verified", userId, async (user, guild) => user.roles.cache.has(guild.verifiedRoleId)) };
  53. },
  54. async verifyUser({ userId }): Promise<{ ok: boolean }> {
  55. return { ok: !(await checkUser("verify", userId, async (user, guild) => {
  56. const result = await tryDo(user.roles.add(guild.verifiedRoleId));
  57. if (result.ok) {
  58. eventLogger.info("Verifying user %s#%s (%s)", user.user.username, user.user.discriminator, user.user.id);
  59. logger.info("Verifying user %s#%s (%s) on guild %s", user.user.username, user.user.discriminator, user.user.id, guild.guildId);
  60. } else {
  61. eventLogger.warn("Failed to verify user %s#%s (%s): %s", user.user.username, user.user.discriminator, user.user.id, result.error);
  62. logger.warn("Failed to verify user %s#%s (%s) on guild %s: %s", user.user.username, user.user.discriminator, user.user.id, guild.guildId, result.error);
  63. }
  64. return !result.ok;
  65. }))};
  66. }
  67. };
  68. app.use(ModuleRpcProtocolServer.registerRpcRoutes(NoctBotService, handler));
  69. export function startRpcServer(): void {
  70. logger.info(`Starting RPC at *:${PORT}`);
  71. createServer(app).listen(PORT);
  72. }