diff --git a/app/api/subs/route.ts b/app/api/subs/route.ts index 0424710..a9aa833 100644 --- a/app/api/subs/route.ts +++ b/app/api/subs/route.ts @@ -1,8 +1,8 @@ import { getAuthTokenOrNull } from '@/helpers/oauth/helpers' -import guildProfileSchema from '@/models/Guild' import { NextResponse } from 'next/server' import connectDb from '@/lib/mongodb' import { stripe } from '@/lib/stripe' +import { prisma } from '@/lib/prisma' interface StripeSubscriptionRequest { monthly: string @@ -27,7 +27,14 @@ export async function POST(req: Request) { const { priceId, serverId, monthly } = (await req.json()) as StripeSubscriptionRequest - const server = await guildProfileSchema.findOne({ guildID: serverId }) + const server = await prisma.guild.findFirst({ + where: { + guildID: serverId + }, + select: { + premiumExpiration: true + } + }) if (!serverId) { return NextResponse.json( diff --git a/app/api/webhook/route.ts b/app/api/webhook/route.ts index 62e5614..2bcff17 100644 --- a/app/api/webhook/route.ts +++ b/app/api/webhook/route.ts @@ -1,7 +1,7 @@ -import guildProfileSchema from '@/models/Guild' import type { NextRequest } from 'next/server' import { NextResponse } from 'next/server' import { stripe } from '@/lib/stripe' +import { prisma } from '@/lib/prisma' import type Stripe from 'stripe' export async function POST(request: NextRequest) { @@ -47,18 +47,29 @@ export async function POST(request: NextRequest) { ) } try { - await guildProfileSchema.findOneAndUpdate( - { guildID: serverId }, - { + await prisma.guild.upsert({ + where: { + guildID: serverId + }, + create: { guildID: serverId, premiumUser: userId, premium: 1, + pending: true, premiumExpiration: new Date( subscription.current_period_end * 1000 - ) + ), + language: 'en_US' }, - { upsert: true } - ) + update: { + premiumUser: userId, + premium: 1, + pending: true, + premiumExpiration: new Date( + subscription.current_period_end * 1000 + ) + } + }) } catch (error) { console.error(error) return NextResponse.json( @@ -71,6 +82,84 @@ export async function POST(request: NextRequest) { } break + case 'invoice.paid': + case 'invoice.payment_succeeded': + const invoice: Stripe.Invoice = event.data.object + + if (invoice.subscription_details === null) + return NextResponse.json( + { message: 'No subscription details found', status: 400 }, + { status: 400 } + ) + + const userIdInvoice = invoice.subscription_details.metadata?.userId + const serverIdInvoice = invoice.subscription_details.metadata?.serverId + const tierInvoice = + invoice.subscription_details.metadata?.monthly === 'true' ? + 'monthly' + : 'yearly' + + if (!userIdInvoice || !serverIdInvoice || !tierInvoice) { + console.error('One or more variables are undefined.') + return NextResponse.json( + { message: 'One or more variables are missing', status: 400 }, + { status: 400 } + ) + } + switch (invoice.billing_reason) { + case 'subscription_create': + try { + await prisma.guild.update({ + // @ts-ignore + where: { + guildID: serverIdInvoice + }, + data: { + pending: false, + premiumExpiration: new Date( + invoice.lines.data[0].period.end * 1000 + ) + } + }) + } catch (error) { + console.error(error) + return NextResponse.json( + { + message: 'An error occurred while updating the database.', + status: 500 + }, + { status: 500 } + ) + } + break + case 'subscription_update': + try { + await prisma.guild.update({ + // @ts-ignore + where: { + guildID: serverIdInvoice + }, + data: { + pending: false, + premiumExpiration: new Date( + invoice.lines.data[0].period.end * 1000 + ) + } + }) + } catch (error) { + console.error(error) + return NextResponse.json( + { + message: 'An error occurred while updating the database.', + status: 500 + }, + { status: 500 } + ) + } + break + } + break + // in the event of a subscription being updated case 'customer.subscription.updated': const subscriptionUpdated: Stripe.Subscription = event.data.object @@ -89,16 +178,19 @@ export async function POST(request: NextRequest) { ) } - await guildProfileSchema.findOneAndUpdate( - { guildID: serverIdUpdated }, - { + await prisma.guild.update({ + // @ts-ignore + where: { + guildID: serverIdUpdated + }, + data: { premium: 1, premiumExpiration: new Date( subscriptionUpdated.current_period_end * 1000 ) - }, - { upsert: true } - ) + } + }) + break // in the event of a subscription being deleted @@ -119,14 +211,17 @@ export async function POST(request: NextRequest) { ) } try { - await guildProfileSchema.findOneAndUpdate( - { guildID: serverIdDeleted }, - { - premiumUser: null, + await prisma.guild.update({ + // @ts-ignore + where: { + guildID: serverIdDeleted + }, + data: { premium: 0, - premiumExpiration: null + premiumExpiration: null, + premiumUser: null } - ) + }) } catch (error) { console.error(error) return NextResponse.json( diff --git a/app/commands/page.tsx b/app/commands/page.tsx index 4bc3458..fbbe758 100644 --- a/app/commands/page.tsx +++ b/app/commands/page.tsx @@ -1,182 +1,34 @@ -// TODO remove the use client directive in favor of a server component -'use client' - -import CopyCommandWrapper from '@/components/CopyCommand' -import { useEffect, useRef, useState } from 'react' -import commands from '../../data/commands.json' -import Head from 'next/head' -import Link from 'next/link' - -export default function Commands() { - interface Command { - name: string - description: string - usage: string - category: string[] - subcommands?: string[] - options?: string[] - } - - const [openedCommand, setOpenedCommand] = useState('') - const [searchTerm, setSearchTerm] = useState('') - const [filteredCommands, setFilteredCommands] = useState( - commands as object as Command[] - ) - const timeoutRef = useRef(null) - - useEffect(() => { - const performSearch = () => { - const lowerCaseTerm = searchTerm.toLowerCase() - - const filtered = commands.filter( - (command) => - command.name.toLowerCase().includes(lowerCaseTerm) || - command.description.toLowerCase().includes(lowerCaseTerm) - ) - - setFilteredCommands(filtered as object as Command[]) - } - - if (timeoutRef.current) { - clearTimeout(timeoutRef.current) - } - - timeoutRef.current = setTimeout(performSearch, 500) - }, [searchTerm]) - - const handleSearchChange = (event: React.ChangeEvent) => { - setSearchTerm(event.target.value) +import Content from '@/components/Commands/Content' +import type { Metadata, Viewport } from 'next' + +export const metadata: Metadata = { + metadataBase: new URL('https://wouldyoubot.gg'), + title: 'Commands - Would You Bot', + description: 'All the commands Would You Bot has to offer!', + twitter: { + title: 'Commands - Would You Bot', + description: 'All the commands Would You Bot has to offer!' + }, + openGraph: { + title: 'Commands - Would You Bot', + description: 'All the commands Would You Bot has to offer!' + }, + robots: { + index: true, + follow: true } +} - const categories = ['Settings', 'Utility', 'Games'] +export const viewport: Viewport = { + themeColor: '#0598F6', + maximumScale: 5 +} +export default function Commands() { return ( <>
-

- Commands -

- -
-

- Search for a command -

- - {categories.map((category, index) => { - // Filter commands for the current category - const categoryCommands = filteredCommands.filter((command) => - command.category.includes(category) - ) - - // Render only if there are commands in the category - if (categoryCommands.length > 0) { - return ( -
-

- {category} -

- {categoryCommands.map((command) => { - const isActive = openedCommand === command.name - - return ( -
- isActive ? - setOpenedCommand('') - : setOpenedCommand(command.name) - } - key={command.name} - > -
-
-

- - / - - {command.name} -

-

- {command.description} -

-
-
- - - -
-
-
-
Usage
- - {command.usage} - - {command.subcommands && ( - <> -
Subcommands
-
- {command.subcommands.join(', ')} -
- - )} - {command.options && ( - <> -
Options
-
- {command.options.join(', ')} -
- - )} -
-
- ) - })} -
- ) - } - // If no commands in the category, return null - return null - })} - {filteredCommands.length === 0 && ( -

- No commands for your search were found!{' '} - - Maybe suggest it? - -

- )} -
+
) diff --git a/components/Commands/Content.tsx b/components/Commands/Content.tsx new file mode 100644 index 0000000..8b1e9b0 --- /dev/null +++ b/components/Commands/Content.tsx @@ -0,0 +1,173 @@ +'use client' + +import CopyCommandWrapper from '@/components/CopyCommand' +import { useEffect, useRef, useState } from 'react' +import commands from '../../data/commands.json' +import { Input } from '../ui/input' +import Link from 'next/link' + +export default function Commands() { + interface Command { + name: string + description: string + usage: string + category: string[] + subcommands?: string[] + options?: string[] + } + + const [openedCommand, setOpenedCommand] = useState('') + const [searchTerm, setSearchTerm] = useState('') + const [filteredCommands, setFilteredCommands] = useState( + commands as object as Command[] + ) + const timeoutRef = useRef(null) + + useEffect(() => { + const performSearch = () => { + const lowerCaseTerm = searchTerm.toLowerCase() + + const filtered = commands.filter( + (command) => + command.name.toLowerCase().includes(lowerCaseTerm) || + command.description.toLowerCase().includes(lowerCaseTerm) + ) + + setFilteredCommands(filtered as object as Command[]) + } + + if (timeoutRef.current) { + clearTimeout(timeoutRef.current) + } + + timeoutRef.current = setTimeout(performSearch, 500) + }, [searchTerm]) + + const handleSearchChange = (event: React.ChangeEvent) => { + setSearchTerm(event.target.value) + } + + const categories = ['Settings', 'Utility', 'Games'] + + return ( + <> +

+ Commands +

+
+

+ Search for a command +

+ + {categories.map((category, index) => { + // Filter commands for the current category + const categoryCommands = filteredCommands.filter((command) => + command.category.includes(category) + ) + + // Render only if there are commands in the category + if (categoryCommands.length > 0) { + return ( +
+

+ {category} +

+ {categoryCommands.map((command) => { + const isActive = openedCommand === command.name + + return ( +
+ isActive ? + setOpenedCommand('') + : setOpenedCommand(command.name) + } + key={command.name} + > +
+
+

+ / + {command.name} +

+

+ {command.description} +

+
+
+ + + +
+
+
+
Usage
+ {command.usage} + {command.subcommands && ( + <> +
Subcommands
+
+ {command.subcommands.join(', ')} +
+ + )} + {command.options && ( + <> +
Options
+
+ {command.options.join(', ')} +
+ + )} +
+
+ ) + })} +
+ ) + } + // If no commands in the category, return null + return null + })} + {filteredCommands.length === 0 && ( +

+ No commands for your search were found!{' '} + + Maybe suggest it? + +

+ )} +
+ + ) +} diff --git a/components/Premium/Content.tsx b/components/Premium/Content.tsx index 471e4ca..1d43339 100644 --- a/components/Premium/Content.tsx +++ b/components/Premium/Content.tsx @@ -1,14 +1,6 @@ // TODO remove the use client directive in favor of a server component 'use client' -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger -} from '@/components/ui/dialog' import { CloseIcon, StripeSquare, @@ -19,6 +11,14 @@ import { PayPal, Stripe } from '@/app/premium/_components/icons' +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger +} from '@/components/ui/dialog' import { Select, SelectContent, diff --git a/package.json b/package.json index 0e61768..515e3bf 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@hookform/resolvers": "^3.9.0", "@oslojs/jwt": "^0.2.0", "@oslojs/oauth2": "^0.5.0", - "@prisma/client": "6.1.0", + "@prisma/client": "6.2.1", "@radix-ui/react-alert-dialog": "^1.1.4", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.1.3", @@ -78,7 +78,7 @@ "prettier": "^3.2.5", "prettier-plugin-sort-imports": "^1.8.6", "prettier-plugin-tailwindcss": "^0.6.6", - "prisma": "^6.1.0", + "prisma": "^6.2.1", "tailwindcss": "^3.3.0", "typescript": "^5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 01d386a..5bf76e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,8 +22,8 @@ importers: specifier: ^0.5.0 version: 0.5.0 '@prisma/client': - specifier: 6.1.0 - version: 6.1.0(prisma@6.1.0) + specifier: 6.2.1 + version: 6.2.1(prisma@6.2.1) '@radix-ui/react-alert-dialog': specifier: ^1.1.4 version: 1.1.4(@types/react-dom@19.0.2(@types/react@19.0.2))(@types/react@19.0.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -203,8 +203,8 @@ importers: specifier: ^0.6.6 version: 0.6.9(prettier-plugin-sort-imports@1.8.6(typescript@5.7.2))(prettier@3.4.2) prisma: - specifier: ^6.1.0 - version: 6.1.0 + specifier: ^6.2.1 + version: 6.2.1 tailwindcss: specifier: ^3.3.0 version: 3.4.17 @@ -697,8 +697,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@prisma/client@6.1.0': - resolution: {integrity: sha512-AbQYc5+EJKm1Ydfq3KxwcGiy7wIbm4/QbjCKWWoNROtvy7d6a3gmAGkKjK0iUCzh+rHV8xDhD5Cge8ke/kiy5Q==} + '@prisma/client@6.2.1': + resolution: {integrity: sha512-msKY2iRLISN8t5X0Tj7hU0UWet1u0KuxSPHWuf3IRkB4J95mCvGpyQBfQ6ufcmvKNOMQSq90O2iUmJEN2e5fiA==} engines: {node: '>=18.18'} peerDependencies: prisma: '*' @@ -706,20 +706,20 @@ packages: prisma: optional: true - '@prisma/debug@6.1.0': - resolution: {integrity: sha512-0himsvcM4DGBTtvXkd2Tggv6sl2JyUYLzEGXXleFY+7Kp6rZeSS3hiTW9mwtUlXrwYbJP6pwlVNB7jYElrjWUg==} + '@prisma/debug@6.2.1': + resolution: {integrity: sha512-0KItvt39CmQxWkEw6oW+RQMD6RZ43SJWgEUnzxN8VC9ixMysa7MzZCZf22LCK5DSooiLNf8vM3LHZm/I/Ni7bQ==} - '@prisma/engines-version@6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959': - resolution: {integrity: sha512-PdJqmYM2Fd8K0weOOtQThWylwjsDlTig+8Pcg47/jszMuLL9iLIaygC3cjWJLda69siRW4STlCTMSgOjZzvKPQ==} + '@prisma/engines-version@6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69': + resolution: {integrity: sha512-7tw1qs/9GWSX6qbZs4He09TOTg1ff3gYsB3ubaVNN0Pp1zLm9NC5C5MZShtkz7TyQjx7blhpknB7HwEhlG+PrQ==} - '@prisma/engines@6.1.0': - resolution: {integrity: sha512-GnYJbCiep3Vyr1P/415ReYrgJUjP79fBNc1wCo7NP6Eia0CzL2Ot9vK7Infczv3oK7JLrCcawOSAxFxNFsAERQ==} + '@prisma/engines@6.2.1': + resolution: {integrity: sha512-lTBNLJBCxVT9iP5I7Mn6GlwqAxTpS5qMERrhebkUhtXpGVkBNd/jHnNJBZQW4kGDCKaQg/r2vlJYkzOHnAb7ZQ==} - '@prisma/fetch-engine@6.1.0': - resolution: {integrity: sha512-asdFi7TvPlEZ8CzSZ/+Du5wZ27q6OJbRSXh+S8ISZguu+S9KtS/gP7NeXceZyb1Jv1SM1S5YfiCv+STDsG6rrg==} + '@prisma/fetch-engine@6.2.1': + resolution: {integrity: sha512-OO7O9d6Mrx2F9i+Gu1LW+DGXXyUFkP7OE5aj9iBfA/2jjDXEJjqa9X0ZmM9NZNo8Uo7ql6zKm6yjDcbAcRrw1A==} - '@prisma/get-platform@6.1.0': - resolution: {integrity: sha512-ia8bNjboBoHkmKGGaWtqtlgQOhCi7+f85aOkPJKgNwWvYrT6l78KgojLekE8zMhVk0R9lWcifV0Pf8l3/15V0Q==} + '@prisma/get-platform@6.2.1': + resolution: {integrity: sha512-zp53yvroPl5m5/gXYLz7tGCNG33bhG+JYCm74ohxOq1pPnrL47VQYFfF3RbTZ7TzGWCrR3EtoiYMywUBw7UK6Q==} '@radix-ui/number@1.1.0': resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} @@ -3043,8 +3043,8 @@ packages: engines: {node: '>=14'} hasBin: true - prisma@6.1.0: - resolution: {integrity: sha512-aFI3Yi+ApUxkwCJJwyQSwpyzUX7YX3ihzuHNHOyv4GJg3X5tQsmRaJEnZ+ZyfHpMtnyahhmXVfbTZ+lS8ZtfKw==} + prisma@6.2.1: + resolution: {integrity: sha512-hhyM0H13pQleQ+br4CkzGizS5I0oInoeTw3JfLw1BRZduBSQxPILlJLwi+46wZzj9Je7ndyQEMGw/n5cN2fknA==} engines: {node: '>=18.18'} hasBin: true @@ -4039,30 +4039,30 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@prisma/client@6.1.0(prisma@6.1.0)': + '@prisma/client@6.2.1(prisma@6.2.1)': optionalDependencies: - prisma: 6.1.0 + prisma: 6.2.1 - '@prisma/debug@6.1.0': {} + '@prisma/debug@6.2.1': {} - '@prisma/engines-version@6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959': {} + '@prisma/engines-version@6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69': {} - '@prisma/engines@6.1.0': + '@prisma/engines@6.2.1': dependencies: - '@prisma/debug': 6.1.0 - '@prisma/engines-version': 6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959 - '@prisma/fetch-engine': 6.1.0 - '@prisma/get-platform': 6.1.0 + '@prisma/debug': 6.2.1 + '@prisma/engines-version': 6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69 + '@prisma/fetch-engine': 6.2.1 + '@prisma/get-platform': 6.2.1 - '@prisma/fetch-engine@6.1.0': + '@prisma/fetch-engine@6.2.1': dependencies: - '@prisma/debug': 6.1.0 - '@prisma/engines-version': 6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959 - '@prisma/get-platform': 6.1.0 + '@prisma/debug': 6.2.1 + '@prisma/engines-version': 6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69 + '@prisma/get-platform': 6.2.1 - '@prisma/get-platform@6.1.0': + '@prisma/get-platform@6.2.1': dependencies: - '@prisma/debug': 6.1.0 + '@prisma/debug': 6.2.1 '@radix-ui/number@1.1.0': {} @@ -5341,8 +5341,8 @@ snapshots: '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.7.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.3(eslint@8.57.1) eslint-plugin-react-hooks: 5.1.0(eslint@8.57.1) @@ -5361,7 +5361,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1): + eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 @@ -5373,22 +5373,22 @@ snapshots: is-glob: 4.0.3 stable-hash: 0.0.4 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.7.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -5399,7 +5399,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -6709,9 +6709,9 @@ snapshots: prettier@3.4.2: {} - prisma@6.1.0: + prisma@6.2.1: dependencies: - '@prisma/engines': 6.1.0 + '@prisma/engines': 6.2.1 optionalDependencies: fsevents: 2.3.3 diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 992fcd3..65e1922 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -86,3 +86,17 @@ model User { @@map("usermodels") } + +model Guild { + id String @id @default(auto()) @map("_id") @db.ObjectId + guildID String @db.String @unique + language String @db.String @default("en_US") + premium Int @db.Int @default(0) + pending Boolean? @default(true) + premiumExpiration DateTime? @db.Date + premiumUser String? @db.String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@map("guildProfile") +}