rpc.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. import { GuildViolationSettings } from "@shared/db/entity/GuildViolationSettings";
  14. const PORT = +(process.env.RPC_PORT ?? "8181");
  15. const app = express();
  16. async function checkUser(action: string, userId: string, check: (user: GuildMember, verification: GuildVerification) => Promise<boolean>): Promise<boolean> {
  17. const verificationGuildRepo = getRepository(GuildVerification);
  18. const guilds = await verificationGuildRepo.find({
  19. select: [
  20. "guildId",
  21. "verifiedRoleId",
  22. ]
  23. });
  24. for (const guild of guilds) {
  25. const guildInstance = await tryDo(client.bot.guilds.fetch(guild.guildId));
  26. if (!guildInstance.ok) {
  27. logger.error("Failed to fetch guild instance for guild %s: %s", guild.guildId, guildInstance.error);
  28. continue;
  29. }
  30. const user = await tryDo(guildInstance.result.members.fetch(userId));
  31. if (!user.ok) {
  32. const userInfo = await tryDo(client.bot.users.fetch(userId));
  33. const userName = userInfo.ok ? `${userInfo.result.username}#${userInfo.result.discriminator}` : "???";
  34. logger.warn("Couldn't %s for user %s (%s) on server %s because: %s", action, userId, userName, guild.guildId, user.error);
  35. }
  36. if (user.ok && await check(user.result, guild)) {
  37. return true;
  38. }
  39. }
  40. return false;
  41. }
  42. async function userMuted(user: GuildMember, guild: GuildVerification): Promise<boolean> {
  43. const violationSettingsRepo = await getRepository(GuildViolationSettings);
  44. const settings = await violationSettingsRepo.findOne(guild.guildId);
  45. if (!settings?.muteRoleId) {
  46. return false;
  47. }
  48. return user.roles.cache.has(settings.muteRoleId);
  49. }
  50. const handler: ModuleRpcServer.ServiceHandlerFor<typeof NoctBotService> = {
  51. async getPing({ ping }): Promise<{ text: string }> {
  52. return { text: `pong: ${ping}` };
  53. },
  54. async userInServer({ userId }): Promise<{ exists: boolean }> {
  55. return { exists: await checkUser("check access" ,userId, async () => true) };
  56. },
  57. async userAuthorised({ userId }): Promise<{ authorised: boolean }> {
  58. return { authorised: await checkUser("check auth", userId, (user) => isAuthorisedAsync(user)) };
  59. },
  60. async userVerified({ userId }): Promise<{ verified: boolean }> {
  61. // Prevent muted users from gaining verified role back
  62. return { verified: await checkUser("check verified", userId, async (user, guild) => user.roles.cache.has(guild.verifiedRoleId) || await userMuted(user, guild)) };
  63. },
  64. async verifyUser({ userId }): Promise<{ ok: boolean }> {
  65. return { ok: !(await checkUser("verify", userId, async (user, guild) => {
  66. if (await userMuted(user, guild)) {
  67. logger.info("Muted user %s#%s (%s) tried to re-verify in guild %s", user.user.username, user.user.discriminator, user.user.id, guild.guildId);
  68. return false;
  69. }
  70. const result = await tryDo(user.roles.add(guild.verifiedRoleId));
  71. if (result.ok) {
  72. eventLogger.info("Verifying user %s#%s (%s)", user.user.username, user.user.discriminator, user.user.id);
  73. logger.info("Verifying user %s#%s (%s) on guild %s", user.user.username, user.user.discriminator, user.user.id, guild.guildId);
  74. } else {
  75. eventLogger.warn("Failed to verify user %s#%s (%s): %s", user.user.username, user.user.discriminator, user.user.id, result.error);
  76. 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);
  77. }
  78. return !result.ok;
  79. }))};
  80. }
  81. };
  82. app.use(ModuleRpcProtocolServer.registerRpcRoutes(NoctBotService, handler));
  83. export function startRpcServer(): void {
  84. logger.info(`Starting RPC at *:${PORT}`);
  85. createServer(app).listen(PORT);
  86. }