From b1c3d788cd145c673664be71ae03c4483aaf20de Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Sat, 18 Feb 2023 12:08:51 +0100 Subject: [PATCH 01/38] client: theme will now change on auto, if system theme changes --- client/src/util/store.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/src/util/store.ts b/client/src/util/store.ts index ca81eef..a03e9a6 100644 --- a/client/src/util/store.ts +++ b/client/src/util/store.ts @@ -63,6 +63,12 @@ export const store = reactive({ }, }) +window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + if (store.theme === 'auto') { + store.update_theme(get_theme()) + } +}) + function get_theme() { const theme = get_cookie("theme") if (theme) { From b2121bc86e3d13b89e74af7cd3a4eca146fca7cb Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Sat, 18 Feb 2023 14:42:56 +0100 Subject: [PATCH 02/38] db: update movie schema to support multilang --- package-lock.json | 64 +++++++++++++++++++++++-------------------- package.json | 4 +-- prisma/schema.prisma | 65 ++++++++++++++++++++++++++------------------ 3 files changed, 74 insertions(+), 59 deletions(-) diff --git a/package-lock.json b/package-lock.json index 363ada1..9c8e2d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@nestjs/schedule": "^2.2.0", "@nestjs/serve-static": "^3.0.0", "@nestjs/swagger": "^6.2.1", - "@prisma/client": "^4.9.0", + "@prisma/client": "^4.10.1", "bcrypt": "^5.1.0", "cron-parser": "^4.7.1", "crypto-js": "^4.1.1", @@ -32,7 +32,6 @@ "passport": "^0.6.0", "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", - "prisma": "^4.9.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.8.0" @@ -59,6 +58,7 @@ "eslint-plugin-prettier": "^4.2.1", "jest": "28.1.2", "prettier": "^2.8.3", + "prisma": "^4.10.1", "source-map-support": "^0.5.20", "supertest": "^6.3.3", "ts-jest": "28.0.5", @@ -3608,12 +3608,12 @@ } }, "node_modules/@prisma/client": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.9.0.tgz", - "integrity": "sha512-bz6QARw54sWcbyR1lLnF2QHvRW5R/Jxnbbmwh3u+969vUKXtBkXgSgjDA85nji31ZBlf7+FrHDy5x+5ydGyQDg==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.10.1.tgz", + "integrity": "sha512-VonXLJZybdt8e5XZH5vnIGCRNnIh6OMX1FS3H/yzMGLT3STj5TJ/OkMcednrvELgk8PK89Vo3aSh51MWNO0axA==", "hasInstallScript": true, "dependencies": { - "@prisma/engines-version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5" + "@prisma/engines-version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19" }, "engines": { "node": ">=14.17" @@ -3628,15 +3628,16 @@ } }, "node_modules/@prisma/engines": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.9.0.tgz", - "integrity": "sha512-t1pt0Gsp+HcgPJrHFc+d/ZSAaKKWar2G/iakrE07yeKPNavDP3iVKPpfXP22OTCHZUWf7OelwKJxQgKAm5hkgw==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.10.1.tgz", + "integrity": "sha512-B3tcTxjx196nuAu1GOTKO9cGPUgTFHYRdkPkTS4m5ptb2cejyBlH9X7GOfSt3xlI7p4zAJDshJP4JJivCg9ouA==", + "devOptional": true, "hasInstallScript": true }, "node_modules/@prisma/engines-version": { - "version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5.tgz", - "integrity": "sha512-M16aibbxi/FhW7z1sJCX8u+0DriyQYY5AyeTH7plQm9MLnURoiyn3CZBqAyIoQ+Z1pS77usCIibYJWSgleBMBA==" + "version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19.tgz", + "integrity": "sha512-tsjTho7laDhf9EJ9EnDxAPEf7yrigSMDhniXeU4YoWc7azHAs4GPxRi2P9LTFonmHkJLMOLjR77J1oIP8Ife1w==" }, "node_modules/@sapphire/async-queue": { "version": "1.5.0", @@ -10318,12 +10319,13 @@ } }, "node_modules/prisma": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.9.0.tgz", - "integrity": "sha512-bS96oZ5oDFXYgoF2l7PJ3Mp1wWWfLOo8B/jAfbA2Pn0Wm5Z/owBHzaMQKS3i1CzVBDWWPVnOohmbJmjvkcHS5w==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.10.1.tgz", + "integrity": "sha512-0jDxgg+DruB1kHVNlcspXQB9au62IFfVg9drkhzXudszHNUAQn0lVuu+T8np0uC2z1nKD5S3qPeCyR8u5YFLnA==", + "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/engines": "4.9.0" + "@prisma/engines": "4.10.1" }, "bin": { "prisma": "build/index.js", @@ -15385,22 +15387,23 @@ } }, "@prisma/client": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.9.0.tgz", - "integrity": "sha512-bz6QARw54sWcbyR1lLnF2QHvRW5R/Jxnbbmwh3u+969vUKXtBkXgSgjDA85nji31ZBlf7+FrHDy5x+5ydGyQDg==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.10.1.tgz", + "integrity": "sha512-VonXLJZybdt8e5XZH5vnIGCRNnIh6OMX1FS3H/yzMGLT3STj5TJ/OkMcednrvELgk8PK89Vo3aSh51MWNO0axA==", "requires": { - "@prisma/engines-version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5" + "@prisma/engines-version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19" } }, "@prisma/engines": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.9.0.tgz", - "integrity": "sha512-t1pt0Gsp+HcgPJrHFc+d/ZSAaKKWar2G/iakrE07yeKPNavDP3iVKPpfXP22OTCHZUWf7OelwKJxQgKAm5hkgw==" + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.10.1.tgz", + "integrity": "sha512-B3tcTxjx196nuAu1GOTKO9cGPUgTFHYRdkPkTS4m5ptb2cejyBlH9X7GOfSt3xlI7p4zAJDshJP4JJivCg9ouA==", + "devOptional": true }, "@prisma/engines-version": { - "version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5.tgz", - "integrity": "sha512-M16aibbxi/FhW7z1sJCX8u+0DriyQYY5AyeTH7plQm9MLnURoiyn3CZBqAyIoQ+Z1pS77usCIibYJWSgleBMBA==" + "version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19.tgz", + "integrity": "sha512-tsjTho7laDhf9EJ9EnDxAPEf7yrigSMDhniXeU4YoWc7azHAs4GPxRi2P9LTFonmHkJLMOLjR77J1oIP8Ife1w==" }, "@sapphire/async-queue": { "version": "1.5.0", @@ -20520,11 +20523,12 @@ } }, "prisma": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.9.0.tgz", - "integrity": "sha512-bS96oZ5oDFXYgoF2l7PJ3Mp1wWWfLOo8B/jAfbA2Pn0Wm5Z/owBHzaMQKS3i1CzVBDWWPVnOohmbJmjvkcHS5w==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.10.1.tgz", + "integrity": "sha512-0jDxgg+DruB1kHVNlcspXQB9au62IFfVg9drkhzXudszHNUAQn0lVuu+T8np0uC2z1nKD5S3qPeCyR8u5YFLnA==", + "devOptional": true, "requires": { - "@prisma/engines": "4.9.0" + "@prisma/engines": "4.10.1" } }, "process-nextick-args": { diff --git a/package.json b/package.json index 0d03fed..455e13a 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@nestjs/schedule": "^2.2.0", "@nestjs/serve-static": "^3.0.0", "@nestjs/swagger": "^6.2.1", - "@prisma/client": "^4.9.0", + "@prisma/client": "^4.10.1", "bcrypt": "^5.1.0", "cron-parser": "^4.7.1", "crypto-js": "^4.1.1", @@ -49,7 +49,6 @@ "passport": "^0.6.0", "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", - "prisma": "^4.9.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.8.0" @@ -76,6 +75,7 @@ "eslint-plugin-prettier": "^4.2.1", "jest": "28.1.2", "prettier": "^2.8.3", + "prisma": "^4.10.1", "source-map-support": "^0.5.20", "supertest": "^6.3.3", "ts-jest": "28.0.5", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b50cd1e..b3c9462 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -12,7 +12,7 @@ datasource db { model User { id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) + created_at DateTime @default(now()) username String @unique password String name String @@ -26,34 +26,52 @@ model User { Vote Vote[] } +model MovieInfo { + imdb_id String @id + language String + title String + year Int + genre String + director String + actors String + imdb_rate String + meta_score String + rotten_score String + languages String + plot String + runtime Int + link String + poster String + + @@unique([imdb_id, language]) +} + model Movie { imdb_id String @id - createdAt DateTime @default(now()) - title String - year Int - genre String - director String - actors String - imdb_rate Float - metascore String? - language String - plot String - runtime Int - link String - poster String? + created_at DateTime @default(now()) proposer_id Int proposer User @relation(fields: [proposer_id], references: [id]) Vote Vote[] WatchList WatchList? } +model History { + imdb_id String @id + language String + watched_at DateTime @default(now()) + title String + link String + + @@unique([imdb_id, language]) +} + model Vote { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - imdb_id String - movie Movie @relation(fields: [imdb_id], references: [imdb_id]) - user_id Int - user User @relation(fields: [user_id], references: [id]) + id Int @id @default(autoincrement()) + created_at DateTime @default(now()) + imdb_id String + movie Movie @relation(fields: [imdb_id], references: [imdb_id]) + user_id Int + user User @relation(fields: [user_id], references: [id]) @@unique([imdb_id, user_id]) } @@ -63,10 +81,3 @@ model WatchList { start_time DateTime movie Movie @relation(fields: [imdb_id], references: [imdb_id]) } - -model History { - imdb_id String @id - watched_at DateTime @default(now()) - title String - link String -} From f100d95cddfad9d03aacae0e0506e5d55a98207e Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Sat, 18 Feb 2023 14:43:27 +0100 Subject: [PATCH 03/38] backend: create util for imdb_api --- .env.tmp | 2 +- src/common/util_services/imdb_api.service.ts | 64 ++++++++++++++++++++ src/types/movie.types/movie_search.type.ts | 3 +- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/common/util_services/imdb_api.service.ts diff --git a/.env.tmp b/.env.tmp index 4efb5b3..ff89743 100644 --- a/.env.tmp +++ b/.env.tmp @@ -5,7 +5,7 @@ PORT="3000" DATABASE_URL="file:./dev.db" JWT_SECRET="secret" JWT_EXPIRATION="2h" -OMDB_API_KEY="XXXXXXXX" +IMDB_API_KEY="k_XXXXXXXX" MAX_VOTES="20" MAX_PROPOSEABLE_MOVIES="5" diff --git a/src/common/util_services/imdb_api.service.ts b/src/common/util_services/imdb_api.service.ts new file mode 100644 index 0000000..64ec722 --- /dev/null +++ b/src/common/util_services/imdb_api.service.ts @@ -0,0 +1,64 @@ +import { Injectable } from "@nestjs/common"; +import * as process from "process"; +import { Prisma } from "@prisma/client"; +import { MovieSearchType } from "../../types/movie.types/movie_search.type"; + +@Injectable() +export class ImdbApiService { + constructor() { + } + + api_key = process.env.IMDB_API_KEY; + + async get_movie_info(imdb_id: string, lang: string = "en"): Promise { + const response = await fetch(`https://imdb-api.com/${lang}/API/Title/${this.api_key}/${imdb_id}`); + const movie = await response.json() as any; + + if (movie.type !== "movie") return {} as Prisma.MovieInfoCreateInput; + + return { + imdb_id: movie.id, + language: lang, + title: movie.title, + year: Number(movie.type), + genre: movie.genres, + director: movie.directors, + actors: movie.stars, + imdb_rate: movie.ratings.imDb, + meta_score: movie.ratings.metacritic, + rotten_score: movie.ratings.rottenTomatoes, + languages: movie.languages, + plot: (movie.plotLocal !== "") ? movie.plotLocal : movie.plot, + runtime: Number(movie.runtimeMins), + link: `https://www.imdb.com/title/${movie.id}/`, + poster: movie.image + } as Prisma.MovieInfoCreateInput; + } + + async get_movie_info_all_langs(imdb_id: string): Promise { + const langs = ["en", "de"]; + const movie_infos: Prisma.MovieInfoCreateInput[] = []; + + for (const lang of langs) { + const movie_info = await this.get_movie_info(imdb_id, lang); + if (movie_info.imdb_id !== undefined) movie_infos.push(movie_info); + } + + return movie_infos; + } + + async search_movie(search_input: string, lang: string = "en"): Promise { + const response = await fetch(`https://imdb-api.com/${lang}/API/SearchMovie/${this.api_key}/${search_input}`); + const data = await response.json() as any; + const movies = data.results as any[]; + + return movies.map((movie) => { + return { + imdb_id: movie.id, + title: movie.title, + description: movie.description, + poster: movie.image + } + }) as MovieSearchType[]; + } +} diff --git a/src/types/movie.types/movie_search.type.ts b/src/types/movie.types/movie_search.type.ts index 8e7e7cb..5262ffd 100644 --- a/src/types/movie.types/movie_search.type.ts +++ b/src/types/movie.types/movie_search.type.ts @@ -1,6 +1,7 @@ export class MovieSearchType { title!: string - year!: string + description!: string imdb_id!: string + poster!: string } From 60791e50b9e18b101d988cba22dec2ad2a2fd101 Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Sat, 18 Feb 2023 15:21:12 +0100 Subject: [PATCH 04/38] backend: create movieInfo service --- .../db_services/histroy/historyDB.service.ts | 4 +- .../movie_infos/movieInfoDB.module.ts | 9 ++++ .../movie_infos/movieInfoDB.service.ts | 54 +++++++++++++++++++ .../db_services/movies/movieDB.module.ts | 2 + .../db_services/movies/movieDB.service.ts | 17 +++--- .../db_services/votes/voteDB.service.ts | 22 ++++---- .../watchlist/watchListDB.service.ts | 6 +-- src/types/movie.types/movie_ext.type.ts | 7 +-- 8 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 src/common/db_services/movie_infos/movieInfoDB.module.ts create mode 100644 src/common/db_services/movie_infos/movieInfoDB.service.ts diff --git a/src/common/db_services/histroy/historyDB.service.ts b/src/common/db_services/histroy/historyDB.service.ts index 443e5f0..b543ce8 100644 --- a/src/common/db_services/histroy/historyDB.service.ts +++ b/src/common/db_services/histroy/historyDB.service.ts @@ -8,11 +8,11 @@ export class HistoryDBService { constructor(private readonly prisma: PrismaService) {} async get_all() { - return await this.prisma.history.findMany(); + return this.prisma.history.findMany(); } async add(data: Prisma.HistoryCreateInput) { - return await this.prisma.history.create({ data }); + return this.prisma.history.create({ data }); } async has(imdb_id: string) { diff --git a/src/common/db_services/movie_infos/movieInfoDB.module.ts b/src/common/db_services/movie_infos/movieInfoDB.module.ts new file mode 100644 index 0000000..fc7f4cb --- /dev/null +++ b/src/common/db_services/movie_infos/movieInfoDB.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { MovieInfoDBService } from './movieInfoDB.service'; +import { PrismaService } from "../prisma.service"; + +@Module({ + providers: [MovieInfoDBService, PrismaService], + exports: [MovieInfoDBService] +}) +export class MovieInfoDBModule {} diff --git a/src/common/db_services/movie_infos/movieInfoDB.service.ts b/src/common/db_services/movie_infos/movieInfoDB.service.ts new file mode 100644 index 0000000..7f067a1 --- /dev/null +++ b/src/common/db_services/movie_infos/movieInfoDB.service.ts @@ -0,0 +1,54 @@ +import { Injectable, InternalServerErrorException } from "@nestjs/common"; +import { PrismaService } from "../prisma.service"; +import { Prisma } from "@prisma/client"; + +@Injectable() +export class MovieInfoDBService { + + constructor(private readonly prisma: PrismaService) { + } + + async get(imdb_id: string, language: string) { + return this.prisma.movieInfo.findUnique({ + where: { imdb_id_language: { imdb_id, language } } + }).catch((e: Prisma.PrismaClientKnownRequestError) => { + throw new InternalServerErrorException(`DB Error: ${e.code}`); + }); + } + + async get_all(language: string) { + return this.prisma.movieInfo.findMany({ + where: { language: language } + }).catch((e: Prisma.PrismaClientKnownRequestError) => { + throw new InternalServerErrorException(`DB Error: ${e.code}`); + }); + } + + async has(imdb_id: string) { + const count = await this.prisma.movieInfo.count({ + where: { imdb_id } + }).catch((e: Prisma.PrismaClientKnownRequestError) => { + throw new InternalServerErrorException(`DB Error: ${e.code}`); + }); + + return count > 0; + } + + async add(data: Prisma.MovieInfoCreateInput[]) { + for (const datum of data) { + await this.prisma.movieInfo.create({ + data: datum + }).catch((e: Prisma.PrismaClientKnownRequestError) => { + throw new InternalServerErrorException(`DB Error: ${e.code}`); + }); + } + } + + async delete(imdb_id: string) { + return this.prisma.movieInfo.deleteMany({ + where: { imdb_id } + }).catch((e: Prisma.PrismaClientKnownRequestError) => { + throw new InternalServerErrorException(`DB Error: ${e.code}`); + }); + } +} diff --git a/src/common/db_services/movies/movieDB.module.ts b/src/common/db_services/movies/movieDB.module.ts index 87d05a4..0a6f578 100644 --- a/src/common/db_services/movies/movieDB.module.ts +++ b/src/common/db_services/movies/movieDB.module.ts @@ -1,8 +1,10 @@ import { Module } from '@nestjs/common'; import { MovieDBService } from './movieDB.service'; import { PrismaService } from "../prisma.service"; +import { MovieInfoDBModule } from "../movie_infos/movieInfoDB.module"; @Module({ + imports: [MovieInfoDBModule], providers: [MovieDBService, PrismaService], exports: [MovieDBService] }) diff --git a/src/common/db_services/movies/movieDB.service.ts b/src/common/db_services/movies/movieDB.service.ts index 2a44c50..bfb2f35 100644 --- a/src/common/db_services/movies/movieDB.service.ts +++ b/src/common/db_services/movies/movieDB.service.ts @@ -1,11 +1,13 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from "../prisma.service"; import { Prisma } from "@prisma/client"; +import { MovieInfoDBService } from "../movie_infos/movieInfoDB.service"; @Injectable() export class MovieDBService { - constructor(private readonly prisma: PrismaService) {} + constructor(private readonly prisma: PrismaService, + private readonly movieInfo: MovieInfoDBService) {} async get(imdb_id : string) { return this.prisma.movie.findUnique({ @@ -28,16 +30,19 @@ export class MovieDBService { } async add(data: Prisma.MovieCreateInput) { - return await this.prisma.movie.create({ data }); + return this.prisma.movie.create({ data }); } async delete(imdb_id: string) { - return await this.prisma.movie.delete({ where: { imdb_id } }); + await this.movieInfo.delete(imdb_id); + return this.prisma.movie.delete({ where: { imdb_id } }); } async delete_all_proposed(user_id : number) { - return await this.prisma.movie.deleteMany({ - where: { proposer_id: user_id } as Prisma.MovieWhereUniqueInput - }); + const movies = await this.get_all_proposed(user_id); + for (const movie of movies) { + await this.movieInfo.delete(movie.imdb_id); + await this.delete(movie.imdb_id) + } } } diff --git a/src/common/db_services/votes/voteDB.service.ts b/src/common/db_services/votes/voteDB.service.ts index ba58b0b..abd9399 100644 --- a/src/common/db_services/votes/voteDB.service.ts +++ b/src/common/db_services/votes/voteDB.service.ts @@ -8,13 +8,13 @@ export class VoteDBService { constructor(private readonly prisma: PrismaService) {} async get(data : Prisma.VoteWhereUniqueInput) { - return await this.prisma.vote.findUnique({ + return this.prisma.vote.findUnique({ where: data, }); } async has(user_id: Prisma.UserWhereUniqueInput, imdb_id: Prisma.MovieWhereUniqueInput) { - return await this.prisma.vote.findFirst({ + return this.prisma.vote.findFirst({ where: { user: user_id, movie: imdb_id @@ -23,7 +23,7 @@ export class VoteDBService { } async num_of(user_id: number) { - return await this.prisma.vote.count({ + return this.prisma.vote.count({ where: { user: { id: user_id } } @@ -31,27 +31,27 @@ export class VoteDBService { } async get_num_of_votes(imdb_id: string) { - return await this.prisma.vote.count({ + return this.prisma.vote.count({ where: { movie: { imdb_id } } }); } async get_votes_user(user_id: number) { - return await this.prisma.vote.findMany({ + return this.prisma.vote.findMany({ where: { user: { id: user_id } }, select: { imdb_id: true } }); } async get_votes_movie(imdb_id: string) { - return await this.prisma.vote.findMany({ + return this.prisma.vote.findMany({ where: { movie: { imdb_id } }, select: { user: true } }) } async get_most_voted(count: number) { - return await this.prisma.vote.groupBy({ + return this.prisma.vote.groupBy({ by: ['imdb_id'], _count: { user_id: true, @@ -66,18 +66,18 @@ export class VoteDBService { } async add(data: Prisma.VoteCreateInput) { - return await this.prisma.vote.create({ data }); + return this.prisma.vote.create({ data }); } async delete(data : Prisma.VoteWhereUniqueInput) { - return await this.prisma.vote.delete({ where: data }); + return this.prisma.vote.delete({ where: data }); } async delete_all(imdb_id: string) { - return await this.prisma.vote.deleteMany({ where: { imdb_id } }); + return this.prisma.vote.deleteMany({ where: { imdb_id } }); } async delete_all_user(user_id: number) { - return await this.prisma.vote.deleteMany({ where: { user_id } }); + return this.prisma.vote.deleteMany({ where: { user_id } }); } } diff --git a/src/common/db_services/watchlist/watchListDB.service.ts b/src/common/db_services/watchlist/watchListDB.service.ts index 432d498..fdbd6f2 100644 --- a/src/common/db_services/watchlist/watchListDB.service.ts +++ b/src/common/db_services/watchlist/watchListDB.service.ts @@ -8,15 +8,15 @@ export class WatchListDBService { constructor(private readonly prisma: PrismaService) {} async get_all() { - return await this.prisma.watchList.findMany() + return this.prisma.watchList.findMany() } async add(data: Prisma.WatchListCreateInput) { - return await this.prisma.watchList.create({ data }) + return this.prisma.watchList.create({ data }) } async delete(imdb_id: string) { - return await this.prisma.watchList.delete({ + return this.prisma.watchList.delete({ where: { imdb_id } diff --git a/src/types/movie.types/movie_ext.type.ts b/src/types/movie.types/movie_ext.type.ts index a489dc8..b4cb70b 100644 --- a/src/types/movie.types/movie_ext.type.ts +++ b/src/types/movie.types/movie_ext.type.ts @@ -9,9 +9,10 @@ export class MovieExtType { proposer_id!: number director!: string actors!: string - imdb_rate!: number language!: string - metascore!: string - createdAt!: Date + imdb_rate!: number + rotten_score!: string + meta_score!: string + created_at!: Date votes!: number } From a4b65dd71e214ed5484e49d3238a304e1955d811 Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Sat, 18 Feb 2023 22:55:45 +0100 Subject: [PATCH 05/38] backend: update movie routes and jobs to new api and db model --- package-lock.json | 704 +++++++++--------- package.json | 30 +- prisma/schema.prisma | 4 +- .../movie_infos/movieInfoDB.service.ts | 4 +- .../db_services/movies/movieDB.service.ts | 19 +- src/common/event_service/event.module.ts | 3 +- src/common/event_service/jobs/announce.job.ts | 11 +- src/common/event_service/jobs/history.job.ts | 12 +- .../event_service/jobs/watchlist.job.ts | 10 +- src/common/util_services/imdb_api.service.ts | 8 +- src/routes/auth/auth.service.ts | 2 +- src/routes/movie/movie.controller.ts | 16 +- src/routes/movie/movie.module.ts | 6 +- src/routes/movie/movie.service.ts | 218 +++--- src/types/movie.dto/omdb_search.dto.ts | 8 - src/types/movie.types/movie_ext.type.ts | 4 +- 16 files changed, 521 insertions(+), 538 deletions(-) delete mode 100644 src/types/movie.dto/omdb_search.dto.ts diff --git a/package-lock.json b/package-lock.json index 9c8e2d1..64ad4b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,14 @@ "version": "1.0.0-alpha.8", "license": "MIT", "dependencies": { - "@nestjs/common": "^9.3.2", - "@nestjs/config": "^2.3.0", - "@nestjs/core": "^9.3.2", - "@nestjs/jwt": "^10.0.1", - "@nestjs/passport": "^9.0.1", - "@nestjs/platform-express": "^9.3.2", + "@nestjs/common": "^9.3.9", + "@nestjs/config": "^2.3.1", + "@nestjs/core": "^9.3.9", + "@nestjs/jwt": "^10.0.2", + "@nestjs/passport": "^9.0.3", + "@nestjs/platform-express": "^9.3.9", "@nestjs/schedule": "^2.2.0", - "@nestjs/serve-static": "^3.0.0", + "@nestjs/serve-static": "^3.0.1", "@nestjs/swagger": "^6.2.1", "@prisma/client": "^4.10.1", "bcrypt": "^5.1.0", @@ -26,7 +26,7 @@ "discord.js": "^14.7.1", "helmet": "^5.1.1", "imdb-api": "^4.4.1", - "joi": "^17.7.0", + "joi": "^17.7.1", "nestjs-i18n": "^10.2.6", "nodemailer": "^6.9.1", "passport": "^0.6.0", @@ -40,24 +40,24 @@ "@compodoc/compodoc": "^1.1.19", "@nestjs/cli": "^9.2.0", "@nestjs/schematics": "^9.0.4", - "@nestjs/testing": "^9.3.2", + "@nestjs/testing": "^9.3.9", "@types/bcrypt": "^5.0.0", "@types/cron": "^2.0.0", "@types/crypto-js": "^4.1.1", - "@types/express": "^4.17.16", + "@types/express": "^4.17.17", "@types/jest": "28.1.4", - "@types/node": "^16.18.11", + "@types/node": "^16.18.12", "@types/nodemailer": "^6.4.7", "@types/passport-jwt": "^3.0.8", "@types/passport-local": "^1.0.35", "@types/supertest": "^2.0.12", - "@typescript-eslint/eslint-plugin": "^5.50.0", - "@typescript-eslint/parser": "^5.50.0", - "eslint": "^8.33.0", + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", + "eslint": "^8.34.0", "eslint-config-prettier": "^8.6.0", "eslint-plugin-prettier": "^4.2.1", "jest": "28.1.2", - "prettier": "^2.8.3", + "prettier": "^2.8.4", "prisma": "^4.10.1", "source-map-support": "^0.5.20", "supertest": "^6.3.3", @@ -2005,6 +2005,12 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "node_modules/@babel/runtime": { "version": "7.20.13", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", @@ -3162,9 +3168,9 @@ "dev": true }, "node_modules/@nestjs/common": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.2.tgz", - "integrity": "sha512-YUqY9qPMxiMqO/pRNXJehR18LFL6Y9BN5Qn0FylVbdpKd7/QKZHVWRKNaAYNu0mGfyJhRJI6oEr/1Tn5GEo6GQ==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.9.tgz", + "integrity": "sha512-GshTD9Xz+wD2em6NyzU4NXw5IXMUmapgDgD+iuj6XL0258hvDwODmNk37mBBnZvTZlqER+krvIUKnS34etqF/A==", "dependencies": { "iterare": "1.2.1", "tslib": "2.5.0", @@ -3194,9 +3200,9 @@ } }, "node_modules/@nestjs/config": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.3.0.tgz", - "integrity": "sha512-VSAqoIagIrc0A3apaqC2O3a8VtQ+asw8xILmxvjK/eHW9m1rmhJ5NqkGf7m+uSv3Yxini4bzyb74Mk62+tB/cA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.3.1.tgz", + "integrity": "sha512-Ckzel0NZ9CWhNsLfE1hxfDuxJuEbhQvGxSlmZ1/X8awjRmAA/g3kT6M1+MO1SHj1wMtPyUfd9WpwkiqFbiwQgA==", "dependencies": { "dotenv": "16.0.3", "dotenv-expand": "10.0.0", @@ -3218,18 +3224,17 @@ } }, "node_modules/@nestjs/core": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.2.tgz", - "integrity": "sha512-79h4RvGAGFIIZJWIXqZ8xvhK/kIY6Fay7a1P0W4v7AUZsMIuNksct0uMzHaBqMT0lo+Ei+gU8PaWvzZt5lZvJw==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.9.tgz", + "integrity": "sha512-9g1A1G9eirLXEpH21rc6dKb08zHc2+adhCRz8NW39hbejcsxxD72FApJzt4QBQAKvu862ixt/tdpStnFT7lOSw==", "hasInstallScript": true, "dependencies": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", - "object-hash": "3.0.0", "path-to-regexp": "3.2.0", "tslib": "2.5.0", - "uuid": "9.0.0" + "uid": "2.0.1" }, "funding": { "type": "opencollective", @@ -3255,20 +3260,12 @@ } } }, - "node_modules/@nestjs/core/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@nestjs/jwt": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.0.1.tgz", - "integrity": "sha512-LwXBKVYHnFeX6GH/Wt0WDjsWCmNDC6tEdLlwNMAvJgYp+TkiCpEmQLkgRpifdUE29mvYSbjSnVs2kW2ob935NA==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.0.2.tgz", + "integrity": "sha512-MLxjCSbO7C9fN2hst5kpIhnJAgglJmrKppXAXqElB8A9ip3ZuCowMDjjmNWWJyfOzE98NV0E0iEQGE2StMUC+Q==", "dependencies": { - "@types/jsonwebtoken": "8.5.9", + "@types/jsonwebtoken": "9.0.1", "jsonwebtoken": "9.0.0" }, "peerDependencies": { @@ -3295,18 +3292,18 @@ } }, "node_modules/@nestjs/passport": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.1.tgz", - "integrity": "sha512-WhT0yhpMp1B8b1OdQdPv/rd2O8V0HUmoGsWFzJKPsALuaxozjem2WotUEy1GV/TT8kvfC4ok7tECjRAArO+I8Q==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.3.tgz", + "integrity": "sha512-HplSJaimEAz1IOZEu+pdJHHJhQyBOPAYWXYHfAPQvRqWtw4FJF1VXl1Qtk9dcXQX1eKytDtH+qBzNQc19GWNEg==", "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0", "passport": "^0.4.0 || ^0.5.0 || ^0.6.0" } }, "node_modules/@nestjs/platform-express": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.3.2.tgz", - "integrity": "sha512-hzLfUcJIFw8NIPlG88QJr+uSgJzkBkhxVsHGtRs+rNShzlMNfX63CPbkI4yfG4Eq0s8oYe598p6OE5O1z924Dg==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.3.9.tgz", + "integrity": "sha512-f8ja2sYuDGj2QSMmjg05n3WF19wJG5yTiYxRi64nsu5GKL0qLM1LzxNemehkni/knExlvF2bDpbKKpna9nC1JA==", "dependencies": { "body-parser": "1.20.1", "cors": "2.8.5", @@ -3481,15 +3478,29 @@ "dev": true }, "node_modules/@nestjs/serve-static": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/serve-static/-/serve-static-3.0.0.tgz", - "integrity": "sha512-TpXjgs4136dQqWUjEcONqppqXDsrJhRkmKWzuBMOUAnP4HjHpNmlycvkHnDnWSoG2YD4a7Enh4ViYGWqCfHStA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/serve-static/-/serve-static-3.0.1.tgz", + "integrity": "sha512-i766UJPYOqvQ2BbRKh0/+Mmq5NkJnmKcShjWV1i5qpXyeM0KDZTn0n7g7ykWq/3LbQgjpMzrhYtGv35GX7GVQw==", "dependencies": { "path-to-regexp": "0.2.5" }, "peerDependencies": { + "@fastify/static": "^6.5.0", "@nestjs/common": "^9.0.0", - "@nestjs/core": "^9.0.0" + "@nestjs/core": "^9.0.0", + "express": "^4.18.1", + "fastify": "^4.7.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "express": { + "optional": true + }, + "fastify": { + "optional": true + } } }, "node_modules/@nestjs/serve-static/node_modules/path-to-regexp": { @@ -3529,9 +3540,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.3.2.tgz", - "integrity": "sha512-A1DleYwUpA/MX4XLTOJYEkhEjdI0HyujTmOUoPzSplAPWXbR48DTtY3Pu3A/qM7A8JwPzfB37glFUAJvFFOYpg==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.3.9.tgz", + "integrity": "sha512-+mPvSVvSC2SAkYgZZv1mOI2xsdGc1pmq7/sem7iin/JDoFtlvoGSK+pfZHD3IV3EpYtq1v/8/5gi+UFH9yZnDg==", "dev": true, "dependencies": { "tslib": "2.5.0" @@ -3857,9 +3868,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz", - "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==", + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.1.tgz", + "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -3883,13 +3894,13 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.16", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.16.tgz", - "integrity": "sha512-LkKpqRZ7zqXJuvoELakaFYuETHjZkSol8EV6cNnyishutDBCCdv6+dsKPbKkCcIk57qRphOLY5sEgClw1bO3gA==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", "dev": true, "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.31", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } @@ -3955,9 +3966,9 @@ "dev": true }, "node_modules/@types/jsonwebtoken": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", - "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==", "dependencies": { "@types/node": "*" } @@ -3975,9 +3986,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==" }, "node_modules/@types/nodemailer": { "version": "6.4.7", @@ -3995,9 +4006,9 @@ "dev": true }, "node_modules/@types/passport": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.11.tgz", - "integrity": "sha512-pz1cx9ptZvozyGKKKIPLcVDVHwae4hrH5d6g5J+DkMRRjR3cVETb4jMabhXAUbg3Ov7T22nFHEgaK2jj+5CBpw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", + "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", "dev": true, "dependencies": { "@types/express": "*" @@ -4124,14 +4135,14 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.50.0.tgz", - "integrity": "sha512-vwksQWSFZiUhgq3Kv7o1Jcj0DUNylwnIlGvKvLLYsq8pAWha6/WCnXUeaSoNNha/K7QSf2+jvmkxggC1u3pIwQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", + "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/type-utils": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/type-utils": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -4158,14 +4169,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.50.0.tgz", - "integrity": "sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", + "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "debug": "^4.3.4" }, "engines": { @@ -4185,13 +4196,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.50.0.tgz", - "integrity": "sha512-rt03kaX+iZrhssaT974BCmoUikYtZI24Vp/kwTSy841XhiYShlqoshRFDvN1FKKvU2S3gK+kcBW1EA7kNUrogg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", + "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0" + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4202,13 +4213,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.50.0.tgz", - "integrity": "sha512-dcnXfZ6OGrNCO7E5UY/i0ktHb7Yx1fV6fnQGGrlnfDhilcs6n19eIRcvLBqx6OQkrPaFlDPk3OJ0WlzQfrV0bQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", + "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -4229,9 +4240,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.50.0.tgz", - "integrity": "sha512-atruOuJpir4OtyNdKahiHZobPKFvZnBnfDiyEaBf6d9vy9visE7gDjlmhl+y29uxZ2ZDgvXijcungGFjGGex7w==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", + "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4242,13 +4253,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.50.0.tgz", - "integrity": "sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", + "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4269,16 +4280,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.50.0.tgz", - "integrity": "sha512-v/AnUFImmh8G4PH0NDkf6wA8hujNNcrwtecqW4vtQ1UOSNBaZl49zP1SHoZ/06e+UiwzHpgb5zP5+hwlYYWYAw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", + "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -4295,12 +4306,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.50.0.tgz", - "integrity": "sha512-cdMeD9HGu6EXIeGOh2yVW6oGf9wq8asBgZx7nsR/D36gTfQ0odE5kcRYe5M81vjEFAcPeugXrHg78Imu55F6gg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", + "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/types": "5.52.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -5333,9 +5344,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", + "version": "1.0.30001456", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001456.tgz", + "integrity": "sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA==", "dev": true, "funding": [ { @@ -5460,9 +5471,9 @@ } }, "node_modules/ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, "funding": [ { @@ -5748,12 +5759,12 @@ "dev": true }, "node_modules/core-js-compat": { - "version": "3.27.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.2.tgz", - "integrity": "sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.28.0.tgz", + "integrity": "sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg==", "dev": true, "dependencies": { - "browserslist": "^4.21.4" + "browserslist": "^4.21.5" }, "funding": { "type": "opencollective", @@ -5980,9 +5991,9 @@ } }, "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "dependencies": { "has-property-descriptors": "^1.0.0", @@ -6090,9 +6101,9 @@ } }, "node_modules/discord-api-types": { - "version": "0.37.31", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.31.tgz", - "integrity": "sha512-k9DQQ7Wv+ehiF7901qk/FnP47k6O2MHm3meQFee4gUzi5dfGAVLf7SfLNtb4w7G2dmukJyWQtVJEDF9oMb9yuQ==" + "version": "0.37.35", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.35.tgz", + "integrity": "sha512-iyKZ/82k7FX3lcmHiAvvWu5TmyfVo78RtghBV/YsehK6CID83k5SI03DKKopBcln+TiEIYw5MGgq7SJXSpNzMg==" }, "node_modules/discord.js": { "version": "14.7.1", @@ -6246,9 +6257,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.285", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.285.tgz", - "integrity": "sha512-47o4PPgxfU1KMNejz+Dgaodf7YTcg48uOfV1oM6cs3adrl2+7R+dHkt3Jpxqo0LRCbGJEzTKMUt0RdvByb/leg==", + "version": "1.4.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.302.tgz", + "integrity": "sha512-Uk7C+7aPBryUR1Fwvk9VmipBcN9fVsqBO57jV2ZjTm+IZ6BMNqu7EDVEg2HxCNufk6QcWlFsBkhQyQroB2VWKw==", "dev": true }, "node_modules/emittery": { @@ -6477,9 +6488,9 @@ } }, "node_modules/eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", - "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.4.1", @@ -6728,9 +6739,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -7132,9 +7143,9 @@ } }, "node_modules/file-type": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.0.tgz", - "integrity": "sha512-M3RQMWY3F2ykyWZ+IHwNCjpnUmukYhtdkGGC1ZVEUb0ve5REGF7NNJ4Q9ehCUabtQKtSVFOMbFTXgJlFb0DQIg==", + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", "dependencies": { "readable-web-to-node-stream": "^3.0.2", "strtok3": "^7.0.0", @@ -8845,14 +8856,14 @@ } }, "node_modules/joi": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.0.tgz", - "integrity": "sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.1.tgz", + "integrity": "sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==", "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", + "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, @@ -9060,9 +9071,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.10.19", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.19.tgz", - "integrity": "sha512-MDZ1zLIkfSDZV5xBta3nuvbEOlsnKCPe4z5r3hyup/AXveevkl9A1eSWmLhd2FX4k7pJDe4MrLeQsux0HI/VWg==", + "version": "1.10.20", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.20.tgz", + "integrity": "sha512-kQovlKNdLcVzerbTPmJ+Fx4R+7/pYXmPDIllHjg7IxL4X6MsMG7jaT5opfYrBok0uqkByVif//JUR8e11l/V7w==", "peer": true }, "node_modules/lines-and-columns": { @@ -9387,17 +9398,17 @@ } }, "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.1.tgz", - "integrity": "sha512-V9esFpNbK0arbN3fm2sxDKqMYgIp7XtVdE4Esj+PE4Qaaxdg1wIw48ITQIOn1sc8xXSmUviVL3cyjMqPlrVkiA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", + "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==", "engines": { "node": ">=8" } @@ -9612,9 +9623,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", - "integrity": "sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "node_modules/nodemailer": { @@ -9690,14 +9701,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -10265,9 +10268,9 @@ } }, "node_modules/prettier": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", - "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -10616,14 +10619,14 @@ } }, "node_modules/regexpu-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", - "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.1.tgz", + "integrity": "sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ==", "dev": true, "dependencies": { + "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", "regjsparser": "^0.9.1", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" @@ -10632,12 +10635,6 @@ "node": ">=4" } }, - "node_modules/regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, "node_modules/regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", @@ -11750,9 +11747,9 @@ } }, "node_modules/terser": { - "version": "5.16.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", - "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.4.tgz", + "integrity": "sha512-5yEGuZ3DZradbogeYQ1NaGz7rXVBDWujWlx1PT8efXO6Txn+eWbfKqB2bTDVmFXmePFkoLU6XI8UektMIEA0ug==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", @@ -12031,9 +12028,9 @@ } }, "node_modules/ts-mixer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", - "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", + "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" }, "node_modules/ts-morph": { "version": "13.0.3", @@ -12251,9 +12248,9 @@ } }, "node_modules/undici": { - "version": "5.19.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.19.1.tgz", - "integrity": "sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", "dependencies": { "busboy": "^1.6.0" }, @@ -12408,9 +12405,9 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", @@ -12716,9 +12713,9 @@ } }, "node_modules/ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", + "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", "engines": { "node": ">=10.0.0" }, @@ -12777,9 +12774,9 @@ } }, "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.0.tgz", + "integrity": "sha512-dwqOPg5trmrre9+v8SUo2q/hAwyKoVfu8OC1xPHKJGNdxAvPl4sKxL4vBnh3bQz/ZvvGAFeA5H3ou2kcOY8sQQ==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -14199,6 +14196,12 @@ "esutils": "^2.0.2" } }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "@babel/runtime": { "version": "7.20.13", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", @@ -15117,9 +15120,9 @@ } }, "@nestjs/common": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.2.tgz", - "integrity": "sha512-YUqY9qPMxiMqO/pRNXJehR18LFL6Y9BN5Qn0FylVbdpKd7/QKZHVWRKNaAYNu0mGfyJhRJI6oEr/1Tn5GEo6GQ==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.9.tgz", + "integrity": "sha512-GshTD9Xz+wD2em6NyzU4NXw5IXMUmapgDgD+iuj6XL0258hvDwODmNk37mBBnZvTZlqER+krvIUKnS34etqF/A==", "requires": { "iterare": "1.2.1", "tslib": "2.5.0", @@ -15127,9 +15130,9 @@ } }, "@nestjs/config": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.3.0.tgz", - "integrity": "sha512-VSAqoIagIrc0A3apaqC2O3a8VtQ+asw8xILmxvjK/eHW9m1rmhJ5NqkGf7m+uSv3Yxini4bzyb74Mk62+tB/cA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.3.1.tgz", + "integrity": "sha512-Ckzel0NZ9CWhNsLfE1hxfDuxJuEbhQvGxSlmZ1/X8awjRmAA/g3kT6M1+MO1SHj1wMtPyUfd9WpwkiqFbiwQgA==", "requires": { "dotenv": "16.0.3", "dotenv-expand": "10.0.0", @@ -15145,32 +15148,24 @@ } }, "@nestjs/core": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.2.tgz", - "integrity": "sha512-79h4RvGAGFIIZJWIXqZ8xvhK/kIY6Fay7a1P0W4v7AUZsMIuNksct0uMzHaBqMT0lo+Ei+gU8PaWvzZt5lZvJw==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.9.tgz", + "integrity": "sha512-9g1A1G9eirLXEpH21rc6dKb08zHc2+adhCRz8NW39hbejcsxxD72FApJzt4QBQAKvu862ixt/tdpStnFT7lOSw==", "requires": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", - "object-hash": "3.0.0", "path-to-regexp": "3.2.0", "tslib": "2.5.0", - "uuid": "9.0.0" - }, - "dependencies": { - "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" - } + "uid": "2.0.1" } }, "@nestjs/jwt": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.0.1.tgz", - "integrity": "sha512-LwXBKVYHnFeX6GH/Wt0WDjsWCmNDC6tEdLlwNMAvJgYp+TkiCpEmQLkgRpifdUE29mvYSbjSnVs2kW2ob935NA==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.0.2.tgz", + "integrity": "sha512-MLxjCSbO7C9fN2hst5kpIhnJAgglJmrKppXAXqElB8A9ip3ZuCowMDjjmNWWJyfOzE98NV0E0iEQGE2StMUC+Q==", "requires": { - "@types/jsonwebtoken": "8.5.9", + "@types/jsonwebtoken": "9.0.1", "jsonwebtoken": "9.0.0" } }, @@ -15181,15 +15176,15 @@ "requires": {} }, "@nestjs/passport": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.1.tgz", - "integrity": "sha512-WhT0yhpMp1B8b1OdQdPv/rd2O8V0HUmoGsWFzJKPsALuaxozjem2WotUEy1GV/TT8kvfC4ok7tECjRAArO+I8Q==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-9.0.3.tgz", + "integrity": "sha512-HplSJaimEAz1IOZEu+pdJHHJhQyBOPAYWXYHfAPQvRqWtw4FJF1VXl1Qtk9dcXQX1eKytDtH+qBzNQc19GWNEg==", "requires": {} }, "@nestjs/platform-express": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.3.2.tgz", - "integrity": "sha512-hzLfUcJIFw8NIPlG88QJr+uSgJzkBkhxVsHGtRs+rNShzlMNfX63CPbkI4yfG4Eq0s8oYe598p6OE5O1z924Dg==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.3.9.tgz", + "integrity": "sha512-f8ja2sYuDGj2QSMmjg05n3WF19wJG5yTiYxRi64nsu5GKL0qLM1LzxNemehkni/knExlvF2bDpbKKpna9nC1JA==", "requires": { "body-parser": "1.20.1", "cors": "2.8.5", @@ -15315,9 +15310,9 @@ } }, "@nestjs/serve-static": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/serve-static/-/serve-static-3.0.0.tgz", - "integrity": "sha512-TpXjgs4136dQqWUjEcONqppqXDsrJhRkmKWzuBMOUAnP4HjHpNmlycvkHnDnWSoG2YD4a7Enh4ViYGWqCfHStA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/serve-static/-/serve-static-3.0.1.tgz", + "integrity": "sha512-i766UJPYOqvQ2BbRKh0/+Mmq5NkJnmKcShjWV1i5qpXyeM0KDZTn0n7g7ykWq/3LbQgjpMzrhYtGv35GX7GVQw==", "requires": { "path-to-regexp": "0.2.5" }, @@ -15342,9 +15337,9 @@ } }, "@nestjs/testing": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.3.2.tgz", - "integrity": "sha512-A1DleYwUpA/MX4XLTOJYEkhEjdI0HyujTmOUoPzSplAPWXbR48DTtY3Pu3A/qM7A8JwPzfB37glFUAJvFFOYpg==", + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.3.9.tgz", + "integrity": "sha512-+mPvSVvSC2SAkYgZZv1mOI2xsdGc1pmq7/sem7iin/JDoFtlvoGSK+pfZHD3IV3EpYtq1v/8/5gi+UFH9yZnDg==", "dev": true, "requires": { "tslib": "2.5.0" @@ -15607,9 +15602,9 @@ "dev": true }, "@types/eslint": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz", - "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==", + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.1.tgz", + "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==", "dev": true, "requires": { "@types/estree": "*", @@ -15633,13 +15628,13 @@ "dev": true }, "@types/express": { - "version": "4.17.16", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.16.tgz", - "integrity": "sha512-LkKpqRZ7zqXJuvoELakaFYuETHjZkSol8EV6cNnyishutDBCCdv6+dsKPbKkCcIk57qRphOLY5sEgClw1bO3gA==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", "dev": true, "requires": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.31", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } @@ -15705,9 +15700,9 @@ "dev": true }, "@types/jsonwebtoken": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", - "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==", "requires": { "@types/node": "*" } @@ -15725,9 +15720,9 @@ "dev": true }, "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==" }, "@types/nodemailer": { "version": "6.4.7", @@ -15745,9 +15740,9 @@ "dev": true }, "@types/passport": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.11.tgz", - "integrity": "sha512-pz1cx9ptZvozyGKKKIPLcVDVHwae4hrH5d6g5J+DkMRRjR3cVETb4jMabhXAUbg3Ov7T22nFHEgaK2jj+5CBpw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", + "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", "dev": true, "requires": { "@types/express": "*" @@ -15874,14 +15869,14 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.50.0.tgz", - "integrity": "sha512-vwksQWSFZiUhgq3Kv7o1Jcj0DUNylwnIlGvKvLLYsq8pAWha6/WCnXUeaSoNNha/K7QSf2+jvmkxggC1u3pIwQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", + "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/type-utils": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/type-utils": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -15892,53 +15887,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.50.0.tgz", - "integrity": "sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", + "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.50.0.tgz", - "integrity": "sha512-rt03kaX+iZrhssaT974BCmoUikYtZI24Vp/kwTSy841XhiYShlqoshRFDvN1FKKvU2S3gK+kcBW1EA7kNUrogg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", + "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0" + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0" } }, "@typescript-eslint/type-utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.50.0.tgz", - "integrity": "sha512-dcnXfZ6OGrNCO7E5UY/i0ktHb7Yx1fV6fnQGGrlnfDhilcs6n19eIRcvLBqx6OQkrPaFlDPk3OJ0WlzQfrV0bQ==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", + "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.50.0", - "@typescript-eslint/utils": "5.50.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.50.0.tgz", - "integrity": "sha512-atruOuJpir4OtyNdKahiHZobPKFvZnBnfDiyEaBf6d9vy9visE7gDjlmhl+y29uxZ2ZDgvXijcungGFjGGex7w==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", + "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.50.0.tgz", - "integrity": "sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", + "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -15947,28 +15942,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.50.0.tgz", - "integrity": "sha512-v/AnUFImmh8G4PH0NDkf6wA8hujNNcrwtecqW4vtQ1UOSNBaZl49zP1SHoZ/06e+UiwzHpgb5zP5+hwlYYWYAw==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", + "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.50.0.tgz", - "integrity": "sha512-cdMeD9HGu6EXIeGOh2yVW6oGf9wq8asBgZx7nsR/D36gTfQ0odE5kcRYe5M81vjEFAcPeugXrHg78Imu55F6gg==", + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", + "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/types": "5.52.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -16793,9 +16788,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", + "version": "1.0.30001456", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001456.tgz", + "integrity": "sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA==", "dev": true }, "chalk": { @@ -16875,9 +16870,9 @@ "dev": true }, "ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true }, "cjs-module-lexer": { @@ -17099,12 +17094,12 @@ "dev": true }, "core-js-compat": { - "version": "3.27.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.2.tgz", - "integrity": "sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.28.0.tgz", + "integrity": "sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg==", "dev": true, "requires": { - "browserslist": "^4.21.4" + "browserslist": "^4.21.5" } }, "core-util-is": { @@ -17282,9 +17277,9 @@ "dev": true }, "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "requires": { "has-property-descriptors": "^1.0.0", @@ -17361,9 +17356,9 @@ } }, "discord-api-types": { - "version": "0.37.31", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.31.tgz", - "integrity": "sha512-k9DQQ7Wv+ehiF7901qk/FnP47k6O2MHm3meQFee4gUzi5dfGAVLf7SfLNtb4w7G2dmukJyWQtVJEDF9oMb9yuQ==" + "version": "0.37.35", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.35.tgz", + "integrity": "sha512-iyKZ/82k7FX3lcmHiAvvWu5TmyfVo78RtghBV/YsehK6CID83k5SI03DKKopBcln+TiEIYw5MGgq7SJXSpNzMg==" }, "discord.js": { "version": "14.7.1", @@ -17481,9 +17476,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.4.285", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.285.tgz", - "integrity": "sha512-47o4PPgxfU1KMNejz+Dgaodf7YTcg48uOfV1oM6cs3adrl2+7R+dHkt3Jpxqo0LRCbGJEzTKMUt0RdvByb/leg==", + "version": "1.4.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.302.tgz", + "integrity": "sha512-Uk7C+7aPBryUR1Fwvk9VmipBcN9fVsqBO57jV2ZjTm+IZ6BMNqu7EDVEg2HxCNufk6QcWlFsBkhQyQroB2VWKw==", "dev": true }, "emittery": { @@ -17664,9 +17659,9 @@ } }, "eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", - "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", "dev": true, "requires": { "@eslint/eslintrc": "^1.4.1", @@ -17837,9 +17832,9 @@ "dev": true }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -18174,9 +18169,9 @@ } }, "file-type": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.0.tgz", - "integrity": "sha512-M3RQMWY3F2ykyWZ+IHwNCjpnUmukYhtdkGGC1ZVEUb0ve5REGF7NNJ4Q9ehCUabtQKtSVFOMbFTXgJlFb0DQIg==", + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", "requires": { "readable-web-to-node-stream": "^3.0.2", "strtok3": "^7.0.0", @@ -19435,14 +19430,14 @@ } }, "joi": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.0.tgz", - "integrity": "sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.1.tgz", + "integrity": "sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==", "requires": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", + "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, @@ -19590,9 +19585,9 @@ } }, "libphonenumber-js": { - "version": "1.10.19", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.19.tgz", - "integrity": "sha512-MDZ1zLIkfSDZV5xBta3nuvbEOlsnKCPe4z5r3hyup/AXveevkl9A1eSWmLhd2FX4k7pJDe4MrLeQsux0HI/VWg==", + "version": "1.10.20", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.20.tgz", + "integrity": "sha512-kQovlKNdLcVzerbTPmJ+Fx4R+7/pYXmPDIllHjg7IxL4X6MsMG7jaT5opfYrBok0uqkByVif//JUR8e11l/V7w==", "peer": true }, "lines-and-columns": { @@ -19839,14 +19834,14 @@ } }, "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.1.tgz", - "integrity": "sha512-V9esFpNbK0arbN3fm2sxDKqMYgIp7XtVdE4Esj+PE4Qaaxdg1wIw48ITQIOn1sc8xXSmUviVL3cyjMqPlrVkiA==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", + "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==" }, "minizlib": { "version": "2.1.2", @@ -20021,9 +20016,9 @@ "dev": true }, "node-releases": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", - "integrity": "sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "nodemailer": { @@ -20078,11 +20073,6 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" - }, "object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -20488,9 +20478,9 @@ "dev": true }, "prettier": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", - "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", "dev": true }, "prettier-linter-helpers": { @@ -20744,25 +20734,19 @@ "dev": true }, "regexpu-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", - "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.1.tgz", + "integrity": "sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ==", "dev": true, "requires": { + "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", "regjsparser": "^0.9.1", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" } }, - "regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, "regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", @@ -21614,9 +21598,9 @@ } }, "terser": { - "version": "5.16.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", - "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.4.tgz", + "integrity": "sha512-5yEGuZ3DZradbogeYQ1NaGz7rXVBDWujWlx1PT8efXO6Txn+eWbfKqB2bTDVmFXmePFkoLU6XI8UektMIEA0ug==", "dev": true, "requires": { "@jridgewell/source-map": "^0.3.2", @@ -21802,9 +21786,9 @@ } }, "ts-mixer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", - "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", + "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" }, "ts-morph": { "version": "13.0.3", @@ -21960,9 +21944,9 @@ } }, "undici": { - "version": "5.19.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.19.1.tgz", - "integrity": "sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", "requires": { "busboy": "^1.6.0" } @@ -22074,9 +22058,9 @@ "dev": true }, "v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.12", @@ -22303,9 +22287,9 @@ } }, "ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", + "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", "requires": {} }, "xmldoc": { @@ -22341,9 +22325,9 @@ "dev": true }, "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.0.tgz", + "integrity": "sha512-dwqOPg5trmrre9+v8SUo2q/hAwyKoVfu8OC1xPHKJGNdxAvPl4sKxL4vBnh3bQz/ZvvGAFeA5H3ou2kcOY8sQQ==", "dev": true, "requires": { "cliui": "^8.0.1", diff --git a/package.json b/package.json index 455e13a..39c2265 100644 --- a/package.json +++ b/package.json @@ -26,14 +26,14 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { - "@nestjs/common": "^9.3.2", - "@nestjs/config": "^2.3.0", - "@nestjs/core": "^9.3.2", - "@nestjs/jwt": "^10.0.1", - "@nestjs/passport": "^9.0.1", - "@nestjs/platform-express": "^9.3.2", + "@nestjs/common": "^9.3.9", + "@nestjs/config": "^2.3.1", + "@nestjs/core": "^9.3.9", + "@nestjs/jwt": "^10.0.2", + "@nestjs/passport": "^9.0.3", + "@nestjs/platform-express": "^9.3.9", "@nestjs/schedule": "^2.2.0", - "@nestjs/serve-static": "^3.0.0", + "@nestjs/serve-static": "^3.0.1", "@nestjs/swagger": "^6.2.1", "@prisma/client": "^4.10.1", "bcrypt": "^5.1.0", @@ -43,7 +43,7 @@ "discord.js": "^14.7.1", "helmet": "^5.1.1", "imdb-api": "^4.4.1", - "joi": "^17.7.0", + "joi": "^17.7.1", "nestjs-i18n": "^10.2.6", "nodemailer": "^6.9.1", "passport": "^0.6.0", @@ -57,24 +57,24 @@ "@compodoc/compodoc": "^1.1.19", "@nestjs/cli": "^9.2.0", "@nestjs/schematics": "^9.0.4", - "@nestjs/testing": "^9.3.2", + "@nestjs/testing": "^9.3.9", "@types/bcrypt": "^5.0.0", "@types/cron": "^2.0.0", "@types/crypto-js": "^4.1.1", - "@types/express": "^4.17.16", + "@types/express": "^4.17.17", "@types/jest": "28.1.4", - "@types/node": "^16.18.11", + "@types/node": "^16.18.12", "@types/nodemailer": "^6.4.7", "@types/passport-jwt": "^3.0.8", "@types/passport-local": "^1.0.35", "@types/supertest": "^2.0.12", - "@typescript-eslint/eslint-plugin": "^5.50.0", - "@typescript-eslint/parser": "^5.50.0", - "eslint": "^8.33.0", + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", + "eslint": "^8.34.0", "eslint-config-prettier": "^8.6.0", "eslint-plugin-prettier": "^4.2.1", "jest": "28.1.2", - "prettier": "^2.8.3", + "prettier": "^2.8.4", "prisma": "^4.10.1", "source-map-support": "^0.5.20", "supertest": "^6.3.3", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b3c9462..74d0741 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -27,7 +27,7 @@ model User { } model MovieInfo { - imdb_id String @id + imdb_id String language String title String year Int @@ -56,7 +56,7 @@ model Movie { } model History { - imdb_id String @id + imdb_id String language String watched_at DateTime @default(now()) title String diff --git a/src/common/db_services/movie_infos/movieInfoDB.service.ts b/src/common/db_services/movie_infos/movieInfoDB.service.ts index 7f067a1..1505042 100644 --- a/src/common/db_services/movie_infos/movieInfoDB.service.ts +++ b/src/common/db_services/movie_infos/movieInfoDB.service.ts @@ -8,7 +8,7 @@ export class MovieInfoDBService { constructor(private readonly prisma: PrismaService) { } - async get(imdb_id: string, language: string) { + async get(imdb_id: string, language: string = "en") { return this.prisma.movieInfo.findUnique({ where: { imdb_id_language: { imdb_id, language } } }).catch((e: Prisma.PrismaClientKnownRequestError) => { @@ -16,7 +16,7 @@ export class MovieInfoDBService { }); } - async get_all(language: string) { + async get_all(language: string = "en") { return this.prisma.movieInfo.findMany({ where: { language: language } }).catch((e: Prisma.PrismaClientKnownRequestError) => { diff --git a/src/common/db_services/movies/movieDB.service.ts b/src/common/db_services/movies/movieDB.service.ts index bfb2f35..64ac841 100644 --- a/src/common/db_services/movies/movieDB.service.ts +++ b/src/common/db_services/movies/movieDB.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable } from "@nestjs/common"; import { PrismaService } from "../prisma.service"; import { Prisma } from "@prisma/client"; import { MovieInfoDBService } from "../movie_infos/movieInfoDB.service"; @@ -7,11 +7,12 @@ import { MovieInfoDBService } from "../movie_infos/movieInfoDB.service"; export class MovieDBService { constructor(private readonly prisma: PrismaService, - private readonly movieInfo: MovieInfoDBService) {} + private readonly movieInfo: MovieInfoDBService) { + } - async get(imdb_id : string) { + async get(imdb_id: string) { return this.prisma.movie.findUnique({ - where: { imdb_id }, + where: { imdb_id } }); } @@ -19,11 +20,15 @@ export class MovieDBService { return this.prisma.movie.findMany(); } + async get_all_imdb(): Promise { + return (await this.prisma.movie.findMany({ select: { imdb_id: true } })).map((movie) => movie.imdb_id); + } + async has(imdb_id: string) { return (await this.prisma.movie.count({ where: { imdb_id } })) > 0; } - async get_all_proposed(user_id : number) { + async get_all_proposed(user_id: number) { return this.prisma.movie.findMany({ where: { proposer_id: user_id } }); @@ -38,11 +43,11 @@ export class MovieDBService { return this.prisma.movie.delete({ where: { imdb_id } }); } - async delete_all_proposed(user_id : number) { + async delete_all_proposed(user_id: number) { const movies = await this.get_all_proposed(user_id); for (const movie of movies) { await this.movieInfo.delete(movie.imdb_id); - await this.delete(movie.imdb_id) + await this.delete(movie.imdb_id); } } } diff --git a/src/common/event_service/event.module.ts b/src/common/event_service/event.module.ts index 41738a4..d20df3b 100644 --- a/src/common/event_service/event.module.ts +++ b/src/common/event_service/event.module.ts @@ -9,9 +9,10 @@ import { DiscordService } from "../util_services/discord.service"; import { AnnounceJob } from "./jobs/announce.job"; import { EmailService } from "../util_services/email.service"; import { UserDBModule } from "../db_services/users/userDB.module"; +import { MovieInfoDBModule } from "../db_services/movie_infos/movieInfoDB.module"; @Module({ - imports: [MovieDBModule, WatchListDBModule, VoteDBModule, HistoryDBModule, UserDBModule], + imports: [MovieDBModule, WatchListDBModule, VoteDBModule, HistoryDBModule, UserDBModule, MovieInfoDBModule], providers: [HistoryJob, WatchListJob, AnnounceJob, DiscordService, EmailService] }) export class EventModule {} diff --git a/src/common/event_service/jobs/announce.job.ts b/src/common/event_service/jobs/announce.job.ts index bde5da3..618a616 100644 --- a/src/common/event_service/jobs/announce.job.ts +++ b/src/common/event_service/jobs/announce.job.ts @@ -1,9 +1,8 @@ import { Injectable } from "@nestjs/common"; import { DiscordService } from "../../util_services/discord.service"; import { WatchListDBService } from "../../db_services/watchlist/watchListDB.service"; -import { MovieDBService } from "../../db_services/movies/movieDB.service"; -import { Movie } from "@prisma/client"; import { EmailService } from "../../util_services/email.service"; +import { MovieInfoDBService } from "../../db_services/movie_infos/movieInfoDB.service"; @Injectable() export class AnnounceJob { @@ -13,8 +12,10 @@ export class AnnounceJob { constructor(private readonly discordService: DiscordService, private readonly watchListDBService: WatchListDBService, - private readonly movieDBService: MovieDBService, + private readonly movieInfoDBService: MovieInfoDBService, private readonly emailService: EmailService) { + + this.announce_discord = (watchlist: string[]) => `<@&1041714399964041286>\n` + `Die Wahl ist durch, diese Filme werden geschaut:\n${watchlist.join("\n")}\n` + `Mehr Infos siehe auch ${process.env.FRONTEND_URL}\n\n` + @@ -31,9 +32,9 @@ export class AnnounceJob { const output = [] as string[]; for (const movie of watchlist) { - const movie_data = await this.movieDBService.get(movie.imdb_id) as Movie; + const movie_info_data = await this.movieInfoDBService.get(movie.imdb_id); const start_time = movie.start_time.toLocaleString(); - output.push(`${start_time} - ${movie_data.title}`); + output.push(`${start_time} - ${movie_info_data!.title}`); } await this.send_announce(output); diff --git a/src/common/event_service/jobs/history.job.ts b/src/common/event_service/jobs/history.job.ts index 7c13038..d05719c 100644 --- a/src/common/event_service/jobs/history.job.ts +++ b/src/common/event_service/jobs/history.job.ts @@ -2,9 +2,10 @@ import { Injectable } from "@nestjs/common"; import { MovieDBService } from "../../db_services/movies/movieDB.service"; import { HistoryDBService } from "../../db_services/histroy/historyDB.service"; import { WatchListDBService } from "../../db_services/watchlist/watchListDB.service"; -import { Movie, Prisma } from "@prisma/client"; +import { MovieInfo, Prisma } from "@prisma/client"; import { VoteDBService } from "../../db_services/votes/voteDB.service"; import { Cron } from "@nestjs/schedule"; +import { MovieInfoDBService } from "../../db_services/movie_infos/movieInfoDB.service"; @Injectable() export class HistoryJob { @@ -12,6 +13,7 @@ export class HistoryJob { constructor(private readonly movieDBService: MovieDBService, private readonly historyDBService: HistoryDBService, private readonly watchListDBService: WatchListDBService, + private readonly movieInfoDBService: MovieInfoDBService, private readonly voteDBService: VoteDBService) {} @Cron(process.env.SCHEDULE_HISTORY as string) @@ -19,11 +21,11 @@ export class HistoryJob { console.log('History job started'); const watch_list = await this.watchListDBService.get_all() for (const movie of watch_list) { - const movie_data = await this.movieDBService.get(movie.imdb_id) as Movie + const movie_info_data = await this.movieInfoDBService.get(movie.imdb_id) as MovieInfo const data = { - imdb_id: movie.imdb_id, - title: movie_data.title, - link: movie_data.link + imdb_id: movie_info_data.imdb_id, + title: movie_info_data.title, + link: movie_info_data.link } as Prisma.HistoryCreateInput await this.historyDBService.add(data) await this.voteDBService.delete_all(movie.imdb_id) diff --git a/src/common/event_service/jobs/watchlist.job.ts b/src/common/event_service/jobs/watchlist.job.ts index 345b6e4..71c0655 100644 --- a/src/common/event_service/jobs/watchlist.job.ts +++ b/src/common/event_service/jobs/watchlist.job.ts @@ -1,11 +1,11 @@ import { Injectable } from "@nestjs/common"; import { WatchListDBService } from "../../db_services/watchlist/watchListDB.service"; import { VoteDBService } from "../../db_services/votes/voteDB.service"; -import { MovieDBService } from "../../db_services/movies/movieDB.service"; import { parseExpression } from "cron-parser" -import { Movie, Prisma } from "@prisma/client"; +import { MovieInfo, Prisma } from "@prisma/client"; import { Cron } from "@nestjs/schedule"; import { AnnounceJob } from "./announce.job"; +import { MovieInfoDBService } from "../../db_services/movie_infos/movieInfoDB.service"; @Injectable() export class WatchListJob { @@ -15,7 +15,7 @@ export class WatchListJob { constructor(private readonly voteDBService: VoteDBService, private readonly watchListDBService: WatchListDBService, - private readonly movieDBService: MovieDBService, + private readonly movieInfoDBService: MovieInfoDBService, private readonly announceJob: AnnounceJob) {} @Cron(process.env.SCHEDULE_WATCHLIST as string) @@ -31,8 +31,8 @@ export class WatchListJob { } as Prisma.WatchListCreateInput await this.watchListDBService.add(data) - const movie_data = await this.movieDBService.get(movie.imdb_id) as Movie - const round_duration_ms = (Math.round(movie_data.runtime/15) * 15) * 60000 + const movie_info_data = await this.movieInfoDBService.get(movie.imdb_id) as MovieInfo + const round_duration_ms = (Math.round(movie_info_data.runtime/15) * 15) * 60000 start_time = new Date(start_time.getTime() + round_duration_ms + this.pause_time) } diff --git a/src/common/util_services/imdb_api.service.ts b/src/common/util_services/imdb_api.service.ts index 64ec722..d5d5620 100644 --- a/src/common/util_services/imdb_api.service.ts +++ b/src/common/util_services/imdb_api.service.ts @@ -10,7 +10,7 @@ export class ImdbApiService { api_key = process.env.IMDB_API_KEY; - async get_movie_info(imdb_id: string, lang: string = "en"): Promise { + async get(imdb_id: string, lang: string = "en"): Promise { const response = await fetch(`https://imdb-api.com/${lang}/API/Title/${this.api_key}/${imdb_id}`); const movie = await response.json() as any; @@ -35,19 +35,19 @@ export class ImdbApiService { } as Prisma.MovieInfoCreateInput; } - async get_movie_info_all_langs(imdb_id: string): Promise { + async get_all_langs(imdb_id: string): Promise { const langs = ["en", "de"]; const movie_infos: Prisma.MovieInfoCreateInput[] = []; for (const lang of langs) { - const movie_info = await this.get_movie_info(imdb_id, lang); + const movie_info = await this.get(imdb_id, lang); if (movie_info.imdb_id !== undefined) movie_infos.push(movie_info); } return movie_infos; } - async search_movie(search_input: string, lang: string = "en"): Promise { + async search(search_input: string, lang: string = "en"): Promise { const response = await fetch(`https://imdb-api.com/${lang}/API/SearchMovie/${this.api_key}/${search_input}`); const data = await response.json() as any; const movies = data.results as any[]; diff --git a/src/routes/auth/auth.service.ts b/src/routes/auth/auth.service.ts index 063253b..a76304b 100644 --- a/src/routes/auth/auth.service.ts +++ b/src/routes/auth/auth.service.ts @@ -7,7 +7,7 @@ import { } from "@nestjs/common"; import { UserDBService } from '../../common/db_services/users/userDB.service'; import { JwtService } from '@nestjs/jwt'; -import { PrismaClientKnownRequestError } from "@prisma/client/runtime"; +import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library"; import { EmailService } from "../../common/util_services/email.service"; import { PasswordService } from "../../common/util_services/password.service"; import cuid from "cuid"; diff --git a/src/routes/movie/movie.controller.ts b/src/routes/movie/movie.controller.ts index daf0e3e..821d03f 100644 --- a/src/routes/movie/movie.controller.ts +++ b/src/routes/movie/movie.controller.ts @@ -6,7 +6,7 @@ import { User } from "../../common/decorators/user.decorator"; import { JwtUser } from "../../types/jwtuser.type"; import { MovieExtType } from "../../types/movie.types/movie_ext.type"; import { WatchlistExtType } from "../../types/movie.types/watchlist_ext.type"; -import { History, Vote, Movie } from "@prisma/client"; +import { History, MovieInfo } from "@prisma/client"; import { ResDto } from "../../types/res.dto"; import { I18n, I18nContext } from "nestjs-i18n"; import { I18nTranslations } from "../../types/generated/i18n.generated"; @@ -23,20 +23,20 @@ export class MovieController { @ApiOperation({ summary: 'GET all movies with its related data' }) @Get('all') - async get_all_media() : Promise { - return await this.movieService.get_all() + async get_all_media(@I18n() i18n: I18nContext) : Promise { + return await this.movieService.get_all(i18n) } @ApiOperation({ summary: 'GET all movies from watchlist with its related data' }) @Get('watchlist') - async get_watchlist() : Promise { - return await this.movieService.get_watchlist() + async get_watchlist(@I18n() i18n: I18nContext) : Promise { + return await this.movieService.get_watchlist(i18n) } @ApiOperation({ summary: 'GET all movies from history with its related data' }) @Get('history') async get_history() : Promise { - return await this.movieService.get_history() + return this.movieService.get_history(); } @ApiOperation({ summary: 'POST returns up to 10 matching movies from input string' }) @@ -49,7 +49,7 @@ export class MovieController { @ApiOperation({ summary: 'GET information about a specific movie given by its imdb_id' }) @Get(':imdb_id') - async get_media(@Param('imdb_id') imdb_id: string, @I18n() i18n: I18nContext) : Promise { + async get_info(@Param('imdb_id') imdb_id: string, @I18n() i18n: I18nContext) : Promise { return await this.movieService.get(imdb_id, i18n) } @@ -57,7 +57,7 @@ export class MovieController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post(':imdb_id') - async post_media(@User() user: JwtUser, @Param('imdb_id') imdb_id: string, @I18n() i18n: I18nContext): Promise<{movie: Movie, vote: Vote}> { + async post_media(@User() user: JwtUser, @Param('imdb_id') imdb_id: string, @I18n() i18n: I18nContext): Promise<{movie: MovieExtType}> { return await this.movieService.save(imdb_id, Number(user.id), i18n) } diff --git a/src/routes/movie/movie.module.ts b/src/routes/movie/movie.module.ts index e19636f..bd494e9 100644 --- a/src/routes/movie/movie.module.ts +++ b/src/routes/movie/movie.module.ts @@ -8,10 +8,12 @@ import { VoteDBModule } from "../../common/db_services/votes/voteDB.module"; import { VoteService } from "../vote/vote.service"; import { HistoryDBModule } from "../../common/db_services/histroy/historyDB.module"; import { WatchListDBModule } from "../../common/db_services/watchlist/watchListDB.module"; +import { MovieInfoDBModule } from "../../common/db_services/movie_infos/movieInfoDB.module"; +import { ImdbApiService } from "../../common/util_services/imdb_api.service"; @Module({ - imports: [MovieDBModule, UserDBModule, VoteDBModule, HistoryDBModule, WatchListDBModule], + imports: [MovieDBModule, UserDBModule, VoteDBModule, HistoryDBModule, WatchListDBModule, MovieInfoDBModule], controllers: [MovieController], - providers: [PrismaService, MovieService, VoteService] + providers: [PrismaService, MovieService, VoteService, ImdbApiService] }) export class MovieModule {} diff --git a/src/routes/movie/movie.service.ts b/src/routes/movie/movie.service.ts index 98a93ea..101239f 100644 --- a/src/routes/movie/movie.service.ts +++ b/src/routes/movie/movie.service.ts @@ -5,9 +5,8 @@ import { InternalServerErrorException, NotFoundException } from "@nestjs/common"; -import { Client } from "imdb-api"; import { MovieDBService } from "../../common/db_services/movies/movieDB.service"; -import { Prisma, User, Movie } from "@prisma/client"; +import { Prisma, User, Movie, MovieInfo } from "@prisma/client"; import { UserDBService } from "../../common/db_services/users/userDB.service"; import { VoteDBService } from "../../common/db_services/votes/voteDB.service"; import { VoteService } from "../vote/vote.service"; @@ -18,181 +17,178 @@ import { WatchlistExtType } from "../../types/movie.types/watchlist_ext.type"; import { ResDto } from "../../types/res.dto"; import { imdb_id_pattern } from "../../common/validation/patterns/imdb_id.pattern"; import { I18nContext } from "nestjs-i18n"; -import { I18nTranslations } from 'src/types/generated/i18n.generated'; +import { I18nTranslations } from "src/types/generated/i18n.generated"; import { MovieSearchType } from "../../types/movie.types/movie_search.type"; import * as process from "process"; -import { OmdbSearchDto } from "../../types/movie.dto/omdb_search.dto"; +import { MovieInfoDBService } from "../../common/db_services/movie_infos/movieInfoDB.service"; +import { ImdbApiService } from "../../common/util_services/imdb_api.service"; @Injectable() export class MovieService { - private readonly imdb: Client - private readonly max_proposeable_movies = Number(process.env.MAX_PROPOSEABLE_MOVIES) + private readonly max_proposeable_movies = Number(process.env.MAX_PROPOSEABLE_MOVIES); constructor(private readonly movieDBService: MovieDBService, + private readonly movieInfoDBService: MovieInfoDBService, private readonly userDBService: UserDBService, private readonly voteDBService: VoteDBService, private readonly histroyDBService: HistoryDBService, private readonly watchlistDBService: WatchListDBService, - private readonly voteService: VoteService) { - this.imdb = new Client({apiKey: process.env.OMDB_API_KEY}) + private readonly voteService: VoteService, + private readonly imdbApiService: ImdbApiService) { } - async get(imdb_id: string, i18n: I18nContext) { + async get(imdb_id: string, i18n: I18nContext): Promise { try { - return await this.movieDBService.get(imdb_id) as Movie + return await this.movieInfoDBService.get(imdb_id, i18n.lang) as MovieInfo; } catch (e) { - throw new NotFoundException(i18n.t('movie.exception.not_found')) + throw new NotFoundException(i18n.t("movie.exception.not_found")); } } - private async get_from_omdb(imdb_id: string, i18n: I18nContext) { - try { - return await this.imdb.get({ id: imdb_id }) - } catch (e) { - throw new NotFoundException(i18n.t('movie.exception.not_found')) - } + async get_ext(imdb_id: string, i18n: I18nContext): Promise { + const movie = await this.movieDBService.get(imdb_id) as Movie; + const user = await this.userDBService.get({ id: movie.proposer_id }) as User; + const votes = await this.voteDBService.get_num_of_votes(movie.imdb_id); + const movie_info = await this.movieInfoDBService.get(movie.imdb_id, i18n.lang) as MovieInfo; + + return { + imdb_id: movie.imdb_id, + title: movie_info.title, + link: movie_info.link, + year: movie_info.year, + genre: movie_info.genre, + proposer: user.name, + proposer_id: movie.proposer_id, + director: movie_info.director, + actors: movie_info.actors, + imdb_rate: movie_info.imdb_rate, + meta_score: movie_info.meta_score, + rotten_score: movie_info.rotten_score, + languages: movie_info.languages, + created_at: movie.created_at, + votes: votes + } as MovieExtType; } - async get_all() { - const movies = await this.movieDBService.get_all() - return await Promise.all(movies.map(async (movie) => { - const user = await this.userDBService.get({ id: movie.proposer_id }) as User - const votes = await this.voteDBService.get_num_of_votes(movie.imdb_id) + async get_all(i18n: I18nContext): Promise { + const imdb_ids = await this.movieDBService.get_all_imdb(); - return { - imdb_id: movie.imdb_id, - title: movie.title, - link: movie.link, - year: movie.year, - genre: movie.genre, - proposer: user.name, - proposer_id: movie.proposer_id, - director: movie.director, - actors: movie.actors, - imdb_rate: movie.imdb_rate, - language: movie.language, - metascore: movie.metascore, - createdAt: movie.createdAt, - votes - } as MovieExtType; + return await Promise.all(imdb_ids.map(async (imdb_id) => { + return await this.get_ext(imdb_id, i18n); })); } - async search(search_input: string, i18n: I18nContext) : Promise { + async search(search_input: string, i18n: I18nContext): Promise { if (search_input.length < 3) { - throw new ForbiddenException(i18n.t('movie.exception.invalid_search_length')) - } - - let movies = [] - try { - const res = await (await fetch(`https://www.omdbapi.com/?apikey=${process.env.OMDB_API_KEY}&s=${search_input}&type=movie`)).json() as any - if (res.Response === 'False') return [] - movies = res.Search as OmdbSearchDto[] - - } catch (e) { - console.log(e) - throw new InternalServerErrorException() + throw new ForbiddenException(i18n.t("movie.exception.invalid_search_length")); } - return movies.map((movie) => { - return { - imdb_id: movie.imdbID, - title: movie.Title, - year: movie.Year - } - }) as MovieSearchType[] + return await this.imdbApiService.search(search_input, i18n.lang); } async save(imdb_id: string, proposer_id: number, i18n: I18nContext) { if (!imdb_id_pattern.test(imdb_id)) { - throw new ForbiddenException(i18n.t('movie.exception.invalid_imdb_id')) + throw new ForbiddenException(i18n.t("movie.exception.invalid_imdb_id")); } if (await this.histroyDBService.has(imdb_id)) { - throw new ConflictException(i18n.t('movie.exception.conflict_history')) + throw new ConflictException(i18n.t("movie.exception.conflict_history")); } if (await this.movieDBService.has(imdb_id)) { - throw new ConflictException(i18n.t('movie.exception.conflict_movie')) + throw new ConflictException(i18n.t("movie.exception.conflict_movie")); } if ((await this.movieDBService.get_all_proposed(proposer_id)).length >= this.max_proposeable_movies) { - throw new ConflictException(i18n.t('movie.exception.conflict_max_proposed', { args: { - max_proposeable_movies: this.max_proposeable_movies - } })) + throw new ConflictException(i18n.t("movie.exception.conflict_max_proposed", { + args: { + max_proposeable_movies: this.max_proposeable_movies + } + })); } - const movie = await this.get_from_omdb(imdb_id, i18n) - const { username } : Prisma.UserCreateInput = await this.userDBService.get({id: proposer_id}) as User + const movie_imdb_api = await this.imdbApiService.get_all_langs(imdb_id); + const { username }: Prisma.UserCreateInput = await this.userDBService.get({ id: proposer_id }) as User; const movieDB_data: Prisma.MovieCreateInput = { imdb_id: imdb_id, - title: movie.title, - year: movie.year, - genre: movie.genres, - link: movie.imdburl, proposer: { connect: { username } } as Prisma.UserCreateNestedOneWithoutMovieInput, - runtime: Number((movie.runtime.split(" "))[0]), - director: movie.director, - actors: movie.actors, - imdb_rate: movie.rating, - poster: movie.poster, - plot: movie.plot, - language: movie.languages, - metascore: movie.metascore, } - try { - return this.movieDBService.add(movieDB_data).then((movie) => { - return this.voteService.vote(movie.imdb_id, proposer_id, i18n) - .then((vote) => { - return { movie, vote, message: i18n.t('movie.success.save'), show_alert: true } - }) - .catch((e) => { - this.movieDBService.delete(movie.imdb_id) - throw e - }) - }) - } catch (e) { - throw new ConflictException(i18n.t('movie.exception.conflict_movie')) - } + movie_imdb_api.map((movie) => { + return { + imdb_id: imdb_id, + language: movie.language, + title: movie.title, + year: movie.year, + genre: movie.genre, + link: movie.link, + runtime: Number(movie.runtime), + director: movie.director, + actors: movie.actors, + imdb_rate: movie.imdb_rate, + meta_score: movie.meta_score, + rotten_score: movie.rotten_score, + poster: movie.poster, + plot: movie.plot, + languages: movie.languages, + } as Prisma.MovieInfoCreateInput; + }) + + await this.movieDBService.add(movieDB_data).catch(() => { + throw new ConflictException(i18n.t("movie.exception.conflict_movie")) + }) + + await this.voteService.vote(imdb_id, proposer_id, i18n).catch((e) => { + this.movieDBService.delete(imdb_id); + throw new InternalServerErrorException(e); + }) + + await this.movieInfoDBService.add(movie_imdb_api).catch((e) => { + this.movieDBService.delete(imdb_id); + this.voteService.unvote(imdb_id, proposer_id, i18n); + throw new InternalServerErrorException(e) + }) + + return { movie: await this.get_ext(imdb_id, i18n), message: i18n.t("movie.success.save"), show_alert: true }; } async delete(imdb_id: string, proposer_id: string, i18n: I18nContext) { - const movie = await this.movieDBService.get(imdb_id) as Movie - const watchlist = await this.watchlistDBService.get_all() - const watchlist_imdbs = watchlist.map((movie) => movie.imdb_id) + const movie = await this.movieDBService.get(imdb_id) as Movie; + const movie_info = await this.movieInfoDBService.get(imdb_id, i18n.lang) as MovieInfo; + const watchlist = await this.watchlistDBService.get_all(); + const watchlist_imdbs = watchlist.map((movie) => movie.imdb_id); if (watchlist_imdbs.includes(imdb_id)) { - throw new ConflictException(i18n.t('movie.exception.conflict_watchlist')) - } - else if (movie.proposer_id === Number(proposer_id)) { - await this.voteDBService.delete_all(imdb_id) - await this.movieDBService.delete(imdb_id) - return { message: i18n.t('movie.success.delete', {args: { title: movie.title }}), show_alert: true } as ResDto + throw new ConflictException(i18n.t("movie.exception.conflict_watchlist")); + } else if (movie.proposer_id === Number(proposer_id)) { + await this.voteDBService.delete_all(imdb_id); + await this.movieDBService.delete(imdb_id); + return { message: i18n.t("movie.success.delete", { args: { title: movie_info.title } }), show_alert: true } as ResDto; } else { - throw new NotFoundException(i18n.t('movie.exception.not_found_or_not_proposer')) + throw new NotFoundException(i18n.t("movie.exception.not_found_or_not_proposer")); } } - async get_watchlist() { - const watchlist = await this.watchlistDBService.get_all() + async get_watchlist(i18n: I18nContext) { + const watchlist = await this.watchlistDBService.get_all(); return await Promise.all(watchlist.map(async (watch_movie) => { - const movie = await this.movieDBService.get(watch_movie.imdb_id) as Movie - const votes = await this.voteDBService.get_votes_movie(movie.imdb_id) + const movie = await this.movieDBService.get(watch_movie.imdb_id) as Movie; + const movie_info = await this.movieInfoDBService.get(watch_movie.imdb_id, i18n.lang) as MovieInfo; + const votes = await this.voteDBService.get_votes_movie(movie.imdb_id); return { imdb_id: movie.imdb_id, - title: movie.title, - link: movie.link, + title: movie_info.title, + link: movie_info.link, start_time: watch_movie.start_time, interested: votes.map((vote) => vote.user.id) - } as WatchlistExtType - })) + } as WatchlistExtType; + })); } async get_history() { - return await this.histroyDBService.get_all() + return this.histroyDBService.get_all(); } } diff --git a/src/types/movie.dto/omdb_search.dto.ts b/src/types/movie.dto/omdb_search.dto.ts deleted file mode 100644 index 63427d8..0000000 --- a/src/types/movie.dto/omdb_search.dto.ts +++ /dev/null @@ -1,8 +0,0 @@ - -export class OmdbSearchDto { - Title!: string - Year!: string - imdbID!: string - Type!: string - Poster!: string -} diff --git a/src/types/movie.types/movie_ext.type.ts b/src/types/movie.types/movie_ext.type.ts index b4cb70b..c91b050 100644 --- a/src/types/movie.types/movie_ext.type.ts +++ b/src/types/movie.types/movie_ext.type.ts @@ -9,8 +9,8 @@ export class MovieExtType { proposer_id!: number director!: string actors!: string - language!: string - imdb_rate!: number + languages!: string + imdb_rate!: string rotten_score!: string meta_score!: string created_at!: Date From a2f2037dacad88750dc302e2a8ebee5e82245717 Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Sat, 18 Feb 2023 23:02:41 +0100 Subject: [PATCH 06/38] backend: update movie routes and jobs to new api and db model now also for history --- .../db_services/histroy/historyDB.service.ts | 15 +++++++++++++++ src/routes/movie/movie.controller.ts | 7 ++++--- src/routes/movie/movie.service.ts | 4 ++-- .../movie.types/history_without_lang.type.ts | 6 ++++++ 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 src/types/movie.types/history_without_lang.type.ts diff --git a/src/common/db_services/histroy/historyDB.service.ts b/src/common/db_services/histroy/historyDB.service.ts index b543ce8..b61c49b 100644 --- a/src/common/db_services/histroy/historyDB.service.ts +++ b/src/common/db_services/histroy/historyDB.service.ts @@ -1,6 +1,7 @@ import { Injectable } from "@nestjs/common"; import { PrismaService } from "../prisma.service"; import { Prisma } from "@prisma/client"; +import { HistoryWithoutLangType } from "../../../types/movie.types/history_without_lang.type"; @Injectable() export class HistoryDBService { @@ -11,6 +12,20 @@ export class HistoryDBService { return this.prisma.history.findMany(); } + async get_all_without_lang(language: string): Promise { + return this.prisma.history.findMany({ + select: { + imdb_id: true, + watched_at: true, + title: true, + link: true, + }, + where: { + language: language + } + }); + } + async add(data: Prisma.HistoryCreateInput) { return this.prisma.history.create({ data }); } diff --git a/src/routes/movie/movie.controller.ts b/src/routes/movie/movie.controller.ts index 821d03f..3e36587 100644 --- a/src/routes/movie/movie.controller.ts +++ b/src/routes/movie/movie.controller.ts @@ -6,11 +6,12 @@ import { User } from "../../common/decorators/user.decorator"; import { JwtUser } from "../../types/jwtuser.type"; import { MovieExtType } from "../../types/movie.types/movie_ext.type"; import { WatchlistExtType } from "../../types/movie.types/watchlist_ext.type"; -import { History, MovieInfo } from "@prisma/client"; +import { MovieInfo } from "@prisma/client"; import { ResDto } from "../../types/res.dto"; import { I18n, I18nContext } from "nestjs-i18n"; import { I18nTranslations } from "../../types/generated/i18n.generated"; import { MovieSearchType } from "../../types/movie.types/movie_search.type"; +import { HistoryWithoutLangType } from "../../types/movie.types/history_without_lang.type"; /** * Controller for movie related routes @@ -35,8 +36,8 @@ export class MovieController { @ApiOperation({ summary: 'GET all movies from history with its related data' }) @Get('history') - async get_history() : Promise { - return this.movieService.get_history(); + async get_history(@I18n() i18n: I18nContext) : Promise { + return this.movieService.get_history(i18n); } @ApiOperation({ summary: 'POST returns up to 10 matching movies from input string' }) diff --git a/src/routes/movie/movie.service.ts b/src/routes/movie/movie.service.ts index 101239f..db03f24 100644 --- a/src/routes/movie/movie.service.ts +++ b/src/routes/movie/movie.service.ts @@ -188,7 +188,7 @@ export class MovieService { })); } - async get_history() { - return this.histroyDBService.get_all(); + async get_history(i18n: I18nContext) { + return this.histroyDBService.get_all_without_lang(i18n.lang); } } diff --git a/src/types/movie.types/history_without_lang.type.ts b/src/types/movie.types/history_without_lang.type.ts new file mode 100644 index 0000000..c00e43c --- /dev/null +++ b/src/types/movie.types/history_without_lang.type.ts @@ -0,0 +1,6 @@ +export class HistoryWithoutLangType { + imdb_id!: string + watched_at!: Date + title!: string + link!: string +} \ No newline at end of file From 0802e5fbcda06841317b6212ac3caec9c99b61fc Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Mon, 20 Feb 2023 13:46:15 +0100 Subject: [PATCH 07/38] client: add defineComponent to every component for better ts support --- client/src/components/CardComponent.vue | 6 ++++-- client/src/components/ModalComponent.vue | 6 ++++-- client/src/components/WatchlistComponent.vue | 6 +++--- client/src/components/alert/AlertDangerComponent.vue | 2 -- client/src/components/err/NotImplementedComponent.vue | 6 ++++-- client/src/components/form/EmailComponent.vue | 6 ++++-- client/src/components/form/FormComponent.vue | 5 +++-- client/src/components/form/InputComponent.vue | 6 ++++-- client/src/components/form/NameComponent.vue | 5 +++-- client/src/components/form/PasswordComponent.vue | 5 +++-- client/src/components/form/SubmitComponent.vue | 5 +++-- client/src/components/movie/MovieSearchComponent.vue | 5 +++-- client/src/components/movie/MovieSearchElementComponent.vue | 6 ++++-- client/src/views/DocsView.vue | 5 +++-- client/src/views/HistoryView.vue | 6 +++--- client/src/views/LoginView.vue | 5 +++-- client/src/views/PrivacyView.vue | 6 ++++-- client/src/views/ProfileView.vue | 6 +++--- client/src/views/RegisterView.vue | 5 +++-- client/src/views/ResetRequestView.vue | 5 +++-- client/src/views/ResetView.vue | 6 +++--- 21 files changed, 67 insertions(+), 46 deletions(-) diff --git a/client/src/components/CardComponent.vue b/client/src/components/CardComponent.vue index 3d7f2e3..8a3ed3d 100644 --- a/client/src/components/CardComponent.vue +++ b/client/src/components/CardComponent.vue @@ -14,7 +14,9 @@ \ No newline at end of file diff --git a/client/src/views/HomeView.vue b/client/src/views/HomeView.vue index 45ef515..6ed7736 100644 --- a/client/src/views/HomeView.vue +++ b/client/src/views/HomeView.vue @@ -3,7 +3,7 @@
+ :disabled="!store.logged_in">{{ $t("movie.modal.title") }} + @@ -50,8 +50,7 @@
-
+ -

----- OR -----

+

----- OR -----

@@ -89,7 +88,7 @@
- + @@ -111,6 +110,7 @@ import MovieSearchComponent from "@/components/movie/MovieSearchComponent.vue"; import MovieBigPictureComponent from "@/components/movie/MovieBigPictureComponent.vue"; import type { MovieExtType } from "@/types/movie.types/movie_ext.type" import type { JwtUser } from "@/types/user.types/user_jwt.type"; +import FormVal from "@/components/form/FormVal.Component.vue"; const search_movies = ref([] as any[]); @@ -126,6 +126,7 @@ export default defineComponent({ }; }, components: { + FormVal, MovieBigPictureComponent, TableComponent, FormComponent, @@ -155,7 +156,6 @@ export default defineComponent({ }); } - return { movies, votes, @@ -163,22 +163,20 @@ export default defineComponent({ }; }, methods: { - search_media(e: Event) { - const search_input = (e.target as HTMLInputElement).value; - if (search_input.length < 3) return; - if (/^tt[0-9]+$/.test(search_input)) return; + search_media(e: Event, form_html: HTMLFormElement) { + if (this.movie_add_with_imdb_id) { + this.add_media(e, form_html); - call("api/movie/search", "POST", { search_input }) - .then((data) => { - search_movies.value = data; - }); - }, - add_media(e: Event) { - const form_html = e.target as HTMLFormElement; - if (!form_html.checkValidity()) { - return; + } else { + const form = new FormData(form_html); + const search_input = form.get("movie_title") as string; + call("api/movie/search", "POST", { search_input }) + .then((data) => { + search_movies.value = data; + }); } - + }, + add_media(e: Event, form_html: HTMLFormElement) { const form = new FormData(form_html); const imdb_id = form.get("imdb_id") as string; diff --git a/client/src/views/ProfileView.vue b/client/src/views/ProfileView.vue index 4d95eeb..8b1af76 100644 --- a/client/src/views/ProfileView.vue +++ b/client/src/views/ProfileView.vue @@ -37,45 +37,45 @@ -
+ - +
-
+ - +
-
+ - +

{{ $t('profile.form.delete_account.desc') }}


-
+ - +
@@ -91,11 +91,13 @@ import { defineComponent, ref } from "vue"; import router from "@/router/router"; import CardComponent from "@/components/CardComponent.vue"; import type { UserSlimType } from "@/types/user.types/user_slim.type"; +import FormVal from "@/components/form/FormVal.Component.vue"; const user = ref({} as UserSlimType) export default defineComponent({ name: "ProfileComponent", components: { + FormVal, CardComponent, InputComponent, NameComponent, From 79460e621daa8d53214af2248b808d792f9a035a Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Tue, 21 Feb 2023 12:03:29 +0100 Subject: [PATCH 16/38] client: make lang change dynamic for backend informations --- client/src/components/NavbarComponent.vue | 11 ++++--- .../movie/MovieBigPictureComponent.vue | 16 ++++++++-- client/src/views/HistoryView.vue | 25 ++++++++++++---- client/src/views/HomeView.vue | 29 ++++++++++++------- 4 files changed, 58 insertions(+), 23 deletions(-) diff --git a/client/src/components/NavbarComponent.vue b/client/src/components/NavbarComponent.vue index 646046c..2998406 100644 --- a/client/src/components/NavbarComponent.vue +++ b/client/src/components/NavbarComponent.vue @@ -61,13 +61,10 @@ - - diff --git a/client/src/views/HistoryView.vue b/client/src/views/HistoryView.vue index ed43c9c..558da2b 100644 --- a/client/src/views/HistoryView.vue +++ b/client/src/views/HistoryView.vue @@ -13,19 +13,34 @@ import { ref, defineComponent } from "vue"; import { call } from "@/util/api"; import type { History } from "@prisma/client"; +const history = ref([] as History[]) + export default defineComponent({ name: "HistoryComponent", components: { TableComponent }, + data() { + return { + history + } + }, + methods: { + get_history() { + call("/api/movie/history") + .then((data: History[]) => { + history.value = data; + }); + } + }, + mounted() { + this.$i18next.on("languageChanged", () => { + this.get_history() + }) + }, setup() { - const history = ref([] as History[]) call("/api/movie/history") .then((data: History[]) => { history.value = data; }); - - return { - history - } } }); diff --git a/client/src/views/HomeView.vue b/client/src/views/HomeView.vue index 6ed7736..5806633 100644 --- a/client/src/views/HomeView.vue +++ b/client/src/views/HomeView.vue @@ -112,6 +112,9 @@ import type { MovieExtType } from "@/types/movie.types/movie_ext.type" import type { JwtUser } from "@/types/user.types/user_jwt.type"; import FormVal from "@/components/form/FormVal.Component.vue"; +const movies = ref([] as MovieExtType[]); +const votes = ref([] as string[]); +const user_id = ref(-1); const search_movies = ref([] as any[]); export default defineComponent({ @@ -122,7 +125,10 @@ export default defineComponent({ search_movies, big_picture_imdb_id: ref(""), big_picture_title: ref(""), - movie_add_with_imdb_id: ref(false) + movie_add_with_imdb_id: ref(false), + movies, + votes, + user_id }; }, components: { @@ -136,10 +142,6 @@ export default defineComponent({ ModalComponent }, setup() { - const movies = ref([] as MovieExtType[]); - const votes = ref([] as string[]); - const user_id = ref(-1); - call("api/movie/all") .then((data: MovieExtType[]) => { movies.value = data; @@ -155,12 +157,11 @@ export default defineComponent({ user_id.value = data.id; }); } - - return { - movies, - votes, - user_id - }; + }, + mounted() { + this.$i18next.on("languageChanged", () => { + this.get_movies_all() + }) }, methods: { search_media(e: Event, form_html: HTMLFormElement) { @@ -228,6 +229,12 @@ export default defineComponent({ delete votes[slice_index]; } }); + }, + get_movies_all() { + call("api/movie/all") + .then((data: MovieExtType[]) => { + movies.value = data; + }); } } }); From 96611d015c534834af7b91408d6efd455b9fbbf8 Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Tue, 21 Feb 2023 17:52:40 +0100 Subject: [PATCH 17/38] client: implement vote button in watchlist by providing new components for voting --- client/src/components/WatchlistComponent.vue | 27 ++++- client/src/components/form/FormComponent.vue | 2 +- ...Val.Component.vue => FormValComponent.vue} | 0 .../movie/MovieBigPictureComponent.vue | 1 + .../components/movie/VoteButtonComponent.vue | 37 +++++++ client/src/components/movie/VoteComponent.vue | 99 +++++++++++++++++++ client/src/views/HomeView.vue | 60 ++--------- client/src/views/ProfileView.vue | 2 +- 8 files changed, 168 insertions(+), 60 deletions(-) rename client/src/components/form/{FormVal.Component.vue => FormValComponent.vue} (100%) create mode 100644 client/src/components/movie/VoteButtonComponent.vue create mode 100644 client/src/components/movie/VoteComponent.vue diff --git a/client/src/components/WatchlistComponent.vue b/client/src/components/WatchlistComponent.vue index f48ca04..91ed303 100644 --- a/client/src/components/WatchlistComponent.vue +++ b/client/src/components/WatchlistComponent.vue @@ -1,10 +1,17 @@ + + \ No newline at end of file diff --git a/client/src/components/movie/VoteComponent.vue b/client/src/components/movie/VoteComponent.vue new file mode 100644 index 0000000..d073f41 --- /dev/null +++ b/client/src/components/movie/VoteComponent.vue @@ -0,0 +1,99 @@ + + + + + \ No newline at end of file diff --git a/client/src/views/HomeView.vue b/client/src/views/HomeView.vue index 5806633..ed5795c 100644 --- a/client/src/views/HomeView.vue +++ b/client/src/views/HomeView.vue @@ -26,24 +26,8 @@ {{ movie.proposer }} {{ (new Date(movie.created_at)).toLocaleDateString() }} -
-
{{ movie.votes }}
-
- - - -
-
+ @@ -110,10 +94,11 @@ import MovieSearchComponent from "@/components/movie/MovieSearchComponent.vue"; import MovieBigPictureComponent from "@/components/movie/MovieBigPictureComponent.vue"; import type { MovieExtType } from "@/types/movie.types/movie_ext.type" import type { JwtUser } from "@/types/user.types/user_jwt.type"; -import FormVal from "@/components/form/FormVal.Component.vue"; +import FormVal from "@/components/form/FormValComponent.vue"; +import VoteButtonComponent from "@/components/movie/VoteButtonComponent.vue"; +import VoteComponent from "@/components/movie/VoteComponent.vue"; const movies = ref([] as MovieExtType[]); -const votes = ref([] as string[]); const user_id = ref(-1); const search_movies = ref([] as any[]); @@ -127,11 +112,12 @@ export default defineComponent({ big_picture_title: ref(""), movie_add_with_imdb_id: ref(false), movies, - votes, user_id }; }, components: { + VoteComponent, + VoteButtonComponent, FormVal, MovieBigPictureComponent, TableComponent, @@ -148,10 +134,6 @@ export default defineComponent({ }); if (store.logged_in) { - call("api/vote") - .then((data: string[]) => { - votes.value = data; - }); call("api/user/id") .then((data: JwtUser) => { user_id.value = data.id; @@ -202,34 +184,6 @@ export default defineComponent({ } }); }, - vote(imdb_id: string, votes: string[]) { - call("api/vote/" + imdb_id, "POST") - .then((data) => { - if (!data.hasOwnProperty("statusCode")) { - const vote_td = document.getElementById("table_movie_votes_td_" + imdb_id) as HTMLTableCellElement; - const vote_div = document.getElementById("table_movie_votes_" + imdb_id) as HTMLDivElement; - const new_vote_number = String(Number(vote_div.innerHTML) + 1); - vote_div.innerHTML = new_vote_number - vote_td.title = new_vote_number - votes.push(imdb_id); - } - }); - }, - unvote(imdb_id: string, votes: string[]) { - call("api/vote/" + imdb_id, "DELETE") - .then((data) => { - if (!data.hasOwnProperty("statusCode")) { - const vote_td = document.getElementById("table_movie_votes_td_" + imdb_id) as HTMLTableCellElement; - const vote_div = document.getElementById("table_movie_votes_" + imdb_id) as HTMLDivElement; - const new_vote_number = String(Number(vote_div.innerHTML) - 1); - vote_div.innerHTML = new_vote_number - vote_td.title = new_vote_number - - const slice_index = votes.indexOf(imdb_id); - delete votes[slice_index]; - } - }); - }, get_movies_all() { call("api/movie/all") .then((data: MovieExtType[]) => { diff --git a/client/src/views/ProfileView.vue b/client/src/views/ProfileView.vue index 8b1af76..a95430e 100644 --- a/client/src/views/ProfileView.vue +++ b/client/src/views/ProfileView.vue @@ -91,7 +91,7 @@ import { defineComponent, ref } from "vue"; import router from "@/router/router"; import CardComponent from "@/components/CardComponent.vue"; import type { UserSlimType } from "@/types/user.types/user_slim.type"; -import FormVal from "@/components/form/FormVal.Component.vue"; +import FormVal from "@/components/form/FormValComponent.vue"; const user = ref({} as UserSlimType) export default defineComponent({ From 89e1a88c0748a7c99c824e3a7b12902c3ff7c9f8 Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Tue, 21 Feb 2023 18:06:03 +0100 Subject: [PATCH 18/38] client: fix vote sorting bug --- client/src/components/movie/VoteComponent.vue | 8 +++++++- client/src/views/HomeView.vue | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/client/src/components/movie/VoteComponent.vue b/client/src/components/movie/VoteComponent.vue index d073f41..51b31af 100644 --- a/client/src/components/movie/VoteComponent.vue +++ b/client/src/components/movie/VoteComponent.vue @@ -63,7 +63,11 @@ export default defineComponent({ delete_media: { type: Function, default: () => {} - } + }, + on_vote: { + type: Function, + default: () => {} + }, }, methods: { vote(imdb_id: string) { @@ -74,6 +78,7 @@ export default defineComponent({ movie_votes.value[imdb_id]++; vote_td.title = String(movie_votes.value[imdb_id]) voted_movies.value.push(imdb_id); + this.on_vote(movie_votes.value[imdb_id]) } }); }, @@ -87,6 +92,7 @@ export default defineComponent({ const slice_index = voted_movies.value.indexOf(imdb_id); delete voted_movies.value[slice_index]; + this.on_vote(movie_votes.value[imdb_id]) } }); }, diff --git a/client/src/views/HomeView.vue b/client/src/views/HomeView.vue index ed5795c..a7334fd 100644 --- a/client/src/views/HomeView.vue +++ b/client/src/views/HomeView.vue @@ -27,7 +27,7 @@ {{ (new Date(movie.created_at)).toLocaleDateString() }} + :proposed="movie.proposer_id === user_id" show_votes :on_vote="(new_votes: number) => movie.votes = new_votes" /> From 4012e254d9cf9d766752ca1fea286eb055d042cd Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Tue, 21 Feb 2023 19:38:17 +0100 Subject: [PATCH 19/38] client: make movie add without page reload --- client/src/components/TableComponent.vue | 18 +++++++------ .../movie/MovieBigPictureComponent.vue | 1 - client/src/views/HomeView.vue | 26 +++++++++++-------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/client/src/components/TableComponent.vue b/client/src/components/TableComponent.vue index e5ac68d..71bc9c8 100644 --- a/client/src/components/TableComponent.vue +++ b/client/src/components/TableComponent.vue @@ -63,7 +63,8 @@ export default defineComponent({ } as any, i: 0, filter_values: this.get_filter_cookie(), - first_update: false + first_update: false, + loop_update: true }; }, setup(props) { @@ -72,18 +73,14 @@ export default defineComponent({ }; }, updated() { - if (!this.first_update) { + if (this.loop_update) { if (this.filterable) { - for (let i = 0; i < this.filter_values.length; i++) { - this.filter(this.id, i, this.filter_values[i]); - } - this.first_update = true; + this.filter_all() } - if (this.sortable && this.sort_default!.length) { this.sort(this.sort_default[0] as any, this.sort_default[1] as any); - } + if (this.first_update) this.loop_update = false; } }, props: { @@ -151,6 +148,11 @@ export default defineComponent({ this.filter_values[cell_index] = set_visible; this.set_filter_cookie(this.filter_values); }, + filter_all() { + for (let i = 0; i < this.filter_values.length; i++) { + this.filter(this.id, i, this.filter_values[i]); + } + }, get_filter_cookie() : boolean[] { const filter_cookie = get_cookie("table_filter_" + this.id) if (filter_cookie) { diff --git a/client/src/components/movie/MovieBigPictureComponent.vue b/client/src/components/movie/MovieBigPictureComponent.vue index f4aeb27..5baa6ef 100644 --- a/client/src/components/movie/MovieBigPictureComponent.vue +++ b/client/src/components/movie/MovieBigPictureComponent.vue @@ -56,7 +56,6 @@ export default defineComponent({ }, methods: { load_movie(imdb_id: string) { - console.log(imdb_id) this.loading = true; call("/api/movie/" + imdb_id) .then((data) => { diff --git a/client/src/views/HomeView.vue b/client/src/views/HomeView.vue index a7334fd..83782e3 100644 --- a/client/src/views/HomeView.vue +++ b/client/src/views/HomeView.vue @@ -6,7 +6,7 @@ :disabled="!store.logged_in">{{ $t("movie.modal.title") }} + + id="table_movie" ref="filter" sortable :sort_default="[12, 'desc']" filterable :filter_default="[true, true, true, true, false, false, true, false, false, false, true, false, true]"> - + {{ movie.year }} {{ movie.genre }} {{ movie.director }} @@ -70,7 +70,8 @@
@@ -84,7 +85,6 @@ import { ref, defineComponent } from "vue"; import { store } from "@/util/store"; import { call } from "@/util/api"; -import router from "@/router/router"; import WatchlistComponent from "@/components/WatchlistComponent.vue"; import ModalComponent from "@/components/ModalComponent.vue"; import FormComponent from "@/components/form/FormComponent.vue"; @@ -165,13 +165,12 @@ export default defineComponent({ call(form_html.action + imdb_id, "POST") .then((data) => { - if (data.hasOwnProperty("statusCode")) { - form_html.setAttribute("data-bs-dismiss", "modal"); - form_html.click(); - form_html.removeAttribute("data-bs-dismiss"); - } else { - router.go(0); + if (!data.hasOwnProperty("statusCode")) { + this.get_movies_all() } + form_html.setAttribute("data-bs-dismiss", "modal"); + form_html.click(); + form_html.removeAttribute("data-bs-dismiss"); }); }, delete_media(imdb_id: string) { @@ -187,7 +186,12 @@ export default defineComponent({ get_movies_all() { call("api/movie/all") .then((data: MovieExtType[]) => { - movies.value = data; + const child = this.$refs.filter as any + child.loop_update = true + movies.value = data + setTimeout(() => { + child.loop_update = false + }, 5000); }); } } From 7dc176bc87d735c0a3904556a3de11f3fbb3958d Mon Sep 17 00:00:00 2001 From: EliasSchaut Date: Tue, 21 Feb 2023 23:34:08 +0100 Subject: [PATCH 20/38] client: implement search --- .../components/movie/MovieSearchComponent.vue | 13 ++++------- .../movie/MovieSearchElementComponent.vue | 22 ++++++++++++++----- client/src/views/HomeView.vue | 10 ++++++++- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/client/src/components/movie/MovieSearchComponent.vue b/client/src/components/movie/MovieSearchComponent.vue index c66e862..a312563 100644 --- a/client/src/components/movie/MovieSearchComponent.vue +++ b/client/src/components/movie/MovieSearchComponent.vue @@ -1,8 +1,9 @@ @@ -20,12 +21,6 @@ export default defineComponent({ type: Array as () => MovieSearchType[], default: [] } - }, - methods: { - save_movie(imdb_id: string) { - const input = document.getElementById("from_imdb_id") as HTMLInputElement - input.value = imdb_id - } } }); diff --git a/client/src/components/movie/MovieSearchElementComponent.vue b/client/src/components/movie/MovieSearchElementComponent.vue index a4caa8b..c4f6e75 100644 --- a/client/src/components/movie/MovieSearchElementComponent.vue +++ b/client/src/components/movie/MovieSearchElementComponent.vue @@ -1,17 +1,29 @@