diff --git a/package.json b/package.json index 6a84ff6..ded9520 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,11 @@ "lefthook": "^1.8.4", "libsodium-wrappers": "^0.7.15", "prism-media": "1.3.5", - "prisma": "^5.22.0", + "prisma": "^6.0.0", "typescript": "^5.6.3" }, "dependencies": { - "@prisma/client": "5.9.1" + "@prisma/client": "6.0.0" }, "volta": { "node": "21.6.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7acc7f5..ce8da76 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@prisma/client': - specifier: 5.9.1 - version: 5.9.1(prisma@5.22.0) + specifier: 6.0.0 + version: 6.0.0(prisma@6.0.0) devDependencies: '@biomejs/biome': @@ -65,8 +65,8 @@ devDependencies: specifier: 1.3.5 version: 1.3.5(@discordjs/opus@0.9.0) prisma: - specifier: ^5.22.0 - version: 5.22.0 + specifier: ^6.0.0 + version: 6.0.0 typescript: specifier: ^5.6.3 version: 5.6.3 @@ -513,9 +513,9 @@ packages: fastq: 1.17.1 dev: true - /@prisma/client@5.9.1(prisma@5.22.0): - resolution: {integrity: sha512-caSOnG4kxcSkhqC/2ShV7rEoWwd3XrftokxJqOCMVvia4NYV/TPtJlS9C2os3Igxw/Qyxumj9GBQzcStzECvtQ==} - engines: {node: '>=16.13'} + /@prisma/client@6.0.0(prisma@6.0.0): + resolution: {integrity: sha512-tOBhG35ozqZ/5Y6B0TNOa6cwULUW8ijXqBXcgb12bfozqf6eGMyGs+jphywCsj6uojv5lAZZnxVSoLMVebIP+g==} + engines: {node: '>=18.18'} requiresBuild: true peerDependencies: prisma: '*' @@ -523,35 +523,35 @@ packages: prisma: optional: true dependencies: - prisma: 5.22.0 + prisma: 6.0.0 dev: false - /@prisma/debug@5.22.0: - resolution: {integrity: sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==} + /@prisma/debug@6.0.0: + resolution: {integrity: sha512-eUjoNThlDXdyJ1iQ2d7U6aTVwm59EwvODb5zFVNJEokNoSiQmiYWNzZIwZyDmZ+j51j42/0iTaHIJ4/aZPKFRg==} - /@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2: - resolution: {integrity: sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==} + /@prisma/engines-version@5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e: + resolution: {integrity: sha512-JmIds0Q2/vsOmnuTJYxY4LE+sajqjYKhLtdOT6y4imojqv5d/aeVEfbBGC74t8Be1uSp0OP8lxIj2OqoKbLsfQ==} - /@prisma/engines@5.22.0: - resolution: {integrity: sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==} + /@prisma/engines@6.0.0: + resolution: {integrity: sha512-ZZCVP3q22ifN6Ex6C8RIcTDBlRtMJS2H1ljV0knCiWNGArvvkEbE88W3uDdq/l4+UvyvHpGzdf9ZsCWSQR7ZQQ==} requiresBuild: true dependencies: - '@prisma/debug': 5.22.0 - '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 - '@prisma/fetch-engine': 5.22.0 - '@prisma/get-platform': 5.22.0 + '@prisma/debug': 6.0.0 + '@prisma/engines-version': 5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e + '@prisma/fetch-engine': 6.0.0 + '@prisma/get-platform': 6.0.0 - /@prisma/fetch-engine@5.22.0: - resolution: {integrity: sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==} + /@prisma/fetch-engine@6.0.0: + resolution: {integrity: sha512-j2m+iO5RDPRI7SUc7sHo8wX7SA4iTkJ+18Sxch8KinQM46YiCQD1iXKN6qU79C1Fliw5Bw/qDyTHaTsa3JMerA==} dependencies: - '@prisma/debug': 5.22.0 - '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 - '@prisma/get-platform': 5.22.0 + '@prisma/debug': 6.0.0 + '@prisma/engines-version': 5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e + '@prisma/get-platform': 6.0.0 - /@prisma/get-platform@5.22.0: - resolution: {integrity: sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==} + /@prisma/get-platform@6.0.0: + resolution: {integrity: sha512-PS6nYyIm9g8C03E4y7LknOfdCw/t2KyEJxntMPQHQZCOUgOpF82Ma60mdlOD08w90I3fjLiZZ0+MadenR3naDQ==} dependencies: - '@prisma/debug': 5.22.0 + '@prisma/debug': 6.0.0 /@protobufjs/aspromise@1.1.2: resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -1765,13 +1765,13 @@ packages: '@discordjs/opus': 0.9.0 dev: true - /prisma@5.22.0: - resolution: {integrity: sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==} - engines: {node: '>=16.13'} + /prisma@6.0.0: + resolution: {integrity: sha512-RX7KtbW7IoEByf7MR32JK1PkVYLVYFqeODTtiIX3cqekq1aKdsF3Eud4zp2sUShMLjvdb5Jow0LbUjRq5LVxPw==} + engines: {node: '>=18.18'} hasBin: true requiresBuild: true dependencies: - '@prisma/engines': 5.22.0 + '@prisma/engines': 6.0.0 optionalDependencies: fsevents: 2.3.3 diff --git a/prisma/migrations/20241130131415_/migration.sql b/prisma/migrations/20241130131415_/migration.sql new file mode 100644 index 0000000..735c2b4 --- /dev/null +++ b/prisma/migrations/20241130131415_/migration.sql @@ -0,0 +1,6 @@ +-- CreateTable +CREATE TABLE "Connections" ( + "guildId" TEXT NOT NULL PRIMARY KEY, + "voiceChannelId" TEXT NOT NULL, + "textChannelId" TEXT NOT NULL +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 33b2fa0..6550686 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -25,3 +25,9 @@ model Dictionary { @@unique([guildId, word]) } + +model Connections { + guildId String @id + voiceChannelId String + textChannelId String +} diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 71cbab3..a37fa2f 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -8,11 +8,40 @@ import manifest from "../../.github/release-please/.release-please-manifest.json type: "json", }; import { initCommands } from "../commands/init.js"; -import { client } from "../index.js"; +import { client, gateway } from "../index.js"; +import { prisma } from "../index.js"; +import Room from "../voice/room.js"; export default async ({ api }: ToEventProps) => { await initCommands(api); + const connections = await prisma.connections.findMany(); + + await Promise.all( + connections.map(async (connection) => { + await new Room( + gateway, + api, + connection.voiceChannelId, + connection.textChannelId, + connection.guildId, + ) + .connect() + .catch(console.error); + await api.channels.createMessage(connection.textChannelId, { + embeds: [ + { + description: "接続しました(再起動が終了しました)", + color: 0x00ff00, + }, + ], + }); + await prisma.connections.delete({ + where: { guildId: connection.guildId }, + }); + }), + ); + console.log("ready!"); client.updatePresence(0, { diff --git a/src/index.ts b/src/index.ts index 6dd7547..bdeba5d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import { WebSocketManager } from "@discordjs/ws"; import { PrismaClient } from "@prisma/client"; import "dotenv/config"; import handlers from "./handlers/index.js"; +import { roomManager } from "./voice/room.js"; if (!process.env["token"]) { process.exit(1); @@ -22,6 +23,38 @@ const gateway = new WebSocketManager({ }); const client = new Client({ rest, gateway }); const prisma = new PrismaClient(); +const handleExit = async () => { + await Promise.all( + [...roomManager.values()].map(async (room) => { + await room.destroy(); + await room.api.channels.createMessage(room.textChannelId, { + embeds: [ + { + description: + "Bot が再起動されるためボイスチャンネルから切断しました.再起動後に再接続されます.", + color: 0xff0000, + }, + ], + }); + await prisma.connections.upsert({ + create: { + guildId: room.guildId, + textChannelId: room.textChannelId, + voiceChannelId: room.voiceChannelId, + }, + update: { + textChannelId: room.textChannelId, + voiceChannelId: room.voiceChannelId, + }, + where: { + guildId: room.guildId, + }, + }); + }), + ); + + process.exit(0); +}; for (const [event, fn] of Object.entries(handlers)) { client.on( @@ -33,4 +66,12 @@ for (const [event, fn] of Object.entries(handlers)) { await gateway.connect(); await prisma.$connect(); +process.on("SIGINT", handleExit); +process.on("SIGTERM", handleExit); +process.on("uncaughtException", async (e) => { + await handleExit(); + console.error("uncaught: %o", e); + process.exit(1); +}); + export { gateway, prisma, client };