From 2a949793be99002ebe66507feed0620fbc10b556 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Mon, 12 Aug 2024 10:50:49 +0200 Subject: [PATCH 01/11] Update packages --- coverage/badge-branches.svg | 2 +- coverage/badge-functions.svg | 2 +- coverage/badge-lines.svg | 2 +- coverage/badge-statements.svg | 2 +- coverage/coverage-summary.json | 4 +- coverage/lcov-report/controllers/bot.ts.html | 41 +- .../lcov-report/controllers/checkers.ts.html | 2 +- .../lcov-report/controllers/helpers.ts.html | 2 +- coverage/lcov-report/controllers/index.html | 28 +- .../lcov-report/dbController/database.ts.html | 4 +- coverage/lcov-report/dbController/index.html | 2 +- .../lcov-report/dbController/index.ts.html | 2 +- .../errorHandler/CheckError.ts.html | 2 +- .../errorHandler/handleCheckErrors.ts.html | 8 +- coverage/lcov-report/errorHandler/index.html | 2 +- .../lcov-report/errorHandler/index.ts.html | 2 +- coverage/lcov-report/index.html | 28 +- coverage/lcov-report/models/index.html | 2 +- coverage/lcov-report/models/index.ts.html | 2 +- coverage/lcov-report/models/movies/index.html | 2 +- .../lcov-report/models/movies/index.ts.html | 2 +- .../lcov-report/models/movies/model.ts.html | 12 +- coverage/lcov.info | 224 +- package-lock.json | 2569 +++++++++++------ package.json | 26 +- src/helpers/index.ts | 1 + src/helpers/log.ts | 7 + src/models/movies/model.ts | 8 +- src/start.ts | 5 + 29 files changed, 1866 insertions(+), 1129 deletions(-) create mode 100644 src/helpers/index.ts create mode 100644 src/helpers/log.ts diff --git a/coverage/badge-branches.svg b/coverage/badge-branches.svg index 8577e9e..acc8a61 100644 --- a/coverage/badge-branches.svg +++ b/coverage/badge-branches.svg @@ -1 +1 @@ -Coverage: 81.39%Coverage81.39% \ No newline at end of file +Coverage:branches: 81.81%Coverage:branches81.81% \ No newline at end of file diff --git a/coverage/badge-functions.svg b/coverage/badge-functions.svg index 5bb55be..330a44e 100644 --- a/coverage/badge-functions.svg +++ b/coverage/badge-functions.svg @@ -1 +1 @@ -Coverage: 100%Coverage100% \ No newline at end of file +Coverage:functions: 100%Coverage:functions100% \ No newline at end of file diff --git a/coverage/badge-lines.svg b/coverage/badge-lines.svg index 0f6e375..e6ee932 100644 --- a/coverage/badge-lines.svg +++ b/coverage/badge-lines.svg @@ -1 +1 @@ -Coverage: 98.47%Coverage98.47% \ No newline at end of file +Coverage:lines: 98.51%Coverage:lines98.51% \ No newline at end of file diff --git a/coverage/badge-statements.svg b/coverage/badge-statements.svg index 20b86f3..4363d89 100644 --- a/coverage/badge-statements.svg +++ b/coverage/badge-statements.svg @@ -1 +1 @@ -Coverage: 98.61%Coverage98.61% \ No newline at end of file +Coverage:statements: 98.64%Coverage:statements98.64% \ No newline at end of file diff --git a/coverage/coverage-summary.json b/coverage/coverage-summary.json index 86b55bb..a7540c1 100644 --- a/coverage/coverage-summary.json +++ b/coverage/coverage-summary.json @@ -1,5 +1,5 @@ -{"total": {"lines":{"total":197,"covered":194,"skipped":0,"pct":98.47},"statements":{"total":217,"covered":214,"skipped":0,"pct":98.61},"functions":{"total":67,"covered":67,"skipped":0,"pct":100},"branches":{"total":43,"covered":35,"skipped":0,"pct":81.39},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/controllers/bot.ts": {"lines":{"total":80,"covered":77,"skipped":0,"pct":96.25},"functions":{"total":31,"covered":31,"skipped":0,"pct":100},"statements":{"total":90,"covered":87,"skipped":0,"pct":96.66},"branches":{"total":13,"covered":9,"skipped":0,"pct":69.23}} +{"total": {"lines":{"total":202,"covered":199,"skipped":0,"pct":98.51},"statements":{"total":221,"covered":218,"skipped":0,"pct":98.64},"functions":{"total":67,"covered":67,"skipped":0,"pct":100},"branches":{"total":44,"covered":36,"skipped":0,"pct":81.81},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/gpont/Documents/watch_together/src/controllers/bot.ts": {"lines":{"total":85,"covered":82,"skipped":0,"pct":96.47},"functions":{"total":31,"covered":31,"skipped":0,"pct":100},"statements":{"total":94,"covered":91,"skipped":0,"pct":96.8},"branches":{"total":14,"covered":10,"skipped":0,"pct":71.42}} ,"/Users/gpont/Documents/watch_together/src/controllers/checkers.ts": {"lines":{"total":36,"covered":36,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":41,"covered":41,"skipped":0,"pct":100},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} ,"/Users/gpont/Documents/watch_together/src/controllers/helpers.ts": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/gpont/Documents/watch_together/src/dbController/database.ts": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} diff --git a/coverage/lcov-report/controllers/bot.ts.html b/coverage/lcov-report/controllers/bot.ts.html index 675051e..04c7625 100644 --- a/coverage/lcov-report/controllers/bot.ts.html +++ b/coverage/lcov-report/controllers/bot.ts.html @@ -23,16 +23,16 @@

All files / controllers
- 96.66% + 96.8% Statements - 87/90 + 91/94
- 69.23% + 71.42% Branches - 9/13 + 10/14
@@ -44,9 +44,9 @@

All files / controllers
- 96.25% + 96.47% Lines - 77/80 + 82/85
@@ -256,7 +256,12 @@

All files / controllers 191 192 193 -194  +194 +195 +196 +197 +198 +199      1x @@ -314,8 +319,13 @@

All files / controllers       +2x +2x +2x +2x 1x 1x +  1x 1x   @@ -437,11 +447,11 @@

All files / controllers   3x 2x -  1x     1x +1x       @@ -509,6 +519,11 @@

All files / controllers /\/create_group/, (bot) => async (msg) => { const chatId = msg.chat.id; + const group = await findGroupByCode(String(chatId)); + if (group) { + bot.sendMessage(chatId, texts.group_already_created + group.code); + return; + } await createGroup(String(chatId)); bot.sendMessage(chatId, `${texts.group_created} ${chatId}`); }, @@ -629,11 +644,11 @@

All files / controllers const chatId = msg.chat.id;   const group = await checkAndGetGroup(msg); - const movies = await checkAndGetMoviesList(group.id); + const movies = (await checkAndGetMoviesList(group.id)).filter( + (movie) => !movie.is_vetoed, + );   - const movie = movies.filter((movie) => !movie.is_vetoed)[ - Math.floor(Math.random() * movies.length) - ]; + const movie = movies[Math.floor(Math.random() * movies.length)]; bot.sendMessage(chatId, getMovieDescription(movie), MSG_OPTIONS); }, ], @@ -649,7 +664,7 @@

All files / controllers + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/helpers/index.ts.html b/coverage/lcov-report/helpers/index.ts.html new file mode 100644 index 0000000..14bb4af --- /dev/null +++ b/coverage/lcov-report/helpers/index.ts.html @@ -0,0 +1,88 @@ + + + + + + Code coverage report for helpers/index.ts + + + + + + + + + +
+
+

All files / helpers index.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +22x + 
export * from './log';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/helpers/log.ts.html b/coverage/lcov-report/helpers/log.ts.html new file mode 100644 index 0000000..702834a --- /dev/null +++ b/coverage/lcov-report/helpers/log.ts.html @@ -0,0 +1,106 @@ + + + + + + Code coverage report for helpers/log.ts + + + + + + + + + +
+
+

All files / helpers log.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 1/1 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +84x +  +2x +4x +4x +  +  + 
export const green = (message: string) => `\x1b[32m${message}\x1b[0m`;
+ 
+export const log = (message: string) => {
+  if (process.env.DEBUG_OUTPUT) {
+    console.log(green(`[DEBUG]: ${message}`));
+  }
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html index 2cf6746..ca7e5ea 100644 --- a/coverage/lcov-report/index.html +++ b/coverage/lcov-report/index.html @@ -23,30 +23,30 @@

All files

- 98.64% + 99.22% Statements - 218/221 + 255/257
- 81.81% + 82.45% Branches - 36/44 + 47/57
100% Functions - 67/67 + 76/76
- 98.51% + 99.11% Lines - 199/202 + 224/226
@@ -79,18 +79,18 @@

All files

- controllers - -
+ controllers + +
- 97.93% - 142/145 + 99.29% + 140/141 83.33% - 25/30 + 30/36 100% 43/43 - 97.65% - 125/128 + 99.18% + 122/123 @@ -109,7 +109,37 @@

All files

- errorHandler + helpers + +
+ + 100% + 8/8 + 100% + 1/1 + 100% + 2/2 + 100% + 5/5 + + + + middlewares + +
+ + 100% + 10/10 + 100% + 0/0 + 100% + 3/3 + 100% + 8/8 + + + + middlewares/errorHandler
@@ -120,7 +150,22 @@

All files

100% 5/5 100% - 15/15 + 13/13 + + + + middlewares/logger + +
+ + 100% + 11/11 + 100% + 5/5 + 100% + 4/4 + 100% + 7/7 @@ -129,28 +174,58 @@

All files

100% - 1/1 + 3/3 100% 0/0 100% 0/0 100% - 1/1 + 3/3 + + + + models/group + +
+ + 100% + 13/13 + 100% + 0/0 + 100% + 3/3 + 100% + 13/13 + + + + models/movie + +
+ + 97.22% + 35/36 + 69.23% + 9/13 + 100% + 12/12 + 97.14% + 34/35 - models/movies + models/user
100% - 50/50 - 75% - 9/12 + 10/10 100% - 17/17 + 0/0 + 100% + 2/2 100% - 49/49 + 10/10 @@ -161,7 +236,7 @@

All files

+ + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/controllers.types.ts.html b/coverage/lcov-report/middlewares/controllers.types.ts.html new file mode 100644 index 0000000..2c0c421 --- /dev/null +++ b/coverage/lcov-report/middlewares/controllers.types.ts.html @@ -0,0 +1,124 @@ + + + + + + Code coverage report for middlewares/controllers.types.ts + + + + + + + + + +
+
+

All files / middlewares controllers.types.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14  +  +  +1x +  +  +  +  +  +  +  +  +  + 
// Fix for error: node-telegram-bot-api
+// deprecated Automatic enabling of cancellation
+// of promises is deprecated In the future
+process.env.NTBA_FIX_319 = '1';
+import TelegramBot from 'node-telegram-bot-api';
+ 
+export type THandler = (
+  bot: TelegramBot,
+) => (msg: TelegramBot.Message, match: string[] | null) => Promise<void>;
+ 
+export type TRule = [RegExp, THandler];
+ 
+export type TMiddleware = (handler: THandler) => THandler;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/CheckError.ts.html b/coverage/lcov-report/middlewares/errorHandler/CheckError.ts.html new file mode 100644 index 0000000..a364071 --- /dev/null +++ b/coverage/lcov-report/middlewares/errorHandler/CheckError.ts.html @@ -0,0 +1,109 @@ + + + + + + Code coverage report for middlewares/errorHandler/CheckError.ts + + + + + + + + + +
+
+

All files / middlewares/errorHandler CheckError.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +92x +  +15x +  +  +15x +  +  + 
export class CheckError extends Error {
+  constructor(msg: string) {
+    super(msg);
+ 
+    // Set the prototype explicitly.
+    Object.setPrototypeOf(this, CheckError.prototype);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/handleCheckErrors.ts.html b/coverage/lcov-report/middlewares/errorHandler/handleCheckErrors.ts.html new file mode 100644 index 0000000..fd688a0 --- /dev/null +++ b/coverage/lcov-report/middlewares/errorHandler/handleCheckErrors.ts.html @@ -0,0 +1,130 @@ + + + + + + Code coverage report for middlewares/errorHandler/handleCheckErrors.ts + + + + + + + + + +
+
+

All files / middlewares/errorHandler handleCheckErrors.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16  +2x +  +2x +31x +31x +31x +  +16x +15x +  +1x +  +  +  + 
import { TMiddleware } from '../controllers.types';
+import { CheckError } from './CheckError';
+ 
+export const handleCheckErrors: TMiddleware =
+  (handler) => (bot) => async (msg, match) => {
+    try {
+      await handler(bot)(msg, match);
+    } catch (error) {
+      if (error instanceof CheckError) {
+        bot.sendMessage(msg.chat.id, error.message);
+      } else {
+        throw error;
+      }
+    }
+  };
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/index.html b/coverage/lcov-report/middlewares/errorHandler/index.html new file mode 100644 index 0000000..fdc4405 --- /dev/null +++ b/coverage/lcov-report/middlewares/errorHandler/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for middlewares/errorHandler + + + + + + + + + +
+
+

All files middlewares/errorHandler

+
+ +
+ 100% + Statements + 16/16 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 100% + Lines + 13/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
CheckError.ts +
+
100%3/3100%0/0100%1/1100%3/3
handleCheckErrors.ts +
+
100%11/11100%2/2100%4/4100%8/8
index.ts +
+
100%2/2100%0/0100%0/0100%2/2
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/index.ts.html b/coverage/lcov-report/middlewares/errorHandler/index.ts.html new file mode 100644 index 0000000..a689fe7 --- /dev/null +++ b/coverage/lcov-report/middlewares/errorHandler/index.ts.html @@ -0,0 +1,91 @@ + + + + + + Code coverage report for middlewares/errorHandler/index.ts + + + + + + + + + +
+
+

All files / middlewares/errorHandler index.ts

+
+ +
+ 100% + Statements + 2/2 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 2/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +31x +1x + 
export * from './CheckError';
+export * from './handleCheckErrors';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/index.html b/coverage/lcov-report/middlewares/index.html new file mode 100644 index 0000000..b629705 --- /dev/null +++ b/coverage/lcov-report/middlewares/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for middlewares + + + + + + + + + +
+
+

All files middlewares

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
applyMiddlewares.ts +
+
100%5/5100%0/0100%3/3100%3/3
controllers.types.ts +
+
100%1/1100%0/0100%0/0100%1/1
index.ts +
+
100%4/4100%0/0100%0/0100%4/4
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/index.ts.html b/coverage/lcov-report/middlewares/index.ts.html new file mode 100644 index 0000000..7b9b0e3 --- /dev/null +++ b/coverage/lcov-report/middlewares/index.ts.html @@ -0,0 +1,97 @@ + + + + + + Code coverage report for middlewares/index.ts + + + + + + + + + +
+
+

All files / middlewares index.ts

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +51x +1x +1x +1x + 
export * from './errorHandler';
+export * from './logger';
+export * from './applyMiddlewares';
+export * from './controllers.types';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/logger/index.html b/coverage/lcov-report/middlewares/logger/index.html new file mode 100644 index 0000000..3e95d66 --- /dev/null +++ b/coverage/lcov-report/middlewares/logger/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for middlewares/logger + + + + + + + + + +
+
+

All files middlewares/logger

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 5/5 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%1/1100%0/0100%0/0100%1/1
logger.ts +
+
100%10/10100%5/5100%4/4100%6/6
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/logger/index.ts.html b/coverage/lcov-report/middlewares/logger/index.ts.html new file mode 100644 index 0000000..38bc782 --- /dev/null +++ b/coverage/lcov-report/middlewares/logger/index.ts.html @@ -0,0 +1,88 @@ + + + + + + Code coverage report for middlewares/logger/index.ts + + + + + + + + + +
+
+

All files / middlewares/logger index.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +21x + 
export * from './logger';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/logger/logger.ts.html b/coverage/lcov-report/middlewares/logger/logger.ts.html new file mode 100644 index 0000000..86cb587 --- /dev/null +++ b/coverage/lcov-report/middlewares/logger/logger.ts.html @@ -0,0 +1,118 @@ + + + + + + Code coverage report for middlewares/logger/logger.ts + + + + + + + + + +
+
+

All files / middlewares/logger logger.ts

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 5/5 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +122x +  +  +30x +30x +2x +2x +  +  +30x +  + 
import { log } from '../../helpers';
+import { TMiddleware } from '../controllers.types';
+ 
+export const logger: TMiddleware = (handler) => (bot) => async (msg, match) => {
+  if (process.env.DEBUG_OUTPUT === '1') {
+    log(`User: ${msg.from?.username}, Message: ${msg.text}`);
+    log(`DB(Movies): `);
+  }
+ 
+  await handler(bot)(msg, match);
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/group/index.html b/coverage/lcov-report/models/group/index.html new file mode 100644 index 0000000..98fcbeb --- /dev/null +++ b/coverage/lcov-report/models/group/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for models/group + + + + + + + + + +
+
+

All files models/group

+
+ +
+ 100% + Statements + 13/13 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 13/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%2/2100%0/0100%0/0100%2/2
model.ts +
+
100%11/11100%0/0100%3/3100%11/11
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/group/index.ts.html b/coverage/lcov-report/models/group/index.ts.html new file mode 100644 index 0000000..bd240df --- /dev/null +++ b/coverage/lcov-report/models/group/index.ts.html @@ -0,0 +1,91 @@ + + + + + + Code coverage report for models/group/index.ts + + + + + + + + + +
+
+

All files / models/group index.ts

+
+ +
+ 100% + Statements + 2/2 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 2/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +31x +1x + 
export * from './model';
+export * from './types';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/group/model.ts.html b/coverage/lcov-report/models/group/model.ts.html new file mode 100644 index 0000000..2484034 --- /dev/null +++ b/coverage/lcov-report/models/group/model.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for models/group/model.ts + + + + + + + + + +
+
+

All files / models/group model.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +281x +  +  +  +1x +16x +16x +16x +  +  +  +  +  +1x +  +  +20x +20x +  +  +1x +15x +15x +  +  +  +  + 
import { openDb } from '../../dbController';
+import { TId } from '../types';
+import { IGroup } from './types';
+ 
+export async function createGroup(code: string): Promise<IGroup> {
+  const db = await openDb();
+  const res = await db.run(`INSERT INTO groups (code) VALUES (?)`, [code]);
+  return {
+    id: res.lastID,
+    code,
+  } as IGroup;
+}
+ 
+export async function findGroupByCode(
+  code: string,
+): Promise<IGroup | undefined> {
+  const db = await openDb();
+  return db.get(`SELECT * FROM groups WHERE code = ?`, [code]);
+}
+ 
+export async function addUserToGroup(groupId: TId, userId: TId) {
+  const db = await openDb();
+  await db.run(`INSERT INTO group_users (group_id, user_id) VALUES (?, ?)`, [
+    groupId,
+    userId,
+  ]);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/index.html b/coverage/lcov-report/models/index.html index 3845b46..fc6a32e 100644 --- a/coverage/lcov-report/models/index.html +++ b/coverage/lcov-report/models/index.html @@ -25,7 +25,7 @@

All files models

100% Statements - 1/1 + 3/3
@@ -46,7 +46,7 @@

All files models

100% Lines - 1/1 + 3/3
@@ -84,13 +84,13 @@

All files models

100% - 1/1 + 3/3 100% 0/0 100% 0/0 100% - 1/1 + 3/3 @@ -101,7 +101,7 @@

All files models

+ + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/movie/index.ts.html b/coverage/lcov-report/models/movie/index.ts.html new file mode 100644 index 0000000..c835a1e --- /dev/null +++ b/coverage/lcov-report/models/movie/index.ts.html @@ -0,0 +1,91 @@ + + + + + + Code coverage report for models/movie/index.ts + + + + + + + + + +
+
+

All files / models/movie index.ts

+
+ +
+ 100% + Statements + 2/2 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 2/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +31x +1x + 
export * from './model';
+export * from './types';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/movie/model.ts.html b/coverage/lcov-report/models/movie/model.ts.html new file mode 100644 index 0000000..be77a20 --- /dev/null +++ b/coverage/lcov-report/models/movie/model.ts.html @@ -0,0 +1,397 @@ + + + + + + Code coverage report for models/movie/model.ts + + + + + + + + + +
+
+

All files / models/movie model.ts

+
+ +
+ 97.05% + Statements + 33/34 +
+ + +
+ 69.23% + Branches + 9/13 +
+ + +
+ 100% + Functions + 12/12 +
+ + +
+ 96.96% + Lines + 32/33 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +1051x +  +  +  +1x +  +  +  +  +  +  +7x +7x +  +  +  +  +7x +  +  +7x +  +  +  +  +  +  +  +  +7x +  +  +  +18x +18x +  +  +  +18x +  +  +1x +  +  +  +3x +3x +  +  +  +3x +  +  +  +  +  +22x +  +  +1x +  +  +  +19x +19x +  +  +  +  +  +  +  +1x +2x +2x +  +  +  +  +  +1x +5x +5x +  +  +5x +  +  +5x +  +  +  +1x +1x +1x +  +  +  +  +  +1x +1x +1x +  + 
import { openDb } from '../../dbController';
+import { TId } from '../types';
+import { IMovie } from './types';
+ 
+export async function suggestMovie(
+  name: string,
+  suggestedBy: number,
+  groupId: TId,
+  kinopoiskLink: string,
+  imdbLink: string,
+): Promise<IMovie> {
+  const db = await openDb();
+  const res = await db.run(
+    `INSERT INTO movies (name, suggested_by, group_id, kinopoisk_link, imdb_link) VALUES (?, ?, ?, ?, ?)`,
+    [name, suggestedBy, groupId, kinopoiskLink, imdbLink],
+  );
+  const movie =
+    res?.lastID !== undefined
+      ? await findMovieById(res.lastID, groupId)
+      : undefined;
+  Iif (!movie) {
+    throw new Error(
+      `Failed to insert movie: ${JSON.stringify({
+        name,
+        suggestedBy,
+        groupId,
+      })}`,
+    );
+  }
+  return movie;
+}
+ 
+async function calcMovieVotes(movieId: TId): Promise<number> {
+  const db = await openDb();
+  const votes = await db.all(
+    `SELECT COUNT(*) AS vote_count FROM votes WHERE movie_id = ?`,
+    [movieId],
+  );
+  return votes[0].vote_count ?? 0;
+}
+ 
+export async function hasUserMovieVote(
+  userId: TId,
+  movieId: TId,
+): Promise<boolean> {
+  const db = await openDb();
+  const res = await db.get(
+    `SELECT * FROM votes WHERE movie_id = ? AND user_id = ?`,
+    [movieId, userId],
+  );
+  return !!res;
+}
+ 
+async function mapMovie(
+  row?: Omit<IMovie, 'votes'>,
+): Promise<IMovie | undefined> {
+  return row && { ...row, votes: await calcMovieVotes(row.id) };
+}
+ 
+export async function findMovieById(
+  movieId: TId,
+  groupId: TId,
+): Promise<IMovie | undefined> {
+  const db = await openDb();
+  return db
+    .get(`SELECT * FROM movies WHERE id = ? AND group_id = ?`, [
+      movieId,
+      groupId,
+    ])
+    .then(mapMovie);
+}
+ 
+export async function voteForMovie(movieId: TId, userId: TId) {
+  const db = await openDb();
+  await db.run(`INSERT INTO votes (movie_id, user_id) VALUES (?, ?)`, [
+    movieId,
+    userId,
+  ]);
+}
+ 
+export async function listMovies(groupId: TId): Promise<IMovie[] | undefined> {
+  const db = await openDb();
+  return db
+    .all(`SELECT * FROM movies WHERE group_id = ?`, [groupId])
+    .then((rows: (Omit<IMovie, 'votes'> | undefined)[]) =>
+      Promise.all(rows.map(mapMovie)),
+    )
+    .then((movies: (IMovie | undefined)[]) =>
+      movies.filter((row): row is IMovie => !!row),
+    );
+}
+ 
+export async function markMovieAsWatched(movieId: TId, groupId: TId) {
+  const db = await openDb();
+  await db.run(`DELETE FROM movies WHERE id = ? AND group_id = ?`, [
+    movieId,
+    groupId,
+  ]);
+}
+ 
+export async function markMovieAsVetoed(movieId: TId) {
+  const db = await openDb();
+  await db.run(`UPDATE movies SET is_vetoed = 1 WHERE id = ?`, [movieId]);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/user/index.html b/coverage/lcov-report/models/user/index.html new file mode 100644 index 0000000..05b75de --- /dev/null +++ b/coverage/lcov-report/models/user/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for models/user + + + + + + + + + +
+
+

All files models/user

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%2/2100%0/0100%0/0100%2/2
model.ts +
+
100%8/8100%0/0100%2/2100%8/8
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/user/index.ts.html b/coverage/lcov-report/models/user/index.ts.html new file mode 100644 index 0000000..db3e157 --- /dev/null +++ b/coverage/lcov-report/models/user/index.ts.html @@ -0,0 +1,91 @@ + + + + + + Code coverage report for models/user/index.ts + + + + + + + + + +
+
+

All files / models/user index.ts

+
+ +
+ 100% + Statements + 2/2 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 2/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +31x +1x + 
export * from './model';
+export * from './types';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/models/user/model.ts.html b/coverage/lcov-report/models/user/model.ts.html new file mode 100644 index 0000000..ba18b50 --- /dev/null +++ b/coverage/lcov-report/models/user/model.ts.html @@ -0,0 +1,142 @@ + + + + + + Code coverage report for models/user/model.ts + + + + + + + + + +
+
+

All files / models/user model.ts

+
+ +
+ 100% + Statements + 8/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +201x +  +  +  +1x +19x +19x +  +  +  +19x +  +  +1x +  +  +9x +9x +  + 
import { openDb } from '../../dbController';
+import { TId } from '../types';
+import { IUser } from './types';
+ 
+export async function createUser(username: string): Promise<IUser | undefined> {
+  const db = await openDb();
+  const res = await db.run(
+    `INSERT OR IGNORE INTO users (username) VALUES (?)`,
+    [username],
+  );
+  return { id: res.lastID as TId, username };
+}
+ 
+export async function findUserByUsername(
+  username: string,
+): Promise<IUser | undefined> {
+  const db = await openDb();
+  return db.get(`SELECT * FROM users WHERE username = ?`, [username]);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info index 8bb0cb1..bf1e969 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -1,36 +1,36 @@ TN: SF:src/controllers/bot.ts -FN:37,(anonymous_8) -FN:37,(anonymous_9) -FN:37,(anonymous_10) -FN:53,(anonymous_11) -FN:53,(anonymous_12) -FN:59,(anonymous_13) -FN:59,(anonymous_14) -FN:59,(anonymous_15) -FN:72,(anonymous_16) -FN:72,(anonymous_17) -FN:72,(anonymous_18) -FN:88,(anonymous_19) -FN:88,(anonymous_20) -FN:88,(anonymous_21) -FN:115,(anonymous_22) -FN:115,(anonymous_23) -FN:115,(anonymous_24) -FN:137,(anonymous_25) -FN:137,(anonymous_26) -FN:137,(anonymous_27) -FN:150,(anonymous_28) -FN:150,(anonymous_29) -FN:150,(anonymous_30) -FN:166,(anonymous_31) -FN:166,(anonymous_32) -FN:166,(anonymous_33) -FN:182,(anonymous_34) -FN:182,(anonymous_35) -FN:182,(anonymous_36) -FN:187,(anonymous_37) -FN:197,(anonymous_38) +FN:43,(anonymous_8) +FN:43,(anonymous_9) +FN:43,(anonymous_10) +FN:56,(anonymous_11) +FN:56,(anonymous_12) +FN:56,(anonymous_13) +FN:62,(anonymous_14) +FN:62,(anonymous_15) +FN:62,(anonymous_16) +FN:75,(anonymous_17) +FN:75,(anonymous_18) +FN:75,(anonymous_19) +FN:91,(anonymous_20) +FN:91,(anonymous_21) +FN:91,(anonymous_22) +FN:114,(anonymous_23) +FN:114,(anonymous_24) +FN:114,(anonymous_25) +FN:136,(anonymous_26) +FN:136,(anonymous_27) +FN:136,(anonymous_28) +FN:149,(anonymous_29) +FN:149,(anonymous_30) +FN:149,(anonymous_31) +FN:165,(anonymous_32) +FN:165,(anonymous_33) +FN:165,(anonymous_34) +FN:181,(anonymous_35) +FN:181,(anonymous_36) +FN:181,(anonymous_37) +FN:186,(anonymous_38) FNF:31 FNH:31 FNDA:1,(anonymous_8) @@ -38,135 +38,136 @@ FNDA:1,(anonymous_9) FNDA:1,(anonymous_10) FNDA:1,(anonymous_11) FNDA:1,(anonymous_12) -FNDA:2,(anonymous_13) +FNDA:1,(anonymous_13) FNDA:2,(anonymous_14) FNDA:2,(anonymous_15) -FNDA:4,(anonymous_16) +FNDA:2,(anonymous_16) FNDA:4,(anonymous_17) FNDA:4,(anonymous_18) -FNDA:3,(anonymous_19) +FNDA:4,(anonymous_19) FNDA:3,(anonymous_20) FNDA:3,(anonymous_21) -FNDA:5,(anonymous_22) +FNDA:3,(anonymous_22) FNDA:5,(anonymous_23) FNDA:5,(anonymous_24) -FNDA:2,(anonymous_25) +FNDA:5,(anonymous_25) FNDA:2,(anonymous_26) FNDA:2,(anonymous_27) -FNDA:4,(anonymous_28) +FNDA:2,(anonymous_28) FNDA:4,(anonymous_29) FNDA:4,(anonymous_30) -FNDA:3,(anonymous_31) +FNDA:4,(anonymous_31) FNDA:3,(anonymous_32) FNDA:3,(anonymous_33) FNDA:3,(anonymous_34) FNDA:3,(anonymous_35) FNDA:3,(anonymous_36) -FNDA:1,(anonymous_37) -FNDA:10,(anonymous_38) +FNDA:3,(anonymous_37) +FNDA:1,(anonymous_38) DA:4,1 DA:6,1 -DA:17,1 DA:18,1 DA:19,1 -DA:21,1 -DA:29,1 -DA:34,1 -DA:37,1 -DA:38,1 -DA:39,1 -DA:41,1 -DA:42,1 -DA:44,0 +DA:20,1 +DA:27,1 +DA:35,1 +DA:40,1 +DA:43,1 +DA:44,1 +DA:46,1 +DA:47,1 DA:48,1 -DA:53,1 -DA:54,1 -DA:59,2 -DA:60,2 -DA:61,2 +DA:51,1 +DA:56,1 +DA:57,1 DA:62,2 -DA:63,1 -DA:64,1 +DA:63,2 +DA:64,2 +DA:65,2 DA:66,1 DA:67,1 -DA:72,4 -DA:73,4 -DA:74,4 -DA:75,3 -DA:77,2 -DA:78,2 -DA:79,1 -DA:80,1 +DA:69,1 +DA:70,1 +DA:75,4 +DA:76,4 +DA:77,4 +DA:78,3 +DA:80,2 +DA:81,2 DA:82,1 DA:83,1 -DA:88,3 -DA:89,3 -DA:90,3 -DA:92,2 -DA:93,1 -DA:95,1 -DA:102,1 -DA:103,0 -DA:104,0 -DA:106,1 +DA:85,1 +DA:86,1 +DA:91,3 +DA:92,3 +DA:93,3 +DA:95,2 +DA:96,1 +DA:98,1 +DA:105,1 +DA:114,5 DA:115,5 DA:116,5 -DA:117,5 +DA:121,4 DA:122,4 DA:123,4 -DA:124,4 -DA:126,3 +DA:125,3 +DA:126,1 DA:127,1 -DA:128,1 +DA:130,2 DA:131,2 -DA:132,2 +DA:136,2 DA:137,2 -DA:138,2 -DA:140,2 -DA:141,1 +DA:139,2 +DA:140,1 +DA:143,1 DA:144,1 -DA:145,1 +DA:149,4 DA:150,4 DA:151,4 -DA:152,4 -DA:157,3 -DA:158,2 +DA:156,3 +DA:157,2 +DA:159,1 DA:160,1 -DA:161,1 +DA:165,3 DA:166,3 DA:167,3 -DA:168,3 +DA:172,2 DA:173,2 -DA:174,2 +DA:175,1 DA:176,1 -DA:177,1 +DA:181,3 DA:182,3 -DA:183,3 -DA:185,3 -DA:186,2 -DA:187,1 +DA:184,3 +DA:185,2 +DA:186,1 +DA:189,1 DA:190,1 -DA:191,1 -DA:196,1 -DA:197,10 -LF:85 -LH:82 -BRDA:41,0,0,1 -BRDA:41,0,1,0 -BRDA:42,1,0,1 -BRDA:42,1,1,0 -BRDA:42,2,0,1 -BRDA:42,2,1,1 -BRDA:42,3,0,0 -BRDA:42,3,1,1 -BRDA:42,4,0,1 -BRDA:42,4,1,1 -BRDA:62,5,0,1 -BRDA:78,6,0,1 -BRDA:102,7,0,0 -BRDA:126,8,0,1 -BRF:14 -BRH:10 +DA:195,1 +LF:80 +LH:80 +BRDA:44,0,0,0 +BRDA:44,0,1,1 +BRDA:44,1,0,1 +BRDA:44,1,1,1 +BRDA:46,2,0,1 +BRDA:46,2,1,0 +BRDA:46,3,0,1 +BRDA:46,3,1,1 +BRDA:47,4,0,1 +BRDA:48,5,0,1 +BRDA:48,5,1,0 +BRDA:48,6,0,1 +BRDA:48,6,1,1 +BRDA:48,7,0,0 +BRDA:48,7,1,1 +BRDA:48,8,0,1 +BRDA:48,8,1,1 +BRDA:65,9,0,1 +BRDA:81,10,0,1 +BRDA:125,11,0,1 +BRF:20 +BRH:16 end_of_record TN: SF:src/controllers/checkers.ts @@ -181,8 +182,8 @@ FN:67,(anonymous_15) FN:69,(anonymous_16) FNF:9 FNH:9 -FNDA:10,(anonymous_8) -FNDA:10,(anonymous_9) +FNDA:9,(anonymous_8) +FNDA:9,(anonymous_9) FNDA:15,(anonymous_10) FNDA:15,(anonymous_11) FNDA:19,(anonymous_12) @@ -195,13 +196,13 @@ DA:6,1 DA:7,1 DA:8,1 DA:18,1 -DA:20,10 -DA:21,10 -DA:23,10 +DA:20,9 +DA:21,9 +DA:23,9 DA:24,2 -DA:26,8 -DA:27,8 -DA:28,1 +DA:26,7 +DA:27,7 +DA:28,0 DA:30,7 DA:33,1 DA:35,15 @@ -227,13 +228,13 @@ DA:71,3 DA:72,1 DA:75,2 LF:36 -LH:36 +LH:35 BRDA:21,0,0,1 -BRDA:21,0,1,9 -BRDA:21,1,0,10 -BRDA:21,1,1,10 +BRDA:21,0,1,8 +BRDA:21,1,0,9 +BRDA:21,1,1,9 BRDA:23,2,0,2 -BRDA:27,3,0,1 +BRDA:27,3,0,0 BRDA:39,4,0,3 BRDA:49,5,0,5 BRDA:49,6,0,0 @@ -245,7 +246,7 @@ BRDA:71,9,0,1 BRDA:71,10,0,3 BRDA:71,10,1,3 BRF:16 -BRH:15 +BRH:14 end_of_record TN: SF:src/controllers/helpers.ts @@ -301,7 +302,76 @@ BRF:0 BRH:0 end_of_record TN: -SF:src/errorHandler/CheckError.ts +SF:src/helpers/index.ts +FNF:0 +FNH:0 +DA:1,2 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/helpers/log.ts +FN:1,(anonymous_0) +FN:3,(anonymous_1) +FNF:2 +FNH:2 +FNDA:4,(anonymous_0) +FNDA:4,(anonymous_1) +DA:1,4 +DA:3,2 +DA:4,4 +DA:5,4 +LF:4 +LH:4 +BRDA:4,0,0,4 +BRF:1 +BRH:1 +end_of_record +TN: +SF:src/middlewares/applyMiddlewares.ts +FN:3,(anonymous_0) +FN:7,(anonymous_1) +FN:9,(anonymous_2) +FNF:3 +FNH:3 +FNDA:1,(anonymous_0) +FNDA:10,(anonymous_1) +FNDA:20,(anonymous_2) +DA:3,1 +DA:7,10 +DA:9,20 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/middlewares/controllers.types.ts +FNF:0 +FNH:0 +DA:4,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/middlewares/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +LF:4 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/middlewares/errorHandler/CheckError.ts FN:2,(anonymous_0) FNF:1 FNH:1 @@ -315,36 +385,34 @@ BRF:0 BRH:0 end_of_record TN: -SF:src/errorHandler/handleCheckErrors.ts +SF:src/middlewares/errorHandler/handleCheckErrors.ts FN:5,(anonymous_7) -FN:6,(anonymous_8) -FN:7,(anonymous_9) -FN:7,(anonymous_10) +FN:5,(anonymous_8) +FN:5,(anonymous_9) +FN:5,(anonymous_10) FNF:4 FNH:4 -FNDA:12,(anonymous_7) -FNDA:30,(anonymous_8) -FNDA:30,(anonymous_9) -FNDA:30,(anonymous_10) +FNDA:13,(anonymous_7) +FNDA:31,(anonymous_8) +FNDA:31,(anonymous_9) +FNDA:31,(anonymous_10) DA:2,2 DA:4,2 -DA:5,2 -DA:6,12 -DA:7,30 -DA:8,30 -DA:9,30 -DA:11,15 -DA:12,14 -DA:14,1 -LF:10 -LH:10 -BRDA:11,0,0,14 -BRDA:11,0,1,1 +DA:5,31 +DA:6,31 +DA:7,31 +DA:9,16 +DA:10,15 +DA:12,1 +LF:8 +LH:8 +BRDA:9,0,0,15 +BRDA:9,0,1,1 BRF:2 BRH:2 end_of_record TN: -SF:src/errorHandler/index.ts +SF:src/middlewares/errorHandler/index.ts FNF:0 FNH:0 DA:1,1 @@ -355,7 +423,7 @@ BRF:0 BRH:0 end_of_record TN: -SF:src/models/index.ts +SF:src/middlewares/logger/index.ts FNF:0 FNH:0 DA:1,1 @@ -365,7 +433,47 @@ BRF:0 BRH:0 end_of_record TN: -SF:src/models/movies/index.ts +SF:src/middlewares/logger/logger.ts +FN:4,(anonymous_7) +FN:4,(anonymous_8) +FN:4,(anonymous_9) +FN:4,(anonymous_10) +FNF:4 +FNH:4 +FNDA:12,(anonymous_7) +FNDA:30,(anonymous_8) +FNDA:30,(anonymous_9) +FNDA:30,(anonymous_10) +DA:1,2 +DA:4,30 +DA:5,30 +DA:6,2 +DA:7,2 +DA:10,30 +LF:6 +LH:6 +BRDA:5,0,0,2 +BRDA:6,1,0,1 +BRDA:6,1,1,1 +BRDA:6,2,0,2 +BRDA:6,2,1,2 +BRF:5 +BRH:5 +end_of_record +TN: +SF:src/models/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/models/group/index.ts FNF:0 FNH:0 DA:1,1 @@ -376,30 +484,58 @@ BRF:0 BRH:0 end_of_record TN: -SF:src/models/movies/model.ts -FN:4,createGroup -FN:13,findGroupByCode -FN:20,createUser -FN:29,addUserToGroup -FN:37,suggestMovie -FN:54,calcMovieVotes -FN:63,hasUserMovieVote -FN:75,mapMovie -FN:81,findMovieById -FN:94,voteForMovie -FN:102,listMovies -FN:106,(anonymous_29) -FN:107,(anonymous_30) -FN:107,(anonymous_31) -FN:110,markMovieAsWatched -FN:118,markMovieAsVetoed -FN:123,findUserByUsername -FNF:17 -FNH:17 +SF:src/models/group/model.ts +FN:5,createGroup +FN:14,findGroupByCode +FN:21,addUserToGroup +FNF:3 +FNH:3 FNDA:16,createGroup FNDA:20,findGroupByCode -FNDA:19,createUser FNDA:15,addUserToGroup +DA:1,1 +DA:5,1 +DA:6,16 +DA:7,16 +DA:8,16 +DA:14,1 +DA:17,20 +DA:18,20 +DA:21,1 +DA:22,15 +DA:23,15 +LF:11 +LH:11 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/models/movie/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +LF:2 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/models/movie/model.ts +FN:5,suggestMovie +FN:33,calcMovieVotes +FN:42,hasUserMovieVote +FN:54,mapMovie +FN:60,findMovieById +FN:73,voteForMovie +FN:81,listMovies +FN:85,(anonymous_21) +FN:88,(anonymous_22) +FN:89,(anonymous_23) +FN:93,markMovieAsWatched +FN:101,markMovieAsVetoed +FNF:12 +FNH:12 FNDA:7,suggestMovie FNDA:18,calcMovieVotes FNDA:3,hasUserMovieVote @@ -407,73 +543,91 @@ FNDA:22,mapMovie FNDA:19,findMovieById FNDA:2,voteForMovie FNDA:5,listMovies -FNDA:5,(anonymous_29) -FNDA:5,(anonymous_30) -FNDA:3,(anonymous_31) +FNDA:5,(anonymous_21) +FNDA:5,(anonymous_22) +FNDA:3,(anonymous_23) FNDA:1,markMovieAsWatched FNDA:1,markMovieAsVetoed -FNDA:9,findUserByUsername DA:1,1 -DA:4,1 -DA:5,16 -DA:6,16 -DA:7,16 -DA:13,1 -DA:16,20 -DA:17,20 -DA:20,1 -DA:21,19 -DA:22,19 -DA:26,19 -DA:29,1 -DA:30,15 -DA:31,15 -DA:37,1 -DA:44,7 -DA:45,7 -DA:49,7 -DA:55,18 -DA:56,18 -DA:60,18 -DA:63,1 -DA:67,3 -DA:68,3 -DA:72,3 -DA:78,22 +DA:5,1 +DA:12,7 +DA:13,7 +DA:18,7 +DA:21,7 +DA:22,0 +DA:30,7 +DA:34,18 +DA:35,18 +DA:39,18 +DA:42,1 +DA:46,3 +DA:47,3 +DA:51,3 +DA:57,22 +DA:60,1 +DA:64,19 +DA:65,19 +DA:73,1 +DA:74,2 +DA:75,2 DA:81,1 -DA:85,19 -DA:86,19 +DA:82,5 +DA:83,5 +DA:86,5 +DA:89,5 +DA:93,1 DA:94,1 -DA:95,2 -DA:96,2 +DA:95,1 +DA:101,1 DA:102,1 -DA:103,5 -DA:104,5 -DA:106,5 -DA:107,5 -DA:110,1 -DA:111,1 -DA:112,1 -DA:118,1 -DA:119,1 -DA:120,1 -DA:123,1 -DA:126,9 -DA:127,9 -LF:47 -LH:47 -BRDA:49,0,0,7 -BRDA:49,0,1,0 -BRDA:49,1,0,0 -BRDA:49,1,1,7 -BRDA:49,2,0,7 -BRDA:49,2,1,7 -BRDA:60,3,0,18 -BRDA:60,3,1,0 -BRDA:60,4,0,18 -BRDA:60,4,1,18 -BRDA:78,5,0,22 -BRDA:78,5,1,18 -BRF:12 +DA:103,1 +LF:33 +LH:32 +BRDA:18,0,0,7 +BRDA:18,0,1,0 +BRDA:18,1,0,0 +BRDA:18,1,1,7 +BRDA:18,2,0,7 +BRDA:18,2,1,7 +BRDA:21,3,0,0 +BRDA:39,4,0,18 +BRDA:39,4,1,0 +BRDA:39,5,0,18 +BRDA:39,5,1,18 +BRDA:57,6,0,22 +BRDA:57,6,1,18 +BRF:13 BRH:9 end_of_record +TN: +SF:src/models/user/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +LF:2 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/models/user/model.ts +FN:5,createUser +FN:14,findUserByUsername +FNF:2 +FNH:2 +FNDA:19,createUser +FNDA:9,findUserByUsername +DA:1,1 +DA:5,1 +DA:6,19 +DA:7,19 +DA:11,19 +DA:14,1 +DA:17,9 +DA:18,9 +LF:8 +LH:8 +BRF:0 +BRH:0 +end_of_record diff --git a/src/consts.ts b/src/consts.ts index 314e7fe..520bdf3 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -1,3 +1,3 @@ -export const DATABASE_FILENAME = './db/database.db'; +export const DATABASE_FILENAME = './db/test_database.db'; export const KINOPOISK_URL = 'https://www.kinopoisk.ru/index.php?kp_query='; export const IMDB_URL = 'https://www.imdb.com/find/?q='; diff --git a/src/controllers/bot.test.ts b/src/controllers/bot.test.ts index d2115c5..e574d98 100644 --- a/src/controllers/bot.test.ts +++ b/src/controllers/bot.test.ts @@ -17,11 +17,11 @@ import { import { initializeDb } from '../dbController'; import { botHandlers } from './bot'; -const DATABASE_FILENAME = './test_database.db'; +const DATABASE_FILENAME = './db/test_database.db'; jest.mock('node-telegram-bot-api'); jest.mock('../consts.ts', () => ({ - DATABASE_FILENAME: './test_database.db', + DATABASE_FILENAME: './db/test_database.db', KINOPOISK_URL: 'https://www.kinopoisk.ru/index.php?kp_query=', IMDB_URL: 'https://www.imdb.com/find/?q=', })); @@ -30,17 +30,15 @@ describe('Bot Commands', () => { let bot: TelegramBot; let chatId = 0; const emitMsg = async (msg: TelegramBot.Message) => { - const handler = botHandlers.find((handler) => { - if (!msg.text) { - return false; - } - return handler[0].test(msg.text); - }); + const handler = botHandlers.find((handler) => + msg.text ? handler[0].test(msg.text) : false, + ); if (!handler) { return; } const match = msg.text?.split(' ') ?? null; - return await Promise.resolve(handler[1](bot)(msg, match)); + const msgHandler = handler[1](bot); + return await msgHandler(msg, match); }; const createChat = () => { chatId += 1; @@ -54,9 +52,6 @@ describe('Bot Commands', () => { afterAll(async () => { fs.rmSync(DATABASE_FILENAME); - }); - - afterEach(() => { jest.clearAllMocks(); }); @@ -305,6 +300,7 @@ describe('Bot Commands', () => { }); it('should not vote for a movie 2 times', async () => { + bot = new TelegramBot('test_token', { polling: true }); const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); const group = await createGroup(String(chatId)); diff --git a/src/controllers/bot.ts b/src/controllers/bot.ts index 127c849..8298f61 100644 --- a/src/controllers/bot.ts +++ b/src/controllers/bot.ts @@ -13,11 +13,17 @@ import { markMovieAsWatched, markMovieAsVetoed, hasUserMovieVote, + findUserByUsername, } from '../models'; import texts from '../texts.json'; import { getImdbUrl, getKinopoiskUrl, getMovieDescription } from './helpers'; -import { CheckError, handleCheckErrors } from '../errorHandler'; -import { THandler } from '../controllersTypes'; +import { + applyMiddlewares, + CheckError, + handleCheckErrors, + logger, + TRule, +} from '../middlewares'; import { checkAndGetArg, checkAndGetGroup, @@ -31,18 +37,15 @@ const MSG_OPTIONS: SendMessageOptions = { parse_mode: 'Markdown', }; -const rawBotHandlers: [RegExp, THandler][] = [ +const rawBotHandlers: TRule[] = [ [ /\/start/, (bot) => async (msg) => { - try { - await checkAndGetUserByUsername(msg); - } catch (error) { - if (error instanceof CheckError) { - await createUser(msg.from?.username ?? ''); - } else { - throw error; - } + const username = msg.from?.username; + + const user = await findUserByUsername(username ?? ''); + if (!user) { + await createUser(msg.from?.username ?? ''); } bot.sendMessage(msg.chat.id, texts.start); @@ -50,7 +53,7 @@ const rawBotHandlers: [RegExp, THandler][] = [ ], [ /\/help/, - (bot) => (msg) => { + (bot) => async (msg) => { bot.sendMessage(msg.chat.id, texts.help); }, ], @@ -99,10 +102,6 @@ const rawBotHandlers: [RegExp, THandler][] = [ getKinopoiskUrl(movieName), getImdbUrl(movieName), ); - if (!movie) { - bot.sendMessage(chatId, texts.movie_not_added); - return; - } bot.sendMessage( chatId, `${texts.movie_suggested}:\n${getMovieDescription(movie)}`, @@ -193,6 +192,7 @@ const rawBotHandlers: [RegExp, THandler][] = [ ], ]; -export const botHandlers = rawBotHandlers.map( - ([regexp, handler]) => [regexp, handleCheckErrors(handler)] as const, -); +export const botHandlers = applyMiddlewares(rawBotHandlers, [ + logger, + handleCheckErrors, +]); diff --git a/src/controllers/checkers.ts b/src/controllers/checkers.ts index a0da613..1823ac3 100644 --- a/src/controllers/checkers.ts +++ b/src/controllers/checkers.ts @@ -4,7 +4,7 @@ process.env.NTBA_FIX_319 = '1'; import TelegramBot from 'node-telegram-bot-api'; import texts from '../texts.json'; -import { CheckError } from '../errorHandler'; +import { CheckError } from '../middlewares/errorHandler'; import { findGroupByCode, findMovieById, diff --git a/src/dbController/database.test.ts b/src/dbController/database.test.ts index 8d8584c..a5cd758 100644 --- a/src/dbController/database.test.ts +++ b/src/dbController/database.test.ts @@ -1,10 +1,10 @@ import fs from 'fs'; import { openDb, initializeDb } from './database'; -const DATABASE_FILENAME = './test_database.db'; +const DATABASE_FILENAME = './db/test_database.db'; jest.mock('../consts.ts', () => ({ - DATABASE_FILENAME: './test_database.db', + DATABASE_FILENAME: './db/test_database.db', })); describe('Database Tests', () => { diff --git a/src/middlewares/applyMiddlewares.ts b/src/middlewares/applyMiddlewares.ts new file mode 100644 index 0000000..c9518ae --- /dev/null +++ b/src/middlewares/applyMiddlewares.ts @@ -0,0 +1,10 @@ +import { TMiddleware, TRule } from './controllers.types'; + +export const applyMiddlewares = ( + rules: TRule[], + middlewares: TMiddleware[], +): TRule[] => + rules.map(([regexp, handler]: TRule) => [ + regexp, + middlewares.reduce((acc, mw) => mw(acc), handler), + ]); diff --git a/src/controllersTypes.ts b/src/middlewares/controllers.types.ts similarity index 59% rename from src/controllersTypes.ts rename to src/middlewares/controllers.types.ts index 4c23ec6..d4e1b2d 100644 --- a/src/controllersTypes.ts +++ b/src/middlewares/controllers.types.ts @@ -6,4 +6,8 @@ import TelegramBot from 'node-telegram-bot-api'; export type THandler = ( bot: TelegramBot, -) => (msg: TelegramBot.Message, match: string[] | null) => void; +) => (msg: TelegramBot.Message, match: string[] | null) => Promise; + +export type TRule = [RegExp, THandler]; + +export type TMiddleware = (handler: THandler) => THandler; diff --git a/src/errorHandler/CheckError.ts b/src/middlewares/errorHandler/CheckError.ts similarity index 100% rename from src/errorHandler/CheckError.ts rename to src/middlewares/errorHandler/CheckError.ts diff --git a/src/errorHandler/handleCheckErrors.test.ts b/src/middlewares/errorHandler/handleCheckErrors.test.ts similarity index 59% rename from src/errorHandler/handleCheckErrors.test.ts rename to src/middlewares/errorHandler/handleCheckErrors.test.ts index 5d0b94a..3cef95c 100644 --- a/src/errorHandler/handleCheckErrors.test.ts +++ b/src/middlewares/errorHandler/handleCheckErrors.test.ts @@ -4,11 +4,25 @@ process.env.NTBA_FIX_319 = '1'; import TelegramBot from 'node-telegram-bot-api'; import { handleCheckErrors } from './handleCheckErrors'; +import { CheckError } from './CheckError'; describe('handleCheckErrors', () => { + it('should pass without errors', async () => { + const bot = { sendMessage: jest.fn() } as unknown as TelegramBot; + const handler = () => () => Promise.resolve(undefined); + const msg = { chat: { id: 1 } } as unknown as TelegramBot.Message; + + const checkErrorsHandler = handleCheckErrors(handler); + + await expect( + checkErrorsHandler(bot)(msg, ['', 'arg']), + ).resolves.toBeUndefined(); + }); + it('should handle CheckError', async () => { const bot = { sendMessage: jest.fn() } as unknown as TelegramBot; - const handler = jest.fn(() => () => undefined); + const handler = () => () => + Promise.reject(new CheckError('Check error message')); const msg = { chat: { id: 1 } } as unknown as TelegramBot.Message; const checkErrorsHandler = handleCheckErrors(handler); @@ -16,13 +30,12 @@ describe('handleCheckErrors', () => { await expect( checkErrorsHandler(bot)(msg, ['', 'arg']), ).resolves.toBeUndefined(); + expect(bot.sendMessage).toHaveBeenCalledWith(1, 'Check error message'); }); it('should throw error if not CheckError', async () => { const bot = { sendMessage: jest.fn() } as unknown as TelegramBot; - const handler = jest.fn(() => () => { - throw new Error('Not a CheckError'); - }); + const handler = () => () => Promise.reject(new Error('Not a CheckError')); const msg = { chat: { id: 1 } } as unknown as TelegramBot.Message; const checkErrorsHandler = handleCheckErrors(handler); diff --git a/src/errorHandler/handleCheckErrors.ts b/src/middlewares/errorHandler/handleCheckErrors.ts similarity index 63% rename from src/errorHandler/handleCheckErrors.ts rename to src/middlewares/errorHandler/handleCheckErrors.ts index 6127b0f..b91936a 100644 --- a/src/errorHandler/handleCheckErrors.ts +++ b/src/middlewares/errorHandler/handleCheckErrors.ts @@ -1,10 +1,8 @@ -import { THandler } from '../controllersTypes'; +import { TMiddleware } from '../controllers.types'; import { CheckError } from './CheckError'; -export const handleCheckErrors = - (handler: THandler): THandler => - (bot) => - async (msg, match) => { +export const handleCheckErrors: TMiddleware = + (handler) => (bot) => async (msg, match) => { try { await handler(bot)(msg, match); } catch (error) { diff --git a/src/errorHandler/index.ts b/src/middlewares/errorHandler/index.ts similarity index 100% rename from src/errorHandler/index.ts rename to src/middlewares/errorHandler/index.ts diff --git a/src/middlewares/index.ts b/src/middlewares/index.ts new file mode 100644 index 0000000..1ba0107 --- /dev/null +++ b/src/middlewares/index.ts @@ -0,0 +1,4 @@ +export * from './errorHandler'; +export * from './logger'; +export * from './applyMiddlewares'; +export * from './controllers.types'; diff --git a/src/middlewares/logger/index.ts b/src/middlewares/logger/index.ts new file mode 100644 index 0000000..1ff09ef --- /dev/null +++ b/src/middlewares/logger/index.ts @@ -0,0 +1 @@ +export * from './logger'; diff --git a/src/middlewares/logger/logger.test.ts b/src/middlewares/logger/logger.test.ts new file mode 100644 index 0000000..8a79a5c --- /dev/null +++ b/src/middlewares/logger/logger.test.ts @@ -0,0 +1,43 @@ +// Fix for error: node-telegram-bot-api +// deprecated Automatic enabling of cancellation +// of promises is deprecated In the future +process.env.NTBA_FIX_319 = '1'; +import TelegramBot from 'node-telegram-bot-api'; +import { logger } from './logger'; + +describe('logger middleware', () => { + it('should log user message', async () => { + const loggerMock = jest.spyOn(console, 'log'); + const bot = {} as TelegramBot; + const handler = () => () => Promise.resolve(undefined); + const msg = { + from: { username: 'test_user' }, + text: 'Hello, bot!', + } as unknown as TelegramBot.Message; + + process.env.DEBUG_OUTPUT = '1'; + logger(handler)(bot)(msg, ['']); + + expect(loggerMock).toHaveBeenCalledWith( + expect.stringContaining('User: test_user, Message: Hello, bot!'), + ); + expect(loggerMock).toHaveBeenCalledWith(expect.stringContaining('DB')); + }); + + it('should log message from unknown user', async () => { + const loggerMock = jest.spyOn(console, 'log'); + const bot = {} as TelegramBot; + const handler = () => () => Promise.resolve(undefined); + const msg = { + text: 'Hello, bot!', + } as unknown as TelegramBot.Message; + + process.env.DEBUG_OUTPUT = '1'; + logger(handler)(bot)(msg, ['']); + + expect(loggerMock).toHaveBeenCalledWith( + expect.stringContaining('User: undefined, Message: Hello, bot!'), + ); + expect(loggerMock).toHaveBeenCalledWith(expect.stringContaining('DB')); + }); +}); diff --git a/src/middlewares/logger/logger.ts b/src/middlewares/logger/logger.ts new file mode 100644 index 0000000..d8d8d19 --- /dev/null +++ b/src/middlewares/logger/logger.ts @@ -0,0 +1,11 @@ +import { log } from '../../helpers'; +import { TMiddleware } from '../controllers.types'; + +export const logger: TMiddleware = (handler) => (bot) => async (msg, match) => { + if (process.env.DEBUG_OUTPUT === '1') { + log(`User: ${msg.from?.username}, Message: ${msg.text}`); + log(`DB(Movies): `); + } + + await handler(bot)(msg, match); +}; diff --git a/src/models/movies/index.ts b/src/models/group/index.ts similarity index 100% rename from src/models/movies/index.ts rename to src/models/group/index.ts diff --git a/src/models/group/model.ts b/src/models/group/model.ts new file mode 100644 index 0000000..b56920f --- /dev/null +++ b/src/models/group/model.ts @@ -0,0 +1,27 @@ +import { openDb } from '../../dbController'; +import { TId } from '../types'; +import { IGroup } from './types'; + +export async function createGroup(code: string): Promise { + const db = await openDb(); + const res = await db.run(`INSERT INTO groups (code) VALUES (?)`, [code]); + return { + id: res.lastID, + code, + } as IGroup; +} + +export async function findGroupByCode( + code: string, +): Promise { + const db = await openDb(); + return db.get(`SELECT * FROM groups WHERE code = ?`, [code]); +} + +export async function addUserToGroup(groupId: TId, userId: TId) { + const db = await openDb(); + await db.run(`INSERT INTO group_users (group_id, user_id) VALUES (?, ?)`, [ + groupId, + userId, + ]); +} diff --git a/src/models/group/types.ts b/src/models/group/types.ts new file mode 100644 index 0000000..2bc5c42 --- /dev/null +++ b/src/models/group/types.ts @@ -0,0 +1,6 @@ +import { TId } from '../types'; + +export interface IGroup { + id: TId; + code: string; +} diff --git a/src/models/index.ts b/src/models/index.ts index 2e93e54..737369d 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1 +1,3 @@ -export * from './movies'; +export * from './group'; +export * from './movie'; +export * from './user'; diff --git a/src/models/movie/index.ts b/src/models/movie/index.ts new file mode 100644 index 0000000..ee648ec --- /dev/null +++ b/src/models/movie/index.ts @@ -0,0 +1,2 @@ +export * from './model'; +export * from './types'; diff --git a/src/models/movies/model.ts b/src/models/movie/model.ts similarity index 64% rename from src/models/movies/model.ts rename to src/models/movie/model.ts index e948615..3886307 100644 --- a/src/models/movies/model.ts +++ b/src/models/movie/model.ts @@ -1,38 +1,6 @@ import { openDb } from '../../dbController'; -import { IGroup, IMovie, IUser, TId } from './types'; - -export async function createGroup(code: string): Promise { - const db = await openDb(); - const res = await db.run(`INSERT INTO groups (code) VALUES (?)`, [code]); - return { - id: res.lastID as TId, - code, - }; -} - -export async function findGroupByCode( - code: string, -): Promise { - const db = await openDb(); - return db.get(`SELECT * FROM groups WHERE code = ?`, [code]); -} - -export async function createUser(username: string): Promise { - const db = await openDb(); - const res = await db.run( - `INSERT OR IGNORE INTO users (username) VALUES (?)`, - [username], - ); - return { id: res.lastID as TId, username }; -} - -export async function addUserToGroup(groupId: TId, userId: TId) { - const db = await openDb(); - await db.run(`INSERT INTO group_users (group_id, user_id) VALUES (?, ?)`, [ - groupId, - userId, - ]); -} +import { TId } from '../types'; +import { IMovie } from './types'; export async function suggestMovie( name: string, @@ -40,15 +8,26 @@ export async function suggestMovie( groupId: TId, kinopoiskLink: string, imdbLink: string, -): Promise { +): Promise { const db = await openDb(); const res = await db.run( `INSERT INTO movies (name, suggested_by, group_id, kinopoisk_link, imdb_link) VALUES (?, ?, ?, ?, ?)`, [name, suggestedBy, groupId, kinopoiskLink, imdbLink], ); - return res?.lastID !== undefined - ? findMovieById(res.lastID, groupId) - : undefined; + const movie = + res?.lastID !== undefined + ? await findMovieById(res.lastID, groupId) + : undefined; + if (!movie) { + throw new Error( + `Failed to insert movie: ${JSON.stringify({ + name, + suggestedBy, + groupId, + })}`, + ); + } + return movie; } async function calcMovieVotes(movieId: TId): Promise { @@ -123,10 +102,3 @@ export async function markMovieAsVetoed(movieId: TId) { const db = await openDb(); await db.run(`UPDATE movies SET is_vetoed = 1 WHERE id = ?`, [movieId]); } - -export async function findUserByUsername( - username: string, -): Promise { - const db = await openDb(); - return db.get(`SELECT * FROM users WHERE username = ?`, [username]); -} diff --git a/src/models/movies/types.ts b/src/models/movie/types.ts similarity index 56% rename from src/models/movies/types.ts rename to src/models/movie/types.ts index d0d438b..ff7026e 100644 --- a/src/models/movies/types.ts +++ b/src/models/movie/types.ts @@ -1,14 +1,4 @@ -export type TId = number; - -export interface IGroup { - id: TId; - code: string; -} - -export interface IUser { - id: TId; - username: string; -} +import { TId } from '../types'; export interface IMovie { id: TId; diff --git a/src/models/types.ts b/src/models/types.ts new file mode 100644 index 0000000..fad98a0 --- /dev/null +++ b/src/models/types.ts @@ -0,0 +1 @@ +export type TId = number; diff --git a/src/models/user/index.ts b/src/models/user/index.ts new file mode 100644 index 0000000..ee648ec --- /dev/null +++ b/src/models/user/index.ts @@ -0,0 +1,2 @@ +export * from './model'; +export * from './types'; diff --git a/src/models/user/model.ts b/src/models/user/model.ts new file mode 100644 index 0000000..40022d9 --- /dev/null +++ b/src/models/user/model.ts @@ -0,0 +1,19 @@ +import { openDb } from '../../dbController'; +import { TId } from '../types'; +import { IUser } from './types'; + +export async function createUser(username: string): Promise { + const db = await openDb(); + const res = await db.run( + `INSERT OR IGNORE INTO users (username) VALUES (?)`, + [username], + ); + return { id: res.lastID as TId, username }; +} + +export async function findUserByUsername( + username: string, +): Promise { + const db = await openDb(); + return db.get(`SELECT * FROM users WHERE username = ?`, [username]); +} diff --git a/src/models/user/types.ts b/src/models/user/types.ts new file mode 100644 index 0000000..5bc7c22 --- /dev/null +++ b/src/models/user/types.ts @@ -0,0 +1,6 @@ +import { TId } from '../types'; + +export interface IUser { + id: TId; + username: string; +} From 689f40b45175c3233df8a39d5a38d90c80f6f666 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Thu, 15 Aug 2024 20:29:06 +0200 Subject: [PATCH 03/11] Remove reports --- coverage/coverage-summary.json | 24 - coverage/lcov-report/base.css | 224 ------ coverage/lcov-report/block-navigation.js | 87 --- coverage/lcov-report/controllers/bot.ts.html | 679 ------------------ .../lcov-report/controllers/checkers.ts.html | 313 -------- .../lcov-report/controllers/helpers.ts.html | 121 ---- coverage/lcov-report/controllers/index.html | 146 ---- coverage/lcov-report/database.ts.html | 226 ------ .../lcov-report/dbController/database.ts.html | 226 ------ coverage/lcov-report/dbController/index.html | 131 ---- .../lcov-report/dbController/index.ts.html | 88 --- .../errorHandler/CheckError.ts.html | 109 --- .../errorHandler/handleCheckErrors.ts.html | 136 ---- coverage/lcov-report/errorHandler/index.html | 146 ---- .../lcov-report/errorHandler/index.ts.html | 91 --- coverage/lcov-report/favicon.png | Bin 445 -> 0 bytes coverage/lcov-report/helpers/index.html | 131 ---- coverage/lcov-report/helpers/index.ts.html | 88 --- coverage/lcov-report/helpers/log.ts.html | 106 --- coverage/lcov-report/index.html | 251 ------- .../middlewares/applyMiddlewares.ts.html | 115 --- .../middlewares/controllers.types.ts.html | 124 ---- .../errorHandler/CheckError.ts.html | 109 --- .../errorHandler/handleCheckErrors.ts.html | 130 ---- .../middlewares/errorHandler/index.html | 146 ---- .../middlewares/errorHandler/index.ts.html | 91 --- coverage/lcov-report/middlewares/index.html | 146 ---- .../lcov-report/middlewares/index.ts.html | 97 --- .../lcov-report/middlewares/logger/index.html | 131 ---- .../middlewares/logger/index.ts.html | 88 --- .../middlewares/logger/logger.ts.html | 118 --- coverage/lcov-report/models/group/index.html | 131 ---- .../lcov-report/models/group/index.ts.html | 91 --- .../lcov-report/models/group/model.ts.html | 166 ----- coverage/lcov-report/models/index.html | 116 --- coverage/lcov-report/models/index.ts.html | 94 --- coverage/lcov-report/models/movie/index.html | 131 ---- .../lcov-report/models/movie/index.ts.html | 91 --- .../lcov-report/models/movie/model.ts.html | 397 ---------- coverage/lcov-report/models/movies/index.html | 131 ---- .../lcov-report/models/movies/index.ts.html | 91 --- .../lcov-report/models/movies/model.ts.html | 469 ------------ coverage/lcov-report/models/user/index.html | 131 ---- .../lcov-report/models/user/index.ts.html | 91 --- .../lcov-report/models/user/model.ts.html | 142 ---- coverage/lcov-report/prettify.css | 1 - coverage/lcov-report/prettify.js | 2 - coverage/lcov-report/sort-arrow-sprite.png | Bin 138 -> 0 bytes coverage/lcov-report/sorter.js | 196 ----- coverage/lcov.info | 633 ---------------- src/consts.ts | 2 +- src/controllers/bot.test.ts | 48 +- src/controllers/bot.ts | 22 +- src/controllers/checkers.ts | 6 +- src/dbController/database.ts | 12 + src/middlewares/logger/logger.test.ts | 24 +- src/middlewares/logger/logger.ts | 6 +- src/models/group/model.ts | 13 +- 58 files changed, 85 insertions(+), 7770 deletions(-) delete mode 100644 coverage/coverage-summary.json delete mode 100644 coverage/lcov-report/base.css delete mode 100644 coverage/lcov-report/block-navigation.js delete mode 100644 coverage/lcov-report/controllers/bot.ts.html delete mode 100644 coverage/lcov-report/controllers/checkers.ts.html delete mode 100644 coverage/lcov-report/controllers/helpers.ts.html delete mode 100644 coverage/lcov-report/controllers/index.html delete mode 100644 coverage/lcov-report/database.ts.html delete mode 100644 coverage/lcov-report/dbController/database.ts.html delete mode 100644 coverage/lcov-report/dbController/index.html delete mode 100644 coverage/lcov-report/dbController/index.ts.html delete mode 100644 coverage/lcov-report/errorHandler/CheckError.ts.html delete mode 100644 coverage/lcov-report/errorHandler/handleCheckErrors.ts.html delete mode 100644 coverage/lcov-report/errorHandler/index.html delete mode 100644 coverage/lcov-report/errorHandler/index.ts.html delete mode 100644 coverage/lcov-report/favicon.png delete mode 100644 coverage/lcov-report/helpers/index.html delete mode 100644 coverage/lcov-report/helpers/index.ts.html delete mode 100644 coverage/lcov-report/helpers/log.ts.html delete mode 100644 coverage/lcov-report/index.html delete mode 100644 coverage/lcov-report/middlewares/applyMiddlewares.ts.html delete mode 100644 coverage/lcov-report/middlewares/controllers.types.ts.html delete mode 100644 coverage/lcov-report/middlewares/errorHandler/CheckError.ts.html delete mode 100644 coverage/lcov-report/middlewares/errorHandler/handleCheckErrors.ts.html delete mode 100644 coverage/lcov-report/middlewares/errorHandler/index.html delete mode 100644 coverage/lcov-report/middlewares/errorHandler/index.ts.html delete mode 100644 coverage/lcov-report/middlewares/index.html delete mode 100644 coverage/lcov-report/middlewares/index.ts.html delete mode 100644 coverage/lcov-report/middlewares/logger/index.html delete mode 100644 coverage/lcov-report/middlewares/logger/index.ts.html delete mode 100644 coverage/lcov-report/middlewares/logger/logger.ts.html delete mode 100644 coverage/lcov-report/models/group/index.html delete mode 100644 coverage/lcov-report/models/group/index.ts.html delete mode 100644 coverage/lcov-report/models/group/model.ts.html delete mode 100644 coverage/lcov-report/models/index.html delete mode 100644 coverage/lcov-report/models/index.ts.html delete mode 100644 coverage/lcov-report/models/movie/index.html delete mode 100644 coverage/lcov-report/models/movie/index.ts.html delete mode 100644 coverage/lcov-report/models/movie/model.ts.html delete mode 100644 coverage/lcov-report/models/movies/index.html delete mode 100644 coverage/lcov-report/models/movies/index.ts.html delete mode 100644 coverage/lcov-report/models/movies/model.ts.html delete mode 100644 coverage/lcov-report/models/user/index.html delete mode 100644 coverage/lcov-report/models/user/index.ts.html delete mode 100644 coverage/lcov-report/models/user/model.ts.html delete mode 100644 coverage/lcov-report/prettify.css delete mode 100644 coverage/lcov-report/prettify.js delete mode 100644 coverage/lcov-report/sort-arrow-sprite.png delete mode 100644 coverage/lcov-report/sorter.js delete mode 100644 coverage/lcov.info diff --git a/coverage/coverage-summary.json b/coverage/coverage-summary.json deleted file mode 100644 index 1124c0e..0000000 --- a/coverage/coverage-summary.json +++ /dev/null @@ -1,24 +0,0 @@ -{"total": {"lines":{"total":226,"covered":224,"skipped":0,"pct":99.11},"statements":{"total":257,"covered":255,"skipped":0,"pct":99.22},"functions":{"total":76,"covered":76,"skipped":0,"pct":100},"branches":{"total":57,"covered":47,"skipped":0,"pct":82.45},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/controllers/bot.ts": {"lines":{"total":80,"covered":80,"skipped":0,"pct":100},"functions":{"total":31,"covered":31,"skipped":0,"pct":100},"statements":{"total":90,"covered":90,"skipped":0,"pct":100},"branches":{"total":20,"covered":16,"skipped":0,"pct":80}} -,"/Users/gpont/Documents/watch_together/src/controllers/checkers.ts": {"lines":{"total":36,"covered":35,"skipped":0,"pct":97.22},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":41,"covered":40,"skipped":0,"pct":97.56},"branches":{"total":16,"covered":14,"skipped":0,"pct":87.5}} -,"/Users/gpont/Documents/watch_together/src/controllers/helpers.ts": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/dbController/database.ts": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/dbController/index.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":1,"covered":1,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/helpers/index.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":1,"covered":1,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/helpers/log.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/applyMiddlewares.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/controllers.types.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":1,"covered":1,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/index.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/errorHandler/CheckError.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/errorHandler/handleCheckErrors.ts": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":11,"covered":11,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/errorHandler/index.ts": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/logger/index.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":1,"covered":1,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/middlewares/logger/logger.ts": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":5,"covered":5,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/models/index.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/models/group/index.ts": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/models/group/model.ts": {"lines":{"total":11,"covered":11,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":11,"covered":11,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/models/movie/index.ts": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/models/movie/model.ts": {"lines":{"total":33,"covered":32,"skipped":0,"pct":96.96},"functions":{"total":12,"covered":12,"skipped":0,"pct":100},"statements":{"total":34,"covered":33,"skipped":0,"pct":97.05},"branches":{"total":13,"covered":9,"skipped":0,"pct":69.23}} -,"/Users/gpont/Documents/watch_together/src/models/user/index.ts": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/gpont/Documents/watch_together/src/models/user/model.ts": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -} diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css deleted file mode 100644 index f418035..0000000 --- a/coverage/lcov-report/base.css +++ /dev/null @@ -1,224 +0,0 @@ -body, html { - margin:0; padding: 0; - height: 100%; -} -body { - font-family: Helvetica Neue, Helvetica, Arial; - font-size: 14px; - color:#333; -} -.small { font-size: 12px; } -*, *:after, *:before { - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - box-sizing:border-box; - } -h1 { font-size: 20px; margin: 0;} -h2 { font-size: 14px; } -pre { - font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; - margin: 0; - padding: 0; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; -} -a { color:#0074D9; text-decoration:none; } -a:hover { text-decoration:underline; } -.strong { font-weight: bold; } -.space-top1 { padding: 10px 0 0 0; } -.pad2y { padding: 20px 0; } -.pad1y { padding: 10px 0; } -.pad2x { padding: 0 20px; } -.pad2 { padding: 20px; } -.pad1 { padding: 10px; } -.space-left2 { padding-left:55px; } -.space-right2 { padding-right:20px; } -.center { text-align:center; } -.clearfix { display:block; } -.clearfix:after { - content:''; - display:block; - height:0; - clear:both; - visibility:hidden; - } -.fl { float: left; } -@media only screen and (max-width:640px) { - .col3 { width:100%; max-width:100%; } - .hide-mobile { display:none!important; } -} - -.quiet { - color: #7f7f7f; - color: rgba(0,0,0,0.5); -} -.quiet a { opacity: 0.7; } - -.fraction { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 10px; - color: #555; - background: #E8E8E8; - padding: 4px 5px; - border-radius: 3px; - vertical-align: middle; -} - -div.path a:link, div.path a:visited { color: #333; } -table.coverage { - border-collapse: collapse; - margin: 10px 0 0 0; - padding: 0; -} - -table.coverage td { - margin: 0; - padding: 0; - vertical-align: top; -} -table.coverage td.line-count { - text-align: right; - padding: 0 5px 0 20px; -} -table.coverage td.line-coverage { - text-align: right; - padding-right: 10px; - min-width:20px; -} - -table.coverage td span.cline-any { - display: inline-block; - padding: 0 5px; - width: 100%; -} -.missing-if-branch { - display: inline-block; - margin-right: 5px; - border-radius: 3px; - position: relative; - padding: 0 4px; - background: #333; - color: yellow; -} - -.skip-if-branch { - display: none; - margin-right: 10px; - position: relative; - padding: 0 4px; - background: #ccc; - color: white; -} -.missing-if-branch .typ, .skip-if-branch .typ { - color: inherit !important; -} -.coverage-summary { - border-collapse: collapse; - width: 100%; -} -.coverage-summary tr { border-bottom: 1px solid #bbb; } -.keyline-all { border: 1px solid #ddd; } -.coverage-summary td, .coverage-summary th { padding: 10px; } -.coverage-summary tbody { border: 1px solid #bbb; } -.coverage-summary td { border-right: 1px solid #bbb; } -.coverage-summary td:last-child { border-right: none; } -.coverage-summary th { - text-align: left; - font-weight: normal; - white-space: nowrap; -} -.coverage-summary th.file { border-right: none !important; } -.coverage-summary th.pct { } -.coverage-summary th.pic, -.coverage-summary th.abs, -.coverage-summary td.pct, -.coverage-summary td.abs { text-align: right; } -.coverage-summary td.file { white-space: nowrap; } -.coverage-summary td.pic { min-width: 120px !important; } -.coverage-summary tfoot td { } - -.coverage-summary .sorter { - height: 10px; - width: 7px; - display: inline-block; - margin-left: 0.5em; - background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; -} -.coverage-summary .sorted .sorter { - background-position: 0 -20px; -} -.coverage-summary .sorted-desc .sorter { - background-position: 0 -10px; -} -.status-line { height: 10px; } -/* yellow */ -.cbranch-no { background: yellow !important; color: #111; } -/* dark red */ -.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } -.low .chart { border:1px solid #C21F39 } -.highlighted, -.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ - background: #C21F39 !important; -} -/* medium red */ -.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } -/* light red */ -.low, .cline-no { background:#FCE1E5 } -/* light green */ -.high, .cline-yes { background:rgb(230,245,208) } -/* medium green */ -.cstat-yes { background:rgb(161,215,106) } -/* dark green */ -.status-line.high, .high .cover-fill { background:rgb(77,146,33) } -.high .chart { border:1px solid rgb(77,146,33) } -/* dark yellow (gold) */ -.status-line.medium, .medium .cover-fill { background: #f9cd0b; } -.medium .chart { border:1px solid #f9cd0b; } -/* light yellow */ -.medium { background: #fff4c2; } - -.cstat-skip { background: #ddd; color: #111; } -.fstat-skip { background: #ddd; color: #111 !important; } -.cbranch-skip { background: #ddd !important; color: #111; } - -span.cline-neutral { background: #eaeaea; } - -.coverage-summary td.empty { - opacity: .5; - padding-top: 4px; - padding-bottom: 4px; - line-height: 1; - color: #888; -} - -.cover-fill, .cover-empty { - display:inline-block; - height: 12px; -} -.chart { - line-height: 0; -} -.cover-empty { - background: white; -} -.cover-full { - border-right: none !important; -} -pre.prettyprint { - border: none !important; - padding: 0 !important; - margin: 0 !important; -} -.com { color: #999 !important; } -.ignore-none { color: #999; font-weight: normal; } - -.wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -48px; -} -.footer, .push { - height: 48px; -} diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js deleted file mode 100644 index cc12130..0000000 --- a/coverage/lcov-report/block-navigation.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable */ -var jumpToCode = (function init() { - // Classes of code we would like to highlight in the file view - var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; - - // Elements to highlight in the file listing view - var fileListingElements = ['td.pct.low']; - - // We don't want to select elements that are direct descendants of another match - var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` - - // Selecter that finds elements on the page to which we can jump - var selector = - fileListingElements.join(', ') + - ', ' + - notSelector + - missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` - - // The NodeList of matching elements - var missingCoverageElements = document.querySelectorAll(selector); - - var currentIndex; - - function toggleClass(index) { - missingCoverageElements - .item(currentIndex) - .classList.remove('highlighted'); - missingCoverageElements.item(index).classList.add('highlighted'); - } - - function makeCurrent(index) { - toggleClass(index); - currentIndex = index; - missingCoverageElements.item(index).scrollIntoView({ - behavior: 'smooth', - block: 'center', - inline: 'center' - }); - } - - function goToPrevious() { - var nextIndex = 0; - if (typeof currentIndex !== 'number' || currentIndex === 0) { - nextIndex = missingCoverageElements.length - 1; - } else if (missingCoverageElements.length > 1) { - nextIndex = currentIndex - 1; - } - - makeCurrent(nextIndex); - } - - function goToNext() { - var nextIndex = 0; - - if ( - typeof currentIndex === 'number' && - currentIndex < missingCoverageElements.length - 1 - ) { - nextIndex = currentIndex + 1; - } - - makeCurrent(nextIndex); - } - - return function jump(event) { - if ( - document.getElementById('fileSearch') === document.activeElement && - document.activeElement != null - ) { - // if we're currently focused on the search input, we don't want to navigate - return; - } - - switch (event.which) { - case 78: // n - case 74: // j - goToNext(); - break; - case 66: // b - case 75: // k - case 80: // p - goToPrevious(); - break; - } - }; -})(); -window.addEventListener('keydown', jumpToCode); diff --git a/coverage/lcov-report/controllers/bot.ts.html b/coverage/lcov-report/controllers/bot.ts.html deleted file mode 100644 index 8f2a3ee..0000000 --- a/coverage/lcov-report/controllers/bot.ts.html +++ /dev/null @@ -1,679 +0,0 @@ - - - - - - Code coverage report for controllers/bot.ts - - - - - - - - - -
-
-

All files / controllers bot.ts

-
- -
- 100% - Statements - 90/90 -
- - -
- 80% - Branches - 16/20 -
- - -
- 100% - Functions - 31/31 -
- - -
- 100% - Lines - 80/80 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199  -  -  -1x -  -1x -  -  -  -  -  -  -  -  -  -  -  -1x -1x -1x -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -1x -  -  -  -  -1x -  -  -1x -1x -  -1x -1x -1x -  -  -1x -  -  -  -  -1x -1x -  -  -  -  -2x -2x -2x -2x -1x -1x -  -1x -1x -  -  -  -  -4x -4x -4x -3x -  -2x -2x -1x -1x -  -1x -1x -  -  -  -  -3x -3x -3x -  -2x -1x -  -1x -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -5x -5x -5x -  -  -  -  -4x -4x -4x -  -3x -1x -1x -  -  -2x -2x -  -  -  -  -2x -2x -  -2x -1x -  -  -1x -1x -  -  -  -  -4x -4x -4x -  -  -  -  -3x -2x -  -1x -1x -  -  -  -  -3x -3x -3x -  -  -  -  -2x -2x -  -1x -1x -  -  -  -  -3x -3x -  -3x -2x -1x -  -  -1x -1x -  -  -  -  -1x -  -  -  - 
// Fix for error: node-telegram-bot-api
-// deprecated Automatic enabling of cancellation
-// of promises is deprecated In the future
-process.env.NTBA_FIX_319 = '1';
-import { SendMessageOptions } from 'node-telegram-bot-api';
-import {
-  createGroup,
-  findGroupByCode,
-  createUser,
-  addUserToGroup,
-  suggestMovie,
-  voteForMovie,
-  markMovieAsWatched,
-  markMovieAsVetoed,
-  hasUserMovieVote,
-  findUserByUsername,
-} from '../models';
-import texts from '../texts.json';
-import { getImdbUrl, getKinopoiskUrl, getMovieDescription } from './helpers';
-import {
-  applyMiddlewares,
-  CheckError,
-  handleCheckErrors,
-  logger,
-  TRule,
-} from '../middlewares';
-import {
-  checkAndGetArg,
-  checkAndGetGroup,
-  checkAndGetMovie,
-  checkAndGetUserByUsername,
-  checkAndGetMoviesList,
-} from './checkers';
- 
-const MSG_OPTIONS: SendMessageOptions = {
-  disable_web_page_preview: true,
-  parse_mode: 'Markdown',
-};
- 
-const rawBotHandlers: TRule[] = [
-  [
-    /\/start/,
-    (bot) => async (msg) => {
-      const username = msg.from?.username;
- 
-      const user = await findUserByUsername(username ?? '');
-      if (!user) {
-        await createUser(msg.from?.username ?? '');
-      }
- 
-      bot.sendMessage(msg.chat.id, texts.start);
-    },
-  ],
-  [
-    /\/help/,
-    (bot) => async (msg) => {
-      bot.sendMessage(msg.chat.id, texts.help);
-    },
-  ],
-  [
-    /\/create_group/,
-    (bot) => async (msg) => {
-      const chatId = msg.chat.id;
-      const group = await findGroupByCode(String(chatId));
-      if (group) {
-        bot.sendMessage(chatId, texts.group_already_created + group.code);
-        return;
-      }
-      await createGroup(String(chatId));
-      bot.sendMessage(chatId, `${texts.group_created} ${chatId}`);
-    },
-  ],
-  [
-    /\/join_group (.*)/,
-    (bot) => async (msg, match) => {
-      const chatId = msg.chat.id;
-      const groupCode = checkAndGetArg(match, texts.no_group_code);
-      const user = await checkAndGetUserByUsername(msg);
- 
-      const group = await findGroupByCode(groupCode);
-      if (!group) {
-        bot.sendMessage(chatId, texts.group_not_found);
-        return;
-      }
-      await addUserToGroup(group.id, user.id);
-      bot.sendMessage(chatId, texts.joined_group);
-    },
-  ],
-  [
-    /\/suggest (.*)/,
-    (bot) => async (msg, match) => {
-      const chatId = msg.chat.id;
-      const movieName = checkAndGetArg(match, texts.no_movie_name);
- 
-      const user = await checkAndGetUserByUsername(msg);
-      const group = await checkAndGetGroup(msg);
- 
-      const movie = await suggestMovie(
-        movieName,
-        user.id,
-        group.id,
-        getKinopoiskUrl(movieName),
-        getImdbUrl(movieName),
-      );
-      bot.sendMessage(
-        chatId,
-        `${texts.movie_suggested}:\n${getMovieDescription(movie)}`,
-        MSG_OPTIONS,
-      );
-    },
-  ],
-  [
-    /\/vote ?(.*)/,
-    (bot) => async (msg, match) => {
-      const chatId = msg.chat.id;
-      const movieId = parseInt(
-        checkAndGetArg(match, texts.movie_not_found),
-        10,
-      );
- 
-      const user = await checkAndGetUserByUsername(msg);
-      const group = await checkAndGetGroup(msg);
-      const movie = await checkAndGetMovie(movieId, group.id);
- 
-      if (await hasUserMovieVote(user.id, movieId)) {
-        bot.sendMessage(chatId, texts.already_voted);
-        return;
-      }
- 
-      await voteForMovie(movieId, user.id);
-      bot.sendMessage(chatId, `${texts.voted} "${movie.name}"`);
-    },
-  ],
-  [
-    /\/list/,
-    (bot) => async (msg) => {
-      const chatId = msg.chat.id;
- 
-      const group = await checkAndGetGroup(msg);
-      const movies = await checkAndGetMoviesList(group.id);
- 
-      const movieList =
-        texts.movie_list + movies.map(getMovieDescription).join('');
-      bot.sendMessage(chatId, movieList, MSG_OPTIONS);
-    },
-  ],
-  [
-    /\/watched (.*)/,
-    (bot) => async (msg, match) => {
-      const chatId = msg.chat.id;
-      const movieId = parseInt(
-        checkAndGetArg(match, texts.movie_not_found),
-        10,
-      );
- 
-      const group = await checkAndGetGroup(msg);
-      const movie = await checkAndGetMovie(movieId, group.id);
- 
-      await markMovieAsWatched(movieId, group.id);
-      bot.sendMessage(chatId, `${texts.movie_watched} "${movie.name}"`);
-    },
-  ],
-  [
-    /\/veto (.*)/,
-    (bot) => async (msg, match) => {
-      const chatId = msg.chat.id;
-      const movieId = parseInt(
-        checkAndGetArg(match, texts.movie_not_found),
-        10,
-      );
- 
-      const group = await checkAndGetGroup(msg);
-      const movie = await checkAndGetMovie(movieId, group.id);
- 
-      await markMovieAsVetoed(movieId);
-      bot.sendMessage(chatId, `${texts.vetoed} "${movie.name}"`);
-    },
-  ],
-  [
-    /\/random/,
-    (bot) => async (msg) => {
-      const chatId = msg.chat.id;
- 
-      const group = await checkAndGetGroup(msg);
-      const movies = (await checkAndGetMoviesList(group.id)).filter(
-        (movie) => !movie.is_vetoed,
-      );
- 
-      const movie = movies[Math.floor(Math.random() * movies.length)];
-      bot.sendMessage(chatId, getMovieDescription(movie), MSG_OPTIONS);
-    },
-  ],
-];
- 
-export const botHandlers = applyMiddlewares(rawBotHandlers, [
-  logger,
-  handleCheckErrors,
-]);
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/controllers/checkers.ts.html b/coverage/lcov-report/controllers/checkers.ts.html deleted file mode 100644 index 29691f4..0000000 --- a/coverage/lcov-report/controllers/checkers.ts.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - Code coverage report for controllers/checkers.ts - - - - - - - - - -
-
-

All files / controllers checkers.ts

-
- -
- 97.56% - Statements - 40/41 -
- - -
- 87.5% - Branches - 14/16 -
- - -
- 100% - Functions - 9/9 -
- - -
- 97.22% - Lines - 35/36 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77  -  -  -1x -  -1x -1x -1x -  -  -  -  -  -  -  -  -  -1x -  -9x -9x -  -9x -2x -  -7x -7x -  -  -7x -  -  -1x -  -15x -15x -15x -  -15x -3x -  -12x -  -  -1x -  -  -  -19x -5x -  -14x -  -  -1x -  -  -8x -8x -  -8x -3x -  -5x -  -  -1x -  -3x -3x -3x -1x -  -  -2x -  - 
// Fix for error: node-telegram-bot-api
-// deprecated Automatic enabling of cancellation
-// of promises is deprecated In the future
-process.env.NTBA_FIX_319 = '1';
-import TelegramBot from 'node-telegram-bot-api';
-import texts from '../texts.json';
-import { CheckError } from '../middlewares/errorHandler';
-import {
-  findGroupByCode,
-  findMovieById,
-  findUserByUsername,
-  IGroup,
-  IMovie,
-  IUser,
-  listMovies,
-} from '../models';
- 
-export const checkAndGetUserByUsername = async (
-  msg: TelegramBot.Message,
-): Promise<IUser> => {
-  const username = msg.from?.username;
- 
-  if (!username) {
-    throw new CheckError(texts.user_not_found);
-  }
-  const user = await findUserByUsername(username);
-  Iif (!user) {
-    throw new CheckError(texts.user_not_found);
-  }
-  return user;
-};
- 
-export const checkAndGetGroup = async (
-  msg: TelegramBot.Message,
-): Promise<IGroup> => {
-  const chatId = msg.chat.id;
-  const group = await findGroupByCode(String(chatId));
- 
-  if (!group) {
-    throw new CheckError(texts.not_in_group);
-  }
-  return group;
-};
- 
-export const checkAndGetArg = (
-  match: string[] | null,
-  errorText: string,
-): string => {
-  if (!match?.[1]) {
-    throw new CheckError(errorText);
-  }
-  return match.slice(1).join(' ');
-};
- 
-export const checkAndGetMovie = async (
-  movieId: number,
-  groupId: number,
-): Promise<IMovie> => {
-  const movie = await findMovieById(movieId, groupId);
- 
-  if (!movie) {
-    throw new CheckError(texts.movie_not_found);
-  }
-  return movie;
-};
- 
-export const checkAndGetMoviesList = async (
-  groupId: number,
-): Promise<IMovie[]> => {
-  const movies = await listMovies(groupId);
-  if (!movies || movies.length === 0) {
-    throw new CheckError(texts.movie_list_empty);
-  }
- 
-  return movies;
-};
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/controllers/helpers.ts.html b/coverage/lcov-report/controllers/helpers.ts.html deleted file mode 100644 index 417f8a9..0000000 --- a/coverage/lcov-report/controllers/helpers.ts.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - Code coverage report for controllers/helpers.ts - - - - - - - - - -
-
-

All files / controllers helpers.ts

-
- -
- 100% - Statements - 10/10 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 3/3 -
- - -
- 100% - Lines - 7/7 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -131x -  -  -1x -1x -  -1x -1x -  -1x -3x -  - 
import { IMDB_URL, KINOPOISK_URL } from '../consts';
-import { IMovie } from '../models';
- 
-export const getKinopoiskUrl = (movieId: string) =>
-  `${KINOPOISK_URL}${encodeURIComponent(movieId)}`;
- 
-export const getImdbUrl = (movieId: string) =>
-  `${IMDB_URL}${encodeURIComponent(movieId)}`;
- 
-export const getMovieDescription = (movie: IMovie) =>
-  `${movie.id}. ${movie.name} (__голоса: ${movie.votes}__) /vote${movie.id}\n` +
-  `[Кинопоиск](${movie.kinopoisk_link}) | [IMDB](${movie.imdb_link})\n`;
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/controllers/index.html b/coverage/lcov-report/controllers/index.html deleted file mode 100644 index 1703706..0000000 --- a/coverage/lcov-report/controllers/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - Code coverage report for controllers - - - - - - - - - -
-
-

All files controllers

-
- -
- 99.29% - Statements - 140/141 -
- - -
- 83.33% - Branches - 30/36 -
- - -
- 100% - Functions - 43/43 -
- - -
- 99.18% - Lines - 122/123 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
bot.ts -
-
100%90/9080%16/20100%31/31100%80/80
checkers.ts -
-
97.56%40/4187.5%14/16100%9/997.22%35/36
helpers.ts -
-
100%10/10100%0/0100%3/3100%7/7
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/database.ts.html b/coverage/lcov-report/database.ts.html deleted file mode 100644 index 967dfb4..0000000 --- a/coverage/lcov-report/database.ts.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - Code coverage report for database.ts - - - - - - - - - -
-
-

All files database.ts

-
- -
- 100% - Statements - 8/8 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 8/8 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -481x -1x -1x -  -1x -4x -  -  -  -  -  -1x -1x -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import sqlite3 from 'sqlite3';
-import { open } from 'sqlite';
-import { DATABASE_FILENAME } from '../consts';
- 
-export async function openDb() {
-  return open({
-    filename: DATABASE_FILENAME,
-    driver: sqlite3.Database,
-  });
-}
- 
-export async function initializeDb() {
-  const db = await openDb();
-  await db.exec(`
-    CREATE TABLE IF NOT EXISTS groups (
-      id INTEGER PRIMARY KEY AUTOINCREMENT,
-      code TEXT UNIQUE
-    );
-    CREATE TABLE IF NOT EXISTS users (
-      id INTEGER PRIMARY KEY AUTOINCREMENT,
-      username TEXT UNIQUE
-    );
-    CREATE TABLE IF NOT EXISTS movies (
-      id INTEGER PRIMARY KEY AUTOINCREMENT,
-      name TEXT,
-      suggested_by INTEGER,
-      kinopoisk_link TEXT,
-      imdb_link TEXT,
-      group_id INTEGER,
-      is_vetoed BOOLEAN DEFAULT 0,
-      FOREIGN KEY (suggested_by) REFERENCES users(id),
-      FOREIGN KEY (group_id) REFERENCES groups(id)
-    );
-    CREATE TABLE IF NOT EXISTS group_users (
-      group_id INTEGER,
-      user_id INTEGER,
-      FOREIGN KEY (group_id) REFERENCES groups(id),
-      FOREIGN KEY (user_id) REFERENCES users(id)
-    );
-    CREATE TABLE IF NOT EXISTS votes (
-      movie_id INTEGER,
-      user_id INTEGER,
-      FOREIGN KEY (movie_id) REFERENCES movies(id),
-      FOREIGN KEY (user_id) REFERENCES users(id)
-    );
-  `);
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/dbController/database.ts.html b/coverage/lcov-report/dbController/database.ts.html deleted file mode 100644 index 3da15f5..0000000 --- a/coverage/lcov-report/dbController/database.ts.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - Code coverage report for dbController/database.ts - - - - - - - - - -
-
-

All files / dbController database.ts

-
- -
- 100% - Statements - 8/8 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 8/8 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -482x -2x -2x -  -2x -140x -  -  -  -  -  -2x -2x -2x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import sqlite3 from 'sqlite3';
-import { open } from 'sqlite';
-import { DATABASE_FILENAME } from '../consts';
- 
-export async function openDb() {
-  return open({
-    filename: DATABASE_FILENAME,
-    driver: sqlite3.Database,
-  });
-}
- 
-export async function initializeDb() {
-  const db = await openDb();
-  await db.exec(`
-    CREATE TABLE IF NOT EXISTS groups (
-      id INTEGER PRIMARY KEY AUTOINCREMENT,
-      code TEXT UNIQUE
-    );
-    CREATE TABLE IF NOT EXISTS users (
-      id INTEGER PRIMARY KEY AUTOINCREMENT,
-      username TEXT UNIQUE
-    );
-    CREATE TABLE IF NOT EXISTS movies (
-      id INTEGER PRIMARY KEY AUTOINCREMENT,
-      name TEXT,
-      suggested_by INTEGER,
-      kinopoisk_link TEXT,
-      imdb_link TEXT,
-      group_id INTEGER,
-      is_vetoed BOOLEAN DEFAULT 0,
-      FOREIGN KEY (suggested_by) REFERENCES users(id),
-      FOREIGN KEY (group_id) REFERENCES groups(id)
-    );
-    CREATE TABLE IF NOT EXISTS group_users (
-      group_id INTEGER,
-      user_id INTEGER,
-      FOREIGN KEY (group_id) REFERENCES groups(id),
-      FOREIGN KEY (user_id) REFERENCES users(id)
-    );
-    CREATE TABLE IF NOT EXISTS votes (
-      movie_id INTEGER,
-      user_id INTEGER,
-      FOREIGN KEY (movie_id) REFERENCES movies(id),
-      FOREIGN KEY (user_id) REFERENCES users(id)
-    );
-  `);
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/dbController/index.html b/coverage/lcov-report/dbController/index.html deleted file mode 100644 index 0cfee79..0000000 --- a/coverage/lcov-report/dbController/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for dbController - - - - - - - - - -
-
-

All files dbController

-
- -
- 100% - Statements - 9/9 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 9/9 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
database.ts -
-
100%8/8100%0/0100%2/2100%8/8
index.ts -
-
100%1/1100%0/0100%0/0100%1/1
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/dbController/index.ts.html b/coverage/lcov-report/dbController/index.ts.html deleted file mode 100644 index 5363b3d..0000000 --- a/coverage/lcov-report/dbController/index.ts.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - Code coverage report for dbController/index.ts - - - - - - - - - -
-
-

All files / dbController index.ts

-
- -
- 100% - Statements - 1/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 1/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -21x - 
export * from './database';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/errorHandler/CheckError.ts.html b/coverage/lcov-report/errorHandler/CheckError.ts.html deleted file mode 100644 index bcd362b..0000000 --- a/coverage/lcov-report/errorHandler/CheckError.ts.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - Code coverage report for errorHandler/CheckError.ts - - - - - - - - - -
-
-

All files / errorHandler CheckError.ts

-
- -
- 100% - Statements - 3/3 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 1/1 -
- - -
- 100% - Lines - 3/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -92x -  -15x -  -  -15x -  -  - 
export class CheckError extends Error {
-  constructor(msg: string) {
-    super(msg);
- 
-    // Set the prototype explicitly.
-    Object.setPrototypeOf(this, CheckError.prototype);
-  }
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/errorHandler/handleCheckErrors.ts.html b/coverage/lcov-report/errorHandler/handleCheckErrors.ts.html deleted file mode 100644 index 4f74679..0000000 --- a/coverage/lcov-report/errorHandler/handleCheckErrors.ts.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - Code coverage report for errorHandler/handleCheckErrors.ts - - - - - - - - - -
-
-

All files / errorHandler handleCheckErrors.ts

-
- -
- 100% - Statements - 11/11 -
- - -
- 100% - Branches - 2/2 -
- - -
- 100% - Functions - 4/4 -
- - -
- 100% - Lines - 10/10 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18  -2x -  -2x -2x -12x -30x -30x -30x -  -15x -14x -  -1x -  -  -  - 
import { THandler } from '../controllersTypes';
-import { CheckError } from './CheckError';
- 
-export const handleCheckErrors =
-  (handler: THandler): THandler =>
-  (bot) =>
-  async (msg, match) => {
-    try {
-      await handler(bot)(msg, match);
-    } catch (error) {
-      if (error instanceof CheckError) {
-        bot.sendMessage(msg.chat.id, error.message);
-      } else {
-        throw error;
-      }
-    }
-  };
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/errorHandler/index.html b/coverage/lcov-report/errorHandler/index.html deleted file mode 100644 index 2d15686..0000000 --- a/coverage/lcov-report/errorHandler/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - Code coverage report for errorHandler - - - - - - - - - -
-
-

All files errorHandler

-
- -
- 100% - Statements - 16/16 -
- - -
- 100% - Branches - 2/2 -
- - -
- 100% - Functions - 5/5 -
- - -
- 100% - Lines - 15/15 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
CheckError.ts -
-
100%3/3100%0/0100%1/1100%3/3
handleCheckErrors.ts -
-
100%11/11100%2/2100%4/4100%10/10
index.ts -
-
100%2/2100%0/0100%0/0100%2/2
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/errorHandler/index.ts.html b/coverage/lcov-report/errorHandler/index.ts.html deleted file mode 100644 index a001f0b..0000000 --- a/coverage/lcov-report/errorHandler/index.ts.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Code coverage report for errorHandler/index.ts - - - - - - - - - -
-
-

All files / errorHandler index.ts

-
- -
- 100% - Statements - 2/2 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 2/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -31x -1x - 
export * from './CheckError';
-export * from './handleCheckErrors';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/favicon.png b/coverage/lcov-report/favicon.png deleted file mode 100644 index c1525b811a167671e9de1fa78aab9f5c0b61cef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmV;u0Yd(XP))rP{nL}Ln%S7`m{0DjX9TLF* zFCb$4Oi7vyLOydb!7n&^ItCzb-%BoB`=x@N2jll2Nj`kauio%aw_@fe&*}LqlFT43 z8doAAe))z_%=P%v^@JHp3Hjhj^6*Kr_h|g_Gr?ZAa&y>wxHE99Gk>A)2MplWz2xdG zy8VD2J|Uf#EAw*bo5O*PO_}X2Tob{%bUoO2G~T`@%S6qPyc}VkhV}UifBuRk>%5v( z)x7B{I~z*k<7dv#5tC+m{km(D087J4O%+<<;K|qwefb6@GSX45wCK}Sn*> - - - - Code coverage report for helpers - - - - - - - - - -
-
-

All files helpers

-
- -
- 100% - Statements - 8/8 -
- - -
- 100% - Branches - 1/1 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 5/5 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
index.ts -
-
100%1/1100%0/0100%0/0100%1/1
log.ts -
-
100%7/7100%1/1100%2/2100%4/4
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/helpers/index.ts.html b/coverage/lcov-report/helpers/index.ts.html deleted file mode 100644 index 14bb4af..0000000 --- a/coverage/lcov-report/helpers/index.ts.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - Code coverage report for helpers/index.ts - - - - - - - - - -
-
-

All files / helpers index.ts

-
- -
- 100% - Statements - 1/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 1/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -22x - 
export * from './log';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/helpers/log.ts.html b/coverage/lcov-report/helpers/log.ts.html deleted file mode 100644 index 702834a..0000000 --- a/coverage/lcov-report/helpers/log.ts.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - Code coverage report for helpers/log.ts - - - - - - - - - -
-
-

All files / helpers log.ts

-
- -
- 100% - Statements - 7/7 -
- - -
- 100% - Branches - 1/1 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 4/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -84x -  -2x -4x -4x -  -  - 
export const green = (message: string) => `\x1b[32m${message}\x1b[0m`;
- 
-export const log = (message: string) => {
-  if (process.env.DEBUG_OUTPUT) {
-    console.log(green(`[DEBUG]: ${message}`));
-  }
-};
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html deleted file mode 100644 index ca7e5ea..0000000 --- a/coverage/lcov-report/index.html +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - Code coverage report for All files - - - - - - - - - -
-
-

All files

-
- -
- 99.22% - Statements - 255/257 -
- - -
- 82.45% - Branches - 47/57 -
- - -
- 100% - Functions - 76/76 -
- - -
- 99.11% - Lines - 224/226 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
controllers -
-
99.29%140/14183.33%30/36100%43/4399.18%122/123
dbController -
-
100%9/9100%0/0100%2/2100%9/9
helpers -
-
100%8/8100%1/1100%2/2100%5/5
middlewares -
-
100%10/10100%0/0100%3/3100%8/8
middlewares/errorHandler -
-
100%16/16100%2/2100%5/5100%13/13
middlewares/logger -
-
100%11/11100%5/5100%4/4100%7/7
models -
-
100%3/3100%0/0100%0/0100%3/3
models/group -
-
100%13/13100%0/0100%3/3100%13/13
models/movie -
-
97.22%35/3669.23%9/13100%12/1297.14%34/35
models/user -
-
100%10/10100%0/0100%2/2100%10/10
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/applyMiddlewares.ts.html b/coverage/lcov-report/middlewares/applyMiddlewares.ts.html deleted file mode 100644 index 14cf1e7..0000000 --- a/coverage/lcov-report/middlewares/applyMiddlewares.ts.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - Code coverage report for middlewares/applyMiddlewares.ts - - - - - - - - - -
-
-

All files / middlewares applyMiddlewares.ts

-
- -
- 100% - Statements - 5/5 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 3/3 -
- - -
- 100% - Lines - 3/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11  -  -1x -  -  -  -10x -  -20x -  - 
import { TMiddleware, TRule } from './controllers.types';
- 
-export const applyMiddlewares = (
-  rules: TRule[],
-  middlewares: TMiddleware[],
-): TRule[] =>
-  rules.map(([regexp, handler]: TRule) => [
-    regexp,
-    middlewares.reduce((acc, mw) => mw(acc), handler),
-  ]);
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/controllers.types.ts.html b/coverage/lcov-report/middlewares/controllers.types.ts.html deleted file mode 100644 index 2c0c421..0000000 --- a/coverage/lcov-report/middlewares/controllers.types.ts.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - Code coverage report for middlewares/controllers.types.ts - - - - - - - - - -
-
-

All files / middlewares controllers.types.ts

-
- -
- 100% - Statements - 1/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 1/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14  -  -  -1x -  -  -  -  -  -  -  -  -  - 
// Fix for error: node-telegram-bot-api
-// deprecated Automatic enabling of cancellation
-// of promises is deprecated In the future
-process.env.NTBA_FIX_319 = '1';
-import TelegramBot from 'node-telegram-bot-api';
- 
-export type THandler = (
-  bot: TelegramBot,
-) => (msg: TelegramBot.Message, match: string[] | null) => Promise<void>;
- 
-export type TRule = [RegExp, THandler];
- 
-export type TMiddleware = (handler: THandler) => THandler;
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/CheckError.ts.html b/coverage/lcov-report/middlewares/errorHandler/CheckError.ts.html deleted file mode 100644 index a364071..0000000 --- a/coverage/lcov-report/middlewares/errorHandler/CheckError.ts.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - Code coverage report for middlewares/errorHandler/CheckError.ts - - - - - - - - - -
-
-

All files / middlewares/errorHandler CheckError.ts

-
- -
- 100% - Statements - 3/3 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 1/1 -
- - -
- 100% - Lines - 3/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -92x -  -15x -  -  -15x -  -  - 
export class CheckError extends Error {
-  constructor(msg: string) {
-    super(msg);
- 
-    // Set the prototype explicitly.
-    Object.setPrototypeOf(this, CheckError.prototype);
-  }
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/handleCheckErrors.ts.html b/coverage/lcov-report/middlewares/errorHandler/handleCheckErrors.ts.html deleted file mode 100644 index fd688a0..0000000 --- a/coverage/lcov-report/middlewares/errorHandler/handleCheckErrors.ts.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - Code coverage report for middlewares/errorHandler/handleCheckErrors.ts - - - - - - - - - -
-
-

All files / middlewares/errorHandler handleCheckErrors.ts

-
- -
- 100% - Statements - 11/11 -
- - -
- 100% - Branches - 2/2 -
- - -
- 100% - Functions - 4/4 -
- - -
- 100% - Lines - 8/8 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16  -2x -  -2x -31x -31x -31x -  -16x -15x -  -1x -  -  -  - 
import { TMiddleware } from '../controllers.types';
-import { CheckError } from './CheckError';
- 
-export const handleCheckErrors: TMiddleware =
-  (handler) => (bot) => async (msg, match) => {
-    try {
-      await handler(bot)(msg, match);
-    } catch (error) {
-      if (error instanceof CheckError) {
-        bot.sendMessage(msg.chat.id, error.message);
-      } else {
-        throw error;
-      }
-    }
-  };
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/index.html b/coverage/lcov-report/middlewares/errorHandler/index.html deleted file mode 100644 index fdc4405..0000000 --- a/coverage/lcov-report/middlewares/errorHandler/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - Code coverage report for middlewares/errorHandler - - - - - - - - - -
-
-

All files middlewares/errorHandler

-
- -
- 100% - Statements - 16/16 -
- - -
- 100% - Branches - 2/2 -
- - -
- 100% - Functions - 5/5 -
- - -
- 100% - Lines - 13/13 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
CheckError.ts -
-
100%3/3100%0/0100%1/1100%3/3
handleCheckErrors.ts -
-
100%11/11100%2/2100%4/4100%8/8
index.ts -
-
100%2/2100%0/0100%0/0100%2/2
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/errorHandler/index.ts.html b/coverage/lcov-report/middlewares/errorHandler/index.ts.html deleted file mode 100644 index a689fe7..0000000 --- a/coverage/lcov-report/middlewares/errorHandler/index.ts.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Code coverage report for middlewares/errorHandler/index.ts - - - - - - - - - -
-
-

All files / middlewares/errorHandler index.ts

-
- -
- 100% - Statements - 2/2 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 2/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -31x -1x - 
export * from './CheckError';
-export * from './handleCheckErrors';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/index.html b/coverage/lcov-report/middlewares/index.html deleted file mode 100644 index b629705..0000000 --- a/coverage/lcov-report/middlewares/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - Code coverage report for middlewares - - - - - - - - - -
-
-

All files middlewares

-
- -
- 100% - Statements - 10/10 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 3/3 -
- - -
- 100% - Lines - 8/8 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
applyMiddlewares.ts -
-
100%5/5100%0/0100%3/3100%3/3
controllers.types.ts -
-
100%1/1100%0/0100%0/0100%1/1
index.ts -
-
100%4/4100%0/0100%0/0100%4/4
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/index.ts.html b/coverage/lcov-report/middlewares/index.ts.html deleted file mode 100644 index 7b9b0e3..0000000 --- a/coverage/lcov-report/middlewares/index.ts.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Code coverage report for middlewares/index.ts - - - - - - - - - -
-
-

All files / middlewares index.ts

-
- -
- 100% - Statements - 4/4 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 4/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -51x -1x -1x -1x - 
export * from './errorHandler';
-export * from './logger';
-export * from './applyMiddlewares';
-export * from './controllers.types';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/logger/index.html b/coverage/lcov-report/middlewares/logger/index.html deleted file mode 100644 index 3e95d66..0000000 --- a/coverage/lcov-report/middlewares/logger/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for middlewares/logger - - - - - - - - - -
-
-

All files middlewares/logger

-
- -
- 100% - Statements - 11/11 -
- - -
- 100% - Branches - 5/5 -
- - -
- 100% - Functions - 4/4 -
- - -
- 100% - Lines - 7/7 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
index.ts -
-
100%1/1100%0/0100%0/0100%1/1
logger.ts -
-
100%10/10100%5/5100%4/4100%6/6
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/logger/index.ts.html b/coverage/lcov-report/middlewares/logger/index.ts.html deleted file mode 100644 index 38bc782..0000000 --- a/coverage/lcov-report/middlewares/logger/index.ts.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - Code coverage report for middlewares/logger/index.ts - - - - - - - - - -
-
-

All files / middlewares/logger index.ts

-
- -
- 100% - Statements - 1/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 1/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -21x - 
export * from './logger';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/middlewares/logger/logger.ts.html b/coverage/lcov-report/middlewares/logger/logger.ts.html deleted file mode 100644 index 86cb587..0000000 --- a/coverage/lcov-report/middlewares/logger/logger.ts.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - Code coverage report for middlewares/logger/logger.ts - - - - - - - - - -
-
-

All files / middlewares/logger logger.ts

-
- -
- 100% - Statements - 10/10 -
- - -
- 100% - Branches - 5/5 -
- - -
- 100% - Functions - 4/4 -
- - -
- 100% - Lines - 6/6 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -122x -  -  -30x -30x -2x -2x -  -  -30x -  - 
import { log } from '../../helpers';
-import { TMiddleware } from '../controllers.types';
- 
-export const logger: TMiddleware = (handler) => (bot) => async (msg, match) => {
-  if (process.env.DEBUG_OUTPUT === '1') {
-    log(`User: ${msg.from?.username}, Message: ${msg.text}`);
-    log(`DB(Movies): `);
-  }
- 
-  await handler(bot)(msg, match);
-};
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/group/index.html b/coverage/lcov-report/models/group/index.html deleted file mode 100644 index 98fcbeb..0000000 --- a/coverage/lcov-report/models/group/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for models/group - - - - - - - - - -
-
-

All files models/group

-
- -
- 100% - Statements - 13/13 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 3/3 -
- - -
- 100% - Lines - 13/13 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
index.ts -
-
100%2/2100%0/0100%0/0100%2/2
model.ts -
-
100%11/11100%0/0100%3/3100%11/11
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/group/index.ts.html b/coverage/lcov-report/models/group/index.ts.html deleted file mode 100644 index bd240df..0000000 --- a/coverage/lcov-report/models/group/index.ts.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Code coverage report for models/group/index.ts - - - - - - - - - -
-
-

All files / models/group index.ts

-
- -
- 100% - Statements - 2/2 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 2/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -31x -1x - 
export * from './model';
-export * from './types';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/group/model.ts.html b/coverage/lcov-report/models/group/model.ts.html deleted file mode 100644 index 2484034..0000000 --- a/coverage/lcov-report/models/group/model.ts.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - Code coverage report for models/group/model.ts - - - - - - - - - -
-
-

All files / models/group model.ts

-
- -
- 100% - Statements - 11/11 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 3/3 -
- - -
- 100% - Lines - 11/11 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -281x -  -  -  -1x -16x -16x -16x -  -  -  -  -  -1x -  -  -20x -20x -  -  -1x -15x -15x -  -  -  -  - 
import { openDb } from '../../dbController';
-import { TId } from '../types';
-import { IGroup } from './types';
- 
-export async function createGroup(code: string): Promise<IGroup> {
-  const db = await openDb();
-  const res = await db.run(`INSERT INTO groups (code) VALUES (?)`, [code]);
-  return {
-    id: res.lastID,
-    code,
-  } as IGroup;
-}
- 
-export async function findGroupByCode(
-  code: string,
-): Promise<IGroup | undefined> {
-  const db = await openDb();
-  return db.get(`SELECT * FROM groups WHERE code = ?`, [code]);
-}
- 
-export async function addUserToGroup(groupId: TId, userId: TId) {
-  const db = await openDb();
-  await db.run(`INSERT INTO group_users (group_id, user_id) VALUES (?, ?)`, [
-    groupId,
-    userId,
-  ]);
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/index.html b/coverage/lcov-report/models/index.html deleted file mode 100644 index fc6a32e..0000000 --- a/coverage/lcov-report/models/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for models - - - - - - - - - -
-
-

All files models

-
- -
- 100% - Statements - 3/3 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 3/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
index.ts -
-
100%3/3100%0/0100%0/0100%3/3
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/index.ts.html b/coverage/lcov-report/models/index.ts.html deleted file mode 100644 index 80f03e2..0000000 --- a/coverage/lcov-report/models/index.ts.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - Code coverage report for models/index.ts - - - - - - - - - -
-
-

All files / models index.ts

-
- -
- 100% - Statements - 3/3 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 3/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -41x -1x -1x - 
export * from './group';
-export * from './movie';
-export * from './user';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/movie/index.html b/coverage/lcov-report/models/movie/index.html deleted file mode 100644 index 53a68b3..0000000 --- a/coverage/lcov-report/models/movie/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for models/movie - - - - - - - - - -
-
-

All files models/movie

-
- -
- 97.22% - Statements - 35/36 -
- - -
- 69.23% - Branches - 9/13 -
- - -
- 100% - Functions - 12/12 -
- - -
- 97.14% - Lines - 34/35 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
index.ts -
-
100%2/2100%0/0100%0/0100%2/2
model.ts -
-
97.05%33/3469.23%9/13100%12/1296.96%32/33
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/movie/index.ts.html b/coverage/lcov-report/models/movie/index.ts.html deleted file mode 100644 index c835a1e..0000000 --- a/coverage/lcov-report/models/movie/index.ts.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Code coverage report for models/movie/index.ts - - - - - - - - - -
-
-

All files / models/movie index.ts

-
- -
- 100% - Statements - 2/2 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 2/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -31x -1x - 
export * from './model';
-export * from './types';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/movie/model.ts.html b/coverage/lcov-report/models/movie/model.ts.html deleted file mode 100644 index be77a20..0000000 --- a/coverage/lcov-report/models/movie/model.ts.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - Code coverage report for models/movie/model.ts - - - - - - - - - -
-
-

All files / models/movie model.ts

-
- -
- 97.05% - Statements - 33/34 -
- - -
- 69.23% - Branches - 9/13 -
- - -
- 100% - Functions - 12/12 -
- - -
- 96.96% - Lines - 32/33 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -1051x -  -  -  -1x -  -  -  -  -  -  -7x -7x -  -  -  -  -7x -  -  -7x -  -  -  -  -  -  -  -  -7x -  -  -  -18x -18x -  -  -  -18x -  -  -1x -  -  -  -3x -3x -  -  -  -3x -  -  -  -  -  -22x -  -  -1x -  -  -  -19x -19x -  -  -  -  -  -  -  -1x -2x -2x -  -  -  -  -  -1x -5x -5x -  -  -5x -  -  -5x -  -  -  -1x -1x -1x -  -  -  -  -  -1x -1x -1x -  - 
import { openDb } from '../../dbController';
-import { TId } from '../types';
-import { IMovie } from './types';
- 
-export async function suggestMovie(
-  name: string,
-  suggestedBy: number,
-  groupId: TId,
-  kinopoiskLink: string,
-  imdbLink: string,
-): Promise<IMovie> {
-  const db = await openDb();
-  const res = await db.run(
-    `INSERT INTO movies (name, suggested_by, group_id, kinopoisk_link, imdb_link) VALUES (?, ?, ?, ?, ?)`,
-    [name, suggestedBy, groupId, kinopoiskLink, imdbLink],
-  );
-  const movie =
-    res?.lastID !== undefined
-      ? await findMovieById(res.lastID, groupId)
-      : undefined;
-  Iif (!movie) {
-    throw new Error(
-      `Failed to insert movie: ${JSON.stringify({
-        name,
-        suggestedBy,
-        groupId,
-      })}`,
-    );
-  }
-  return movie;
-}
- 
-async function calcMovieVotes(movieId: TId): Promise<number> {
-  const db = await openDb();
-  const votes = await db.all(
-    `SELECT COUNT(*) AS vote_count FROM votes WHERE movie_id = ?`,
-    [movieId],
-  );
-  return votes[0].vote_count ?? 0;
-}
- 
-export async function hasUserMovieVote(
-  userId: TId,
-  movieId: TId,
-): Promise<boolean> {
-  const db = await openDb();
-  const res = await db.get(
-    `SELECT * FROM votes WHERE movie_id = ? AND user_id = ?`,
-    [movieId, userId],
-  );
-  return !!res;
-}
- 
-async function mapMovie(
-  row?: Omit<IMovie, 'votes'>,
-): Promise<IMovie | undefined> {
-  return row && { ...row, votes: await calcMovieVotes(row.id) };
-}
- 
-export async function findMovieById(
-  movieId: TId,
-  groupId: TId,
-): Promise<IMovie | undefined> {
-  const db = await openDb();
-  return db
-    .get(`SELECT * FROM movies WHERE id = ? AND group_id = ?`, [
-      movieId,
-      groupId,
-    ])
-    .then(mapMovie);
-}
- 
-export async function voteForMovie(movieId: TId, userId: TId) {
-  const db = await openDb();
-  await db.run(`INSERT INTO votes (movie_id, user_id) VALUES (?, ?)`, [
-    movieId,
-    userId,
-  ]);
-}
- 
-export async function listMovies(groupId: TId): Promise<IMovie[] | undefined> {
-  const db = await openDb();
-  return db
-    .all(`SELECT * FROM movies WHERE group_id = ?`, [groupId])
-    .then((rows: (Omit<IMovie, 'votes'> | undefined)[]) =>
-      Promise.all(rows.map(mapMovie)),
-    )
-    .then((movies: (IMovie | undefined)[]) =>
-      movies.filter((row): row is IMovie => !!row),
-    );
-}
- 
-export async function markMovieAsWatched(movieId: TId, groupId: TId) {
-  const db = await openDb();
-  await db.run(`DELETE FROM movies WHERE id = ? AND group_id = ?`, [
-    movieId,
-    groupId,
-  ]);
-}
- 
-export async function markMovieAsVetoed(movieId: TId) {
-  const db = await openDb();
-  await db.run(`UPDATE movies SET is_vetoed = 1 WHERE id = ?`, [movieId]);
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/movies/index.html b/coverage/lcov-report/models/movies/index.html deleted file mode 100644 index bbc9e99..0000000 --- a/coverage/lcov-report/models/movies/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for models/movies - - - - - - - - - -
-
-

All files models/movies

-
- -
- 100% - Statements - 50/50 -
- - -
- 75% - Branches - 9/12 -
- - -
- 100% - Functions - 17/17 -
- - -
- 100% - Lines - 49/49 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
index.ts -
-
100%2/2100%0/0100%0/0100%2/2
model.ts -
-
100%48/4875%9/12100%17/17100%47/47
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/movies/index.ts.html b/coverage/lcov-report/models/movies/index.ts.html deleted file mode 100644 index 35be592..0000000 --- a/coverage/lcov-report/models/movies/index.ts.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Code coverage report for models/movies/index.ts - - - - - - - - - -
-
-

All files / models/movies index.ts

-
- -
- 100% - Statements - 2/2 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 2/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -31x -1x - 
export * from './model';
-export * from './types';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/movies/model.ts.html b/coverage/lcov-report/models/movies/model.ts.html deleted file mode 100644 index c3aa4a2..0000000 --- a/coverage/lcov-report/models/movies/model.ts.html +++ /dev/null @@ -1,469 +0,0 @@ - - - - - - Code coverage report for models/movies/model.ts - - - - - - - - - -
-
-

All files / models/movies model.ts

-
- -
- 100% - Statements - 48/48 -
- - -
- 75% - Branches - 9/12 -
- - -
- 100% - Functions - 17/17 -
- - -
- 100% - Lines - 47/47 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -1291x -  -  -1x -16x -16x -16x -  -  -  -  -  -1x -  -  -20x -20x -  -  -1x -19x -19x -  -  -  -19x -  -  -1x -15x -15x -  -  -  -  -  -1x -  -  -  -  -  -  -7x -7x -  -  -  -7x -  -  -  -  -  -18x -18x -  -  -  -18x -  -  -1x -  -  -  -3x -3x -  -  -  -3x -  -  -  -  -  -22x -  -  -1x -  -  -  -19x -19x -  -  -  -  -  -  -  -1x -2x -2x -  -  -  -  -  -1x -5x -5x -  -5x -5x -  -  -1x -1x -1x -  -  -  -  -  -1x -1x -1x -  -  -1x -  -  -9x -9x -  - 
import { openDb } from '../../dbController';
-import { IGroup, IMovie, IUser, TId } from './types';
- 
-export async function createGroup(code: string): Promise<IGroup> {
-  const db = await openDb();
-  const res = await db.run(`INSERT INTO groups (code) VALUES (?)`, [code]);
-  return {
-    id: res.lastID as TId,
-    code,
-  };
-}
- 
-export async function findGroupByCode(
-  code: string,
-): Promise<IGroup | undefined> {
-  const db = await openDb();
-  return db.get(`SELECT * FROM groups WHERE code = ?`, [code]);
-}
- 
-export async function createUser(username: string): Promise<IUser | undefined> {
-  const db = await openDb();
-  const res = await db.run(
-    `INSERT OR IGNORE INTO users (username) VALUES (?)`,
-    [username],
-  );
-  return { id: res.lastID as TId, username };
-}
- 
-export async function addUserToGroup(groupId: TId, userId: TId) {
-  const db = await openDb();
-  await db.run(`INSERT INTO group_users (group_id, user_id) VALUES (?, ?)`, [
-    groupId,
-    userId,
-  ]);
-}
- 
-export async function suggestMovie(
-  name: string,
-  suggestedBy: number,
-  groupId: TId,
-  kinopoiskLink: string,
-  imdbLink: string,
-): Promise<IMovie | undefined> {
-  const db = await openDb();
-  const res = await db.run(
-    `INSERT INTO movies (name, suggested_by, group_id, kinopoisk_link, imdb_link) VALUES (?, ?, ?, ?, ?)`,
-    [name, suggestedBy, groupId, kinopoiskLink, imdbLink],
-  );
-  return res?.lastID !== undefined
-    ? findMovieById(res.lastID, groupId)
-    : undefined;
-}
- 
-async function calcMovieVotes(movieId: TId): Promise<number> {
-  const db = await openDb();
-  const votes = await db.all(
-    `SELECT COUNT(*) AS vote_count FROM votes WHERE movie_id = ?`,
-    [movieId],
-  );
-  return votes[0].vote_count ?? 0;
-}
- 
-export async function hasUserMovieVote(
-  userId: TId,
-  movieId: TId,
-): Promise<boolean> {
-  const db = await openDb();
-  const res = await db.get(
-    `SELECT * FROM votes WHERE movie_id = ? AND user_id = ?`,
-    [movieId, userId],
-  );
-  return !!res;
-}
- 
-async function mapMovie(
-  row?: Omit<IMovie, 'votes'>,
-): Promise<IMovie | undefined> {
-  return row && { ...row, votes: await calcMovieVotes(row.id) };
-}
- 
-export async function findMovieById(
-  movieId: TId,
-  groupId: TId,
-): Promise<IMovie | undefined> {
-  const db = await openDb();
-  return db
-    .get(`SELECT * FROM movies WHERE id = ? AND group_id = ?`, [
-      movieId,
-      groupId,
-    ])
-    .then(mapMovie);
-}
- 
-export async function voteForMovie(movieId: TId, userId: TId) {
-  const db = await openDb();
-  await db.run(`INSERT INTO votes (movie_id, user_id) VALUES (?, ?)`, [
-    movieId,
-    userId,
-  ]);
-}
- 
-export async function listMovies(groupId: TId): Promise<IMovie[] | undefined> {
-  const db = await openDb();
-  return db
-    .all(`SELECT * FROM movies WHERE group_id = ?`, [groupId])
-    .then((rows) => Promise.all(rows.map(mapMovie)))
-    .then((movies) => movies.filter((row): row is IMovie => !!row));
-}
- 
-export async function markMovieAsWatched(movieId: TId, groupId: TId) {
-  const db = await openDb();
-  await db.run(`DELETE FROM movies WHERE id = ? AND group_id = ?`, [
-    movieId,
-    groupId,
-  ]);
-}
- 
-export async function markMovieAsVetoed(movieId: TId) {
-  const db = await openDb();
-  await db.run(`UPDATE movies SET is_vetoed = 1 WHERE id = ?`, [movieId]);
-}
- 
-export async function findUserByUsername(
-  username: string,
-): Promise<IUser | undefined> {
-  const db = await openDb();
-  return db.get(`SELECT * FROM users WHERE username = ?`, [username]);
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/user/index.html b/coverage/lcov-report/models/user/index.html deleted file mode 100644 index 05b75de..0000000 --- a/coverage/lcov-report/models/user/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for models/user - - - - - - - - - -
-
-

All files models/user

-
- -
- 100% - Statements - 10/10 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 10/10 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
index.ts -
-
100%2/2100%0/0100%0/0100%2/2
model.ts -
-
100%8/8100%0/0100%2/2100%8/8
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/user/index.ts.html b/coverage/lcov-report/models/user/index.ts.html deleted file mode 100644 index db3e157..0000000 --- a/coverage/lcov-report/models/user/index.ts.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Code coverage report for models/user/index.ts - - - - - - - - - -
-
-

All files / models/user index.ts

-
- -
- 100% - Statements - 2/2 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 100% - Lines - 2/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -31x -1x - 
export * from './model';
-export * from './types';
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/models/user/model.ts.html b/coverage/lcov-report/models/user/model.ts.html deleted file mode 100644 index ba18b50..0000000 --- a/coverage/lcov-report/models/user/model.ts.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - Code coverage report for models/user/model.ts - - - - - - - - - -
-
-

All files / models/user model.ts

-
- -
- 100% - Statements - 8/8 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 8/8 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -201x -  -  -  -1x -19x -19x -  -  -  -19x -  -  -1x -  -  -9x -9x -  - 
import { openDb } from '../../dbController';
-import { TId } from '../types';
-import { IUser } from './types';
- 
-export async function createUser(username: string): Promise<IUser | undefined> {
-  const db = await openDb();
-  const res = await db.run(
-    `INSERT OR IGNORE INTO users (username) VALUES (?)`,
-    [username],
-  );
-  return { id: res.lastID as TId, username };
-}
- 
-export async function findUserByUsername(
-  username: string,
-): Promise<IUser | undefined> {
-  const db = await openDb();
-  return db.get(`SELECT * FROM users WHERE username = ?`, [username]);
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css deleted file mode 100644 index b317a7c..0000000 --- a/coverage/lcov-report/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js deleted file mode 100644 index b322523..0000000 --- a/coverage/lcov-report/prettify.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable */ -window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/lcov-report/sort-arrow-sprite.png b/coverage/lcov-report/sort-arrow-sprite.png deleted file mode 100644 index 6ed68316eb3f65dec9063332d2f69bf3093bbfab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qh}Z>jv*C{$p!i!8j}?a+@3A= zIAGwzjijN=FBi!|L1t?LM;Q;gkwn>2cAy-KV{dn nf0J1DIvEHQu*n~6U}x}qyky7vi4|9XhBJ7&`njxgN@xNA8m%nc diff --git a/coverage/lcov-report/sorter.js b/coverage/lcov-report/sorter.js deleted file mode 100644 index 2bb296a..0000000 --- a/coverage/lcov-report/sorter.js +++ /dev/null @@ -1,196 +0,0 @@ -/* eslint-disable */ -var addSorting = (function() { - 'use strict'; - var cols, - currentSort = { - index: 0, - desc: false - }; - - // returns the summary table element - function getTable() { - return document.querySelector('.coverage-summary'); - } - // returns the thead element of the summary table - function getTableHeader() { - return getTable().querySelector('thead tr'); - } - // returns the tbody element of the summary table - function getTableBody() { - return getTable().querySelector('tbody'); - } - // returns the th element for nth column - function getNthColumn(n) { - return getTableHeader().querySelectorAll('th')[n]; - } - - function onFilterInput() { - const searchValue = document.getElementById('fileSearch').value; - const rows = document.getElementsByTagName('tbody')[0].children; - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - if ( - row.textContent - .toLowerCase() - .includes(searchValue.toLowerCase()) - ) { - row.style.display = ''; - } else { - row.style.display = 'none'; - } - } - } - - // loads the search box - function addSearchBox() { - var template = document.getElementById('filterTemplate'); - var templateClone = template.content.cloneNode(true); - templateClone.getElementById('fileSearch').oninput = onFilterInput; - template.parentElement.appendChild(templateClone); - } - - // loads all columns - function loadColumns() { - var colNodes = getTableHeader().querySelectorAll('th'), - colNode, - cols = [], - col, - i; - - for (i = 0; i < colNodes.length; i += 1) { - colNode = colNodes[i]; - col = { - key: colNode.getAttribute('data-col'), - sortable: !colNode.getAttribute('data-nosort'), - type: colNode.getAttribute('data-type') || 'string' - }; - cols.push(col); - if (col.sortable) { - col.defaultDescSort = col.type === 'number'; - colNode.innerHTML = - colNode.innerHTML + ''; - } - } - return cols; - } - // attaches a data attribute to every tr element with an object - // of data values keyed by column name - function loadRowData(tableRow) { - var tableCols = tableRow.querySelectorAll('td'), - colNode, - col, - data = {}, - i, - val; - for (i = 0; i < tableCols.length; i += 1) { - colNode = tableCols[i]; - col = cols[i]; - val = colNode.getAttribute('data-value'); - if (col.type === 'number') { - val = Number(val); - } - data[col.key] = val; - } - return data; - } - // loads all row data - function loadData() { - var rows = getTableBody().querySelectorAll('tr'), - i; - - for (i = 0; i < rows.length; i += 1) { - rows[i].data = loadRowData(rows[i]); - } - } - // sorts the table using the data for the ith column - function sortByIndex(index, desc) { - var key = cols[index].key, - sorter = function(a, b) { - a = a.data[key]; - b = b.data[key]; - return a < b ? -1 : a > b ? 1 : 0; - }, - finalSorter = sorter, - tableBody = document.querySelector('.coverage-summary tbody'), - rowNodes = tableBody.querySelectorAll('tr'), - rows = [], - i; - - if (desc) { - finalSorter = function(a, b) { - return -1 * sorter(a, b); - }; - } - - for (i = 0; i < rowNodes.length; i += 1) { - rows.push(rowNodes[i]); - tableBody.removeChild(rowNodes[i]); - } - - rows.sort(finalSorter); - - for (i = 0; i < rows.length; i += 1) { - tableBody.appendChild(rows[i]); - } - } - // removes sort indicators for current column being sorted - function removeSortIndicators() { - var col = getNthColumn(currentSort.index), - cls = col.className; - - cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); - col.className = cls; - } - // adds sort indicators for current column being sorted - function addSortIndicators() { - getNthColumn(currentSort.index).className += currentSort.desc - ? ' sorted-desc' - : ' sorted'; - } - // adds event listeners for all sorter widgets - function enableUI() { - var i, - el, - ithSorter = function ithSorter(i) { - var col = cols[i]; - - return function() { - var desc = col.defaultDescSort; - - if (currentSort.index === i) { - desc = !currentSort.desc; - } - sortByIndex(i, desc); - removeSortIndicators(); - currentSort.index = i; - currentSort.desc = desc; - addSortIndicators(); - }; - }; - for (i = 0; i < cols.length; i += 1) { - if (cols[i].sortable) { - // add the click event handler on the th so users - // dont have to click on those tiny arrows - el = getNthColumn(i).querySelector('.sorter').parentElement; - if (el.addEventListener) { - el.addEventListener('click', ithSorter(i)); - } else { - el.attachEvent('onclick', ithSorter(i)); - } - } - } - } - // adds sorting functionality to the UI - return function() { - if (!getTable()) { - return; - } - cols = loadColumns(); - loadData(); - addSearchBox(); - addSortIndicators(); - enableUI(); - }; -})(); - -window.addEventListener('load', addSorting); diff --git a/coverage/lcov.info b/coverage/lcov.info deleted file mode 100644 index bf1e969..0000000 --- a/coverage/lcov.info +++ /dev/null @@ -1,633 +0,0 @@ -TN: -SF:src/controllers/bot.ts -FN:43,(anonymous_8) -FN:43,(anonymous_9) -FN:43,(anonymous_10) -FN:56,(anonymous_11) -FN:56,(anonymous_12) -FN:56,(anonymous_13) -FN:62,(anonymous_14) -FN:62,(anonymous_15) -FN:62,(anonymous_16) -FN:75,(anonymous_17) -FN:75,(anonymous_18) -FN:75,(anonymous_19) -FN:91,(anonymous_20) -FN:91,(anonymous_21) -FN:91,(anonymous_22) -FN:114,(anonymous_23) -FN:114,(anonymous_24) -FN:114,(anonymous_25) -FN:136,(anonymous_26) -FN:136,(anonymous_27) -FN:136,(anonymous_28) -FN:149,(anonymous_29) -FN:149,(anonymous_30) -FN:149,(anonymous_31) -FN:165,(anonymous_32) -FN:165,(anonymous_33) -FN:165,(anonymous_34) -FN:181,(anonymous_35) -FN:181,(anonymous_36) -FN:181,(anonymous_37) -FN:186,(anonymous_38) -FNF:31 -FNH:31 -FNDA:1,(anonymous_8) -FNDA:1,(anonymous_9) -FNDA:1,(anonymous_10) -FNDA:1,(anonymous_11) -FNDA:1,(anonymous_12) -FNDA:1,(anonymous_13) -FNDA:2,(anonymous_14) -FNDA:2,(anonymous_15) -FNDA:2,(anonymous_16) -FNDA:4,(anonymous_17) -FNDA:4,(anonymous_18) -FNDA:4,(anonymous_19) -FNDA:3,(anonymous_20) -FNDA:3,(anonymous_21) -FNDA:3,(anonymous_22) -FNDA:5,(anonymous_23) -FNDA:5,(anonymous_24) -FNDA:5,(anonymous_25) -FNDA:2,(anonymous_26) -FNDA:2,(anonymous_27) -FNDA:2,(anonymous_28) -FNDA:4,(anonymous_29) -FNDA:4,(anonymous_30) -FNDA:4,(anonymous_31) -FNDA:3,(anonymous_32) -FNDA:3,(anonymous_33) -FNDA:3,(anonymous_34) -FNDA:3,(anonymous_35) -FNDA:3,(anonymous_36) -FNDA:3,(anonymous_37) -FNDA:1,(anonymous_38) -DA:4,1 -DA:6,1 -DA:18,1 -DA:19,1 -DA:20,1 -DA:27,1 -DA:35,1 -DA:40,1 -DA:43,1 -DA:44,1 -DA:46,1 -DA:47,1 -DA:48,1 -DA:51,1 -DA:56,1 -DA:57,1 -DA:62,2 -DA:63,2 -DA:64,2 -DA:65,2 -DA:66,1 -DA:67,1 -DA:69,1 -DA:70,1 -DA:75,4 -DA:76,4 -DA:77,4 -DA:78,3 -DA:80,2 -DA:81,2 -DA:82,1 -DA:83,1 -DA:85,1 -DA:86,1 -DA:91,3 -DA:92,3 -DA:93,3 -DA:95,2 -DA:96,1 -DA:98,1 -DA:105,1 -DA:114,5 -DA:115,5 -DA:116,5 -DA:121,4 -DA:122,4 -DA:123,4 -DA:125,3 -DA:126,1 -DA:127,1 -DA:130,2 -DA:131,2 -DA:136,2 -DA:137,2 -DA:139,2 -DA:140,1 -DA:143,1 -DA:144,1 -DA:149,4 -DA:150,4 -DA:151,4 -DA:156,3 -DA:157,2 -DA:159,1 -DA:160,1 -DA:165,3 -DA:166,3 -DA:167,3 -DA:172,2 -DA:173,2 -DA:175,1 -DA:176,1 -DA:181,3 -DA:182,3 -DA:184,3 -DA:185,2 -DA:186,1 -DA:189,1 -DA:190,1 -DA:195,1 -LF:80 -LH:80 -BRDA:44,0,0,0 -BRDA:44,0,1,1 -BRDA:44,1,0,1 -BRDA:44,1,1,1 -BRDA:46,2,0,1 -BRDA:46,2,1,0 -BRDA:46,3,0,1 -BRDA:46,3,1,1 -BRDA:47,4,0,1 -BRDA:48,5,0,1 -BRDA:48,5,1,0 -BRDA:48,6,0,1 -BRDA:48,6,1,1 -BRDA:48,7,0,0 -BRDA:48,7,1,1 -BRDA:48,8,0,1 -BRDA:48,8,1,1 -BRDA:65,9,0,1 -BRDA:81,10,0,1 -BRDA:125,11,0,1 -BRF:20 -BRH:16 -end_of_record -TN: -SF:src/controllers/checkers.ts -FN:18,(anonymous_8) -FN:20,(anonymous_9) -FN:33,(anonymous_10) -FN:35,(anonymous_11) -FN:45,(anonymous_12) -FN:55,(anonymous_13) -FN:58,(anonymous_14) -FN:67,(anonymous_15) -FN:69,(anonymous_16) -FNF:9 -FNH:9 -FNDA:9,(anonymous_8) -FNDA:9,(anonymous_9) -FNDA:15,(anonymous_10) -FNDA:15,(anonymous_11) -FNDA:19,(anonymous_12) -FNDA:8,(anonymous_13) -FNDA:8,(anonymous_14) -FNDA:3,(anonymous_15) -FNDA:3,(anonymous_16) -DA:4,1 -DA:6,1 -DA:7,1 -DA:8,1 -DA:18,1 -DA:20,9 -DA:21,9 -DA:23,9 -DA:24,2 -DA:26,7 -DA:27,7 -DA:28,0 -DA:30,7 -DA:33,1 -DA:35,15 -DA:36,15 -DA:37,15 -DA:39,15 -DA:40,3 -DA:42,12 -DA:45,1 -DA:49,19 -DA:50,5 -DA:52,14 -DA:55,1 -DA:58,8 -DA:59,8 -DA:61,8 -DA:62,3 -DA:64,5 -DA:67,1 -DA:69,3 -DA:70,3 -DA:71,3 -DA:72,1 -DA:75,2 -LF:36 -LH:35 -BRDA:21,0,0,1 -BRDA:21,0,1,8 -BRDA:21,1,0,9 -BRDA:21,1,1,9 -BRDA:23,2,0,2 -BRDA:27,3,0,0 -BRDA:39,4,0,3 -BRDA:49,5,0,5 -BRDA:49,6,0,0 -BRDA:49,6,1,19 -BRDA:49,7,0,19 -BRDA:49,7,1,19 -BRDA:61,8,0,3 -BRDA:71,9,0,1 -BRDA:71,10,0,3 -BRDA:71,10,1,3 -BRF:16 -BRH:14 -end_of_record -TN: -SF:src/controllers/helpers.ts -FN:4,(anonymous_0) -FN:7,(anonymous_1) -FN:10,(anonymous_2) -FNF:3 -FNH:3 -FNDA:1,(anonymous_0) -FNDA:1,(anonymous_1) -FNDA:3,(anonymous_2) -DA:1,1 -DA:4,1 -DA:5,1 -DA:7,1 -DA:8,1 -DA:10,1 -DA:11,3 -LF:7 -LH:7 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/dbController/database.ts -FN:5,openDb -FN:12,initializeDb -FNF:2 -FNH:2 -FNDA:140,openDb -FNDA:2,initializeDb -DA:1,2 -DA:2,2 -DA:3,2 -DA:5,2 -DA:6,140 -DA:12,2 -DA:13,2 -DA:14,2 -LF:8 -LH:8 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/dbController/index.ts -FNF:0 -FNH:0 -DA:1,1 -LF:1 -LH:1 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/helpers/index.ts -FNF:0 -FNH:0 -DA:1,2 -LF:1 -LH:1 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/helpers/log.ts -FN:1,(anonymous_0) -FN:3,(anonymous_1) -FNF:2 -FNH:2 -FNDA:4,(anonymous_0) -FNDA:4,(anonymous_1) -DA:1,4 -DA:3,2 -DA:4,4 -DA:5,4 -LF:4 -LH:4 -BRDA:4,0,0,4 -BRF:1 -BRH:1 -end_of_record -TN: -SF:src/middlewares/applyMiddlewares.ts -FN:3,(anonymous_0) -FN:7,(anonymous_1) -FN:9,(anonymous_2) -FNF:3 -FNH:3 -FNDA:1,(anonymous_0) -FNDA:10,(anonymous_1) -FNDA:20,(anonymous_2) -DA:3,1 -DA:7,10 -DA:9,20 -LF:3 -LH:3 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/middlewares/controllers.types.ts -FNF:0 -FNH:0 -DA:4,1 -LF:1 -LH:1 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/middlewares/index.ts -FNF:0 -FNH:0 -DA:1,1 -DA:2,1 -DA:3,1 -DA:4,1 -LF:4 -LH:4 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/middlewares/errorHandler/CheckError.ts -FN:2,(anonymous_0) -FNF:1 -FNH:1 -FNDA:15,(anonymous_0) -DA:1,2 -DA:3,15 -DA:6,15 -LF:3 -LH:3 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/middlewares/errorHandler/handleCheckErrors.ts -FN:5,(anonymous_7) -FN:5,(anonymous_8) -FN:5,(anonymous_9) -FN:5,(anonymous_10) -FNF:4 -FNH:4 -FNDA:13,(anonymous_7) -FNDA:31,(anonymous_8) -FNDA:31,(anonymous_9) -FNDA:31,(anonymous_10) -DA:2,2 -DA:4,2 -DA:5,31 -DA:6,31 -DA:7,31 -DA:9,16 -DA:10,15 -DA:12,1 -LF:8 -LH:8 -BRDA:9,0,0,15 -BRDA:9,0,1,1 -BRF:2 -BRH:2 -end_of_record -TN: -SF:src/middlewares/errorHandler/index.ts -FNF:0 -FNH:0 -DA:1,1 -DA:2,1 -LF:2 -LH:2 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/middlewares/logger/index.ts -FNF:0 -FNH:0 -DA:1,1 -LF:1 -LH:1 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/middlewares/logger/logger.ts -FN:4,(anonymous_7) -FN:4,(anonymous_8) -FN:4,(anonymous_9) -FN:4,(anonymous_10) -FNF:4 -FNH:4 -FNDA:12,(anonymous_7) -FNDA:30,(anonymous_8) -FNDA:30,(anonymous_9) -FNDA:30,(anonymous_10) -DA:1,2 -DA:4,30 -DA:5,30 -DA:6,2 -DA:7,2 -DA:10,30 -LF:6 -LH:6 -BRDA:5,0,0,2 -BRDA:6,1,0,1 -BRDA:6,1,1,1 -BRDA:6,2,0,2 -BRDA:6,2,1,2 -BRF:5 -BRH:5 -end_of_record -TN: -SF:src/models/index.ts -FNF:0 -FNH:0 -DA:1,1 -DA:2,1 -DA:3,1 -LF:3 -LH:3 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/models/group/index.ts -FNF:0 -FNH:0 -DA:1,1 -DA:2,1 -LF:2 -LH:2 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/models/group/model.ts -FN:5,createGroup -FN:14,findGroupByCode -FN:21,addUserToGroup -FNF:3 -FNH:3 -FNDA:16,createGroup -FNDA:20,findGroupByCode -FNDA:15,addUserToGroup -DA:1,1 -DA:5,1 -DA:6,16 -DA:7,16 -DA:8,16 -DA:14,1 -DA:17,20 -DA:18,20 -DA:21,1 -DA:22,15 -DA:23,15 -LF:11 -LH:11 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/models/movie/index.ts -FNF:0 -FNH:0 -DA:1,1 -DA:2,1 -LF:2 -LH:2 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/models/movie/model.ts -FN:5,suggestMovie -FN:33,calcMovieVotes -FN:42,hasUserMovieVote -FN:54,mapMovie -FN:60,findMovieById -FN:73,voteForMovie -FN:81,listMovies -FN:85,(anonymous_21) -FN:88,(anonymous_22) -FN:89,(anonymous_23) -FN:93,markMovieAsWatched -FN:101,markMovieAsVetoed -FNF:12 -FNH:12 -FNDA:7,suggestMovie -FNDA:18,calcMovieVotes -FNDA:3,hasUserMovieVote -FNDA:22,mapMovie -FNDA:19,findMovieById -FNDA:2,voteForMovie -FNDA:5,listMovies -FNDA:5,(anonymous_21) -FNDA:5,(anonymous_22) -FNDA:3,(anonymous_23) -FNDA:1,markMovieAsWatched -FNDA:1,markMovieAsVetoed -DA:1,1 -DA:5,1 -DA:12,7 -DA:13,7 -DA:18,7 -DA:21,7 -DA:22,0 -DA:30,7 -DA:34,18 -DA:35,18 -DA:39,18 -DA:42,1 -DA:46,3 -DA:47,3 -DA:51,3 -DA:57,22 -DA:60,1 -DA:64,19 -DA:65,19 -DA:73,1 -DA:74,2 -DA:75,2 -DA:81,1 -DA:82,5 -DA:83,5 -DA:86,5 -DA:89,5 -DA:93,1 -DA:94,1 -DA:95,1 -DA:101,1 -DA:102,1 -DA:103,1 -LF:33 -LH:32 -BRDA:18,0,0,7 -BRDA:18,0,1,0 -BRDA:18,1,0,0 -BRDA:18,1,1,7 -BRDA:18,2,0,7 -BRDA:18,2,1,7 -BRDA:21,3,0,0 -BRDA:39,4,0,18 -BRDA:39,4,1,0 -BRDA:39,5,0,18 -BRDA:39,5,1,18 -BRDA:57,6,0,22 -BRDA:57,6,1,18 -BRF:13 -BRH:9 -end_of_record -TN: -SF:src/models/user/index.ts -FNF:0 -FNH:0 -DA:1,1 -DA:2,1 -LF:2 -LH:2 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/models/user/model.ts -FN:5,createUser -FN:14,findUserByUsername -FNF:2 -FNH:2 -FNDA:19,createUser -FNDA:9,findUserByUsername -DA:1,1 -DA:5,1 -DA:6,19 -DA:7,19 -DA:11,19 -DA:14,1 -DA:17,9 -DA:18,9 -LF:8 -LH:8 -BRF:0 -BRH:0 -end_of_record diff --git a/src/consts.ts b/src/consts.ts index 520bdf3..314e7fe 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -1,3 +1,3 @@ -export const DATABASE_FILENAME = './db/test_database.db'; +export const DATABASE_FILENAME = './db/database.db'; export const KINOPOISK_URL = 'https://www.kinopoisk.ru/index.php?kp_query='; export const IMDB_URL = 'https://www.imdb.com/find/?q='; diff --git a/src/controllers/bot.test.ts b/src/controllers/bot.test.ts index e574d98..65945da 100644 --- a/src/controllers/bot.test.ts +++ b/src/controllers/bot.test.ts @@ -6,13 +6,13 @@ process.env.NTBA_FIX_319 = '1'; import TelegramBot from 'node-telegram-bot-api'; import { createGroup, - findGroupByCode, createUser, addUserToGroup, suggestMovie, findMovieById, findUserByUsername, listMovies, + findGroupByUserId, } from '../models'; import { initializeDb } from '../dbController'; import { botHandlers } from './bot'; @@ -46,10 +46,13 @@ describe('Bot Commands', () => { }; beforeAll(async () => { - bot = new TelegramBot('test_token', { polling: true }); await initializeDb(); }); + beforeEach(() => { + bot = new TelegramBot('test_token', { polling: true }); + }); + afterAll(async () => { fs.rmSync(DATABASE_FILENAME); jest.clearAllMocks(); @@ -96,14 +99,17 @@ describe('Bot Commands', () => { describe('create_group', () => { it('should create a new group', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); + const chatId = createChat(); const msg = { - chat: { id: createChat() }, + chat: { id: chatId }, text: '/create_group', + user: { username: String(chatId) }, } as unknown as TelegramBot.Message; + const user = await createUser(String(chatId)); await emitMsg(msg); - const group = await findGroupByCode(String(msg.chat.id)); + const group = await findGroupByUserId(user?.id ?? 0); expect(group).not.toBeNull(); expect(sendMessage).toHaveBeenCalledWith( msg.chat.id, @@ -115,7 +121,7 @@ describe('Bot Commands', () => { it('should error with duplicate group code', async () => { const chatId = createChat(); - await createGroup(String(chatId)); + await createGroup(); const sendMessage = jest.spyOn(bot, 'sendMessage'); const msg = { chat: { id: chatId }, @@ -136,11 +142,11 @@ describe('Bot Commands', () => { it('should add user to group', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); - const group = await createGroup(String(chatId)); + const group = await createGroup(); const user = await createUser(String(chatId)); const msg = { chat: { id: chatId }, - text: `/join_group ${chatId}`, + text: `/join_group ${group.code}`, from: { username: user?.username }, } as unknown as TelegramBot.Message; await addUserToGroup(group.id, user?.id ?? 0); @@ -171,7 +177,7 @@ describe('Bot Commands', () => { ); }); - it('should error without user code', async () => { + it('should error without username', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const msg = { chat: { id: createChat() }, @@ -215,7 +221,7 @@ describe('Bot Commands', () => { text: '/suggest Inception', from: { username: user?.username ?? 0 }, } as unknown as TelegramBot.Message; - const group = await createGroup(String(msg.chat.id)); + const group = await createGroup(); await addUserToGroup(group.id, user?.id ?? 0); await emitMsg(msg); @@ -252,7 +258,7 @@ describe('Bot Commands', () => { text: '/suggest ', from: { username: user?.username ?? 0 }, } as unknown as TelegramBot.Message; - const group = await createGroup(String(msg.chat.id)); + const group = await createGroup(); await addUserToGroup(group.id, user?.id ?? 0); await emitMsg(msg); @@ -275,7 +281,7 @@ describe('Bot Commands', () => { text: '/vote 1', from: { username: user?.username ?? '' }, } as unknown as TelegramBot.Message; - const group = await createGroup(String(msg.chat.id)); + const group = await createGroup(); await addUserToGroup(group.id, user?.id ?? 0); const insertedMovie = await suggestMovie( 'Inception', @@ -303,7 +309,7 @@ describe('Bot Commands', () => { bot = new TelegramBot('test_token', { polling: true }); const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); - const group = await createGroup(String(chatId)); + const group = await createGroup(); const user = await createUser(String(chatId)); await addUserToGroup(group.id, user?.id ?? 0); const msg = { @@ -338,7 +344,7 @@ describe('Bot Commands', () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); const user = await createUser(String(chatId)); - const group = await createGroup(String(chatId)); + const group = await createGroup(); await addUserToGroup(group.id, user?.id ?? 0); const msg = { chat: { id: chatId }, @@ -358,7 +364,7 @@ describe('Bot Commands', () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); const user = await createUser(String(chatId)); - const group = await createGroup(String(chatId)); + const group = await createGroup(); await addUserToGroup(group.id, user?.id ?? 0); const msg = { chat: { id: chatId }, @@ -382,7 +388,7 @@ describe('Bot Commands', () => { chat: { id: createChat() }, text: '/list', } as unknown as TelegramBot.Message; - const group = await createGroup(String(msg.chat.id)); + const group = await createGroup(); const user = await createUser(String(chatId)); await addUserToGroup(group.id, user?.id ?? 0); const movie = await suggestMovie( @@ -421,7 +427,7 @@ describe('Bot Commands', () => { it('should delete a movie from the list', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); - const group = await createGroup(String(chatId)); + const group = await createGroup(); const user = await createUser(String(chatId)); const msg = { chat: { id: chatId }, @@ -489,7 +495,7 @@ describe('Bot Commands', () => { chat: { id: chatId }, text: '/watched 9999', } as unknown as TelegramBot.Message; - const group = await createGroup(String(chatId)); + const group = await createGroup(); const user = await createUser(String(chatId)); await addUserToGroup(group.id, user?.id ?? 0); @@ -506,7 +512,7 @@ describe('Bot Commands', () => { it('veto command should veto a movie', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); - const group = await createGroup(String(chatId)); + const group = await createGroup(); const user = await createUser(String(chatId)); const msg = { chat: { id: chatId }, @@ -556,7 +562,7 @@ describe('Bot Commands', () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); const user = await createUser(String(chatId)); - const group = await createGroup(String(chatId)); + const group = await createGroup(); const msg = { chat: { id: chatId }, text: '/veto 9999', @@ -577,7 +583,7 @@ describe('Bot Commands', () => { it('should send a random movie', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); - const group = await createGroup(String(chatId)); + const group = await createGroup(); const user = await createUser(String(chatId)); const msg = { chat: { id: chatId }, @@ -623,7 +629,7 @@ describe('Bot Commands', () => { it('should error if list is empty', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); - const group = await createGroup(String(chatId)); + const group = await createGroup(); const user = await createUser(String(chatId)); const msg = { chat: { id: chatId }, diff --git a/src/controllers/bot.ts b/src/controllers/bot.ts index 8298f61..5d43c95 100644 --- a/src/controllers/bot.ts +++ b/src/controllers/bot.ts @@ -14,12 +14,12 @@ import { markMovieAsVetoed, hasUserMovieVote, findUserByUsername, + findGroupByUserId, } from '../models'; import texts from '../texts.json'; import { getImdbUrl, getKinopoiskUrl, getMovieDescription } from './helpers'; import { applyMiddlewares, - CheckError, handleCheckErrors, logger, TRule, @@ -41,11 +41,11 @@ const rawBotHandlers: TRule[] = [ [ /\/start/, (bot) => async (msg) => { - const username = msg.from?.username; + const username = msg.from?.username ?? ''; - const user = await findUserByUsername(username ?? ''); + const user = await findUserByUsername(username); if (!user) { - await createUser(msg.from?.username ?? ''); + await createUser(username); } bot.sendMessage(msg.chat.id, texts.start); @@ -61,13 +61,15 @@ const rawBotHandlers: TRule[] = [ /\/create_group/, (bot) => async (msg) => { const chatId = msg.chat.id; - const group = await findGroupByCode(String(chatId)); - if (group) { - bot.sendMessage(chatId, texts.group_already_created + group.code); + const user = await checkAndGetUserByUsername(msg); + + const foundGroup = await findGroupByUserId(user.id); + if (foundGroup) { + bot.sendMessage(chatId, texts.group_already_created + foundGroup.code); return; } - await createGroup(String(chatId)); - bot.sendMessage(chatId, `${texts.group_created} ${chatId}`); + const group = await createGroup(); + bot.sendMessage(chatId, `${texts.group_created} ${group.code}`); }, ], [ @@ -75,13 +77,13 @@ const rawBotHandlers: TRule[] = [ (bot) => async (msg, match) => { const chatId = msg.chat.id; const groupCode = checkAndGetArg(match, texts.no_group_code); - const user = await checkAndGetUserByUsername(msg); const group = await findGroupByCode(groupCode); if (!group) { bot.sendMessage(chatId, texts.group_not_found); return; } + const user = await checkAndGetUserByUsername(msg); await addUserToGroup(group.id, user.id); bot.sendMessage(chatId, texts.joined_group); }, diff --git a/src/controllers/checkers.ts b/src/controllers/checkers.ts index 1823ac3..e41a561 100644 --- a/src/controllers/checkers.ts +++ b/src/controllers/checkers.ts @@ -6,7 +6,7 @@ import TelegramBot from 'node-telegram-bot-api'; import texts from '../texts.json'; import { CheckError } from '../middlewares/errorHandler'; import { - findGroupByCode, + findGroupByUserId, findMovieById, findUserByUsername, IGroup, @@ -33,8 +33,8 @@ export const checkAndGetUserByUsername = async ( export const checkAndGetGroup = async ( msg: TelegramBot.Message, ): Promise => { - const chatId = msg.chat.id; - const group = await findGroupByCode(String(chatId)); + const user = await checkAndGetUserByUsername(msg); + const group = await findGroupByUserId(user.id); if (!group) { throw new CheckError(texts.not_in_group); diff --git a/src/dbController/database.ts b/src/dbController/database.ts index b747933..def8162 100644 --- a/src/dbController/database.ts +++ b/src/dbController/database.ts @@ -45,3 +45,15 @@ export async function initializeDb() { ); `); } + +export async function listAllTablesData() { + const db = await openDb(); + + console.log({ + groups: await db.all('SELECT * FROM groups'), + users: await db.all('SELECT * FROM users'), + movies: await db.all('SELECT * FROM movies'), + group_users: await db.all('SELECT * FROM group_users'), + votes: await db.all('SELECT * FROM votes'), + }); +} diff --git a/src/middlewares/logger/logger.test.ts b/src/middlewares/logger/logger.test.ts index 8a79a5c..0e108d1 100644 --- a/src/middlewares/logger/logger.test.ts +++ b/src/middlewares/logger/logger.test.ts @@ -5,9 +5,15 @@ process.env.NTBA_FIX_319 = '1'; import TelegramBot from 'node-telegram-bot-api'; import { logger } from './logger'; +jest.mock('../../dbController', () => ({ + listAllTablesData: jest.fn().mockResolvedValue(undefined), +})); + describe('logger middleware', () => { it('should log user message', async () => { - const loggerMock = jest.spyOn(console, 'log'); + const loggerMock = jest + .spyOn(console, 'log') + .mockImplementation(() => undefined); const bot = {} as TelegramBot; const handler = () => () => Promise.resolve(undefined); const msg = { @@ -18,14 +24,13 @@ describe('logger middleware', () => { process.env.DEBUG_OUTPUT = '1'; logger(handler)(bot)(msg, ['']); - expect(loggerMock).toHaveBeenCalledWith( - expect.stringContaining('User: test_user, Message: Hello, bot!'), - ); - expect(loggerMock).toHaveBeenCalledWith(expect.stringContaining('DB')); + expect(loggerMock.mock.calls.length).toEqual(2); }); it('should log message from unknown user', async () => { - const loggerMock = jest.spyOn(console, 'log'); + const loggerMock = jest + .spyOn(console, 'log') + .mockImplementation(() => undefined); const bot = {} as TelegramBot; const handler = () => () => Promise.resolve(undefined); const msg = { @@ -35,9 +40,8 @@ describe('logger middleware', () => { process.env.DEBUG_OUTPUT = '1'; logger(handler)(bot)(msg, ['']); - expect(loggerMock).toHaveBeenCalledWith( - expect.stringContaining('User: undefined, Message: Hello, bot!'), - ); - expect(loggerMock).toHaveBeenCalledWith(expect.stringContaining('DB')); + expect( + loggerMock.mock.calls.slice(loggerMock.mock.calls.length - 2).length, + ).toEqual(2); }); }); diff --git a/src/middlewares/logger/logger.ts b/src/middlewares/logger/logger.ts index d8d8d19..3c4dc8c 100644 --- a/src/middlewares/logger/logger.ts +++ b/src/middlewares/logger/logger.ts @@ -1,10 +1,12 @@ +import { listAllTablesData } from '../../dbController'; import { log } from '../../helpers'; import { TMiddleware } from '../controllers.types'; export const logger: TMiddleware = (handler) => (bot) => async (msg, match) => { if (process.env.DEBUG_OUTPUT === '1') { - log(`User: ${msg.from?.username}, Message: ${msg.text}`); - log(`DB(Movies): `); + log(`User: ${msg.from?.username}, Command: ${msg.text}`); + log('DB:'); + await listAllTablesData(); } await handler(bot)(msg, match); diff --git a/src/models/group/model.ts b/src/models/group/model.ts index b56920f..08b343a 100644 --- a/src/models/group/model.ts +++ b/src/models/group/model.ts @@ -2,7 +2,8 @@ import { openDb } from '../../dbController'; import { TId } from '../types'; import { IGroup } from './types'; -export async function createGroup(code: string): Promise { +export async function createGroup(): Promise { + const code = Math.random().toString().substr(2, 7); const db = await openDb(); const res = await db.run(`INSERT INTO groups (code) VALUES (?)`, [code]); return { @@ -18,6 +19,16 @@ export async function findGroupByCode( return db.get(`SELECT * FROM groups WHERE code = ?`, [code]); } +export async function findGroupByUserId( + userId: TId, +): Promise { + const db = await openDb(); + return db.get( + `SELECT g.* FROM groups g JOIN group_users gu ON g.id = gu.group_id WHERE gu.user_id =?`, + [userId], + ); +} + export async function addUserToGroup(groupId: TId, userId: TId) { const db = await openDb(); await db.run(`INSERT INTO group_users (group_id, user_id) VALUES (?, ?)`, [ From 18cf3b3d5bdbd31b0fed363a5cb2151f3cb9169f Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Sun, 18 Aug 2024 01:11:30 +0200 Subject: [PATCH 04/11] Leave group command --- README.md | 1 + docs/tech_info.md | 1 + src/controllers/bot.test.ts | 25 +++++++++++++++++++++++++ src/controllers/bot.ts | 12 ++++++++++++ src/models/group/model.ts | 8 ++++++++ src/texts.json | 1 + 6 files changed, 48 insertions(+) diff --git a/README.md b/README.md index c8613e0..6d8e57e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Telegram bot for selecting movies to watch together. - `/help` - Show the list of commands and their descriptions. - `/create_group` - Create a new group for group movie watching. - `/join_group ` - Join an existing group by code. +- `/leave_group` - Leave current group. - `/suggest ` - Suggest a movie for watching. - `/vote ` - Vote for a suggested movie. - `/list` - Show the list of suggested movies. diff --git a/docs/tech_info.md b/docs/tech_info.md index a7b0051..c2a0389 100644 --- a/docs/tech_info.md +++ b/docs/tech_info.md @@ -7,6 +7,7 @@ Test bot(for local development): [@watch_together_test_bot](https://t.me/watch_t create_group - создать группу join_group - присоединиться к группе +leave_group - покинуть группу suggest - предложить фильм vote - проголосовать за фильм list - показать список фильмов diff --git a/src/controllers/bot.test.ts b/src/controllers/bot.test.ts index 65945da..989ebcc 100644 --- a/src/controllers/bot.test.ts +++ b/src/controllers/bot.test.ts @@ -212,6 +212,31 @@ describe('Bot Commands', () => { }); }); + describe('leave_group', () => { + it('should remove user from group', async () => { + const sendMessage = jest.spyOn(bot, 'sendMessage'); + const chatId = createChat(); + const group = await createGroup(); + const user = await createUser(String(chatId)); + await addUserToGroup(group.id, user?.id ?? 0); + const msg = { + chat: { id: chatId }, + text: `/leave_group`, + from: { username: user?.username }, + } as unknown as TelegramBot.Message; + + await emitMsg(msg); + + const userGroup = await findGroupByUserId(user?.id ?? 0); + + expect(userGroup).toBeUndefined(); + expect(sendMessage).toHaveBeenCalledWith( + msg.chat.id, + expect.stringContaining('Вы покинули группу'), + ); + }); + }); + describe('suggest', () => { it('should suggest a movie', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); diff --git a/src/controllers/bot.ts b/src/controllers/bot.ts index 5d43c95..4c8f9ca 100644 --- a/src/controllers/bot.ts +++ b/src/controllers/bot.ts @@ -15,6 +15,7 @@ import { hasUserMovieVote, findUserByUsername, findGroupByUserId, + removeUserFromGroup, } from '../models'; import texts from '../texts.json'; import { getImdbUrl, getKinopoiskUrl, getMovieDescription } from './helpers'; @@ -88,6 +89,17 @@ const rawBotHandlers: TRule[] = [ bot.sendMessage(chatId, texts.joined_group); }, ], + [ + /\/leave_group/, + (bot) => async (msg) => { + const chatId = msg.chat.id; + const user = await checkAndGetUserByUsername(msg); + const group = await checkAndGetGroup(msg); + + await removeUserFromGroup(group.id, user.id); + bot.sendMessage(chatId, texts.left_group); + }, + ], [ /\/suggest (.*)/, (bot) => async (msg, match) => { diff --git a/src/models/group/model.ts b/src/models/group/model.ts index 08b343a..f05661d 100644 --- a/src/models/group/model.ts +++ b/src/models/group/model.ts @@ -36,3 +36,11 @@ export async function addUserToGroup(groupId: TId, userId: TId) { userId, ]); } + +export async function removeUserFromGroup(groupId: TId, userId: TId) { + const db = await openDb(); + await db.run('DELETE FROM group_users WHERE user_id =? AND group_id =?', [ + userId, + groupId, + ]); +} diff --git a/src/texts.json b/src/texts.json index 5c8003d..d2f7cfd 100644 --- a/src/texts.json +++ b/src/texts.json @@ -5,6 +5,7 @@ "joined_group": "Вы присоединились к группе!", "group_not_found": "Группа с таким кодом не найдена.", "group_already_created": "Группа уже создана. Код присоединения: ", + "left_group": "Вы покинули группу.", "no_group_code": "Код группы не указан.", "movie_suggested": "Фильм предложен", "not_in_group": "Вы не состоите ни в одной группе.", From 9447a7bd8aadcbcba93894929583d9388633a055 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Sun, 18 Aug 2024 01:42:36 +0200 Subject: [PATCH 05/11] Some tests fixes --- src/controllers/bot.test.ts | 122 +++++++++++++++++++----------------- src/controllers/bot.ts | 1 + 2 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/controllers/bot.test.ts b/src/controllers/bot.test.ts index 989ebcc..09590c2 100644 --- a/src/controllers/bot.test.ts +++ b/src/controllers/bot.test.ts @@ -65,7 +65,7 @@ describe('Bot Commands', () => { chat: { id: createChat() }, text: '/start', from: { username: 'test' }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -85,7 +85,7 @@ describe('Bot Commands', () => { const msg = { chat: { id: createChat() }, text: '/help', - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -100,12 +100,12 @@ describe('Bot Commands', () => { it('should create a new group', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); + const user = await createUser(String(chatId)); const msg = { chat: { id: chatId }, text: '/create_group', - user: { username: String(chatId) }, - } as unknown as TelegramBot.Message; - const user = await createUser(String(chatId)); + from: { username: user?.username }, + } as TelegramBot.Message; await emitMsg(msg); @@ -113,21 +113,21 @@ describe('Bot Commands', () => { expect(group).not.toBeNull(); expect(sendMessage).toHaveBeenCalledWith( msg.chat.id, - expect.stringContaining( - `Группа создана! Код для присоединения: ${msg.chat.id}`, - ), + expect.stringContaining(`Группа создана! Код для присоединения:`), ); }); - it('should error with duplicate group code', async () => { - const chatId = createChat(); - await createGroup(); + it('should error with existing group', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); + const chatId = createChat(); + const user = await createUser(String(chatId)); + const group = await createGroup(); + await addUserToGroup(group.id, user?.id ?? 0); const msg = { chat: { id: chatId }, text: '/create_group', - from: { username: 'test' }, - } as unknown as TelegramBot.Message; + from: { username: user?.username }, + } as TelegramBot.Message; await emitMsg(msg); @@ -148,7 +148,7 @@ describe('Bot Commands', () => { chat: { id: chatId }, text: `/join_group ${group.code}`, from: { username: user?.username }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await addUserToGroup(group.id, user?.id ?? 0); await emitMsg(msg); @@ -167,7 +167,7 @@ describe('Bot Commands', () => { chat: { id: createChat() }, text: '/join_group ', from: { username: user?.username }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -179,11 +179,12 @@ describe('Bot Commands', () => { it('should error without username', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); + const group = await createGroup(); const msg = { chat: { id: createChat() }, - text: '/join_group 1', + text: `/join_group ${group.code}`, from: {}, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -201,7 +202,7 @@ describe('Bot Commands', () => { chat: { id: chatId }, text: '/join_group 9999', from: { username: user?.username }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -223,7 +224,7 @@ describe('Bot Commands', () => { chat: { id: chatId }, text: `/leave_group`, from: { username: user?.username }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -240,14 +241,15 @@ describe('Bot Commands', () => { describe('suggest', () => { it('should suggest a movie', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); + const chatId = createChat(); + const group = await createGroup(); const user = await createUser(String(chatId)); + await addUserToGroup(group.id, user?.id ?? 0); const msg = { - chat: { id: createChat() }, + chat: { id: chatId }, text: '/suggest Inception', from: { username: user?.username ?? 0 }, - } as unknown as TelegramBot.Message; - const group = await createGroup(); - await addUserToGroup(group.id, user?.id ?? 0); + } as TelegramBot.Message; await emitMsg(msg); @@ -265,7 +267,7 @@ describe('Bot Commands', () => { const msg = { chat: { id: createChat() }, text: '/suggest Inception', - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -282,7 +284,7 @@ describe('Bot Commands', () => { chat: { id: createChat() }, text: '/suggest ', from: { username: user?.username ?? 0 }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; const group = await createGroup(); await addUserToGroup(group.id, user?.id ?? 0); @@ -305,7 +307,7 @@ describe('Bot Commands', () => { chat: { id: createChat() }, text: '/vote 1', from: { username: user?.username ?? '' }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; const group = await createGroup(); await addUserToGroup(group.id, user?.id ?? 0); const insertedMovie = await suggestMovie( @@ -341,7 +343,7 @@ describe('Bot Commands', () => { chat: { id: chatId }, text: '/vote 1', from: { username: user?.username ?? '' }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; const insertedMovie = await suggestMovie( 'Inception', user?.id ?? 0, @@ -375,7 +377,7 @@ describe('Bot Commands', () => { chat: { id: chatId }, text: '/vote', from: { username: user?.username ?? '' }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -395,7 +397,7 @@ describe('Bot Commands', () => { chat: { id: chatId }, text: '/vote qwe', from: { username: user?.username ?? '' }, - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -409,13 +411,15 @@ describe('Bot Commands', () => { describe('list', () => { it('should print current list of movies', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); - const msg = { - chat: { id: createChat() }, - text: '/list', - } as unknown as TelegramBot.Message; + const chatId = createChat(); const group = await createGroup(); const user = await createUser(String(chatId)); await addUserToGroup(group.id, user?.id ?? 0); + const msg = { + chat: { id: chatId }, + text: '/list', + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; const movie = await suggestMovie( 'Inception', user?.id ?? 0, @@ -434,11 +438,13 @@ describe('Bot Commands', () => { it('should error if user not in group', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); + const chatId = createChat(); + const user = await createUser(String(chatId)); const msg = { chat: { id: createChat() }, text: '/list', - } as unknown as TelegramBot.Message; - await createUser(String(msg.chat.id)); + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await emitMsg(msg); expect(sendMessage).toHaveBeenCalledWith( @@ -457,8 +463,8 @@ describe('Bot Commands', () => { const msg = { chat: { id: chatId }, text: '/watched 1', - from: { id: user?.id ?? 0 }, - } as unknown as TelegramBot.Message; + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await addUserToGroup(group.id, user?.id ?? 0); const insertedMovie = await suggestMovie( 'Inception', @@ -488,7 +494,7 @@ describe('Bot Commands', () => { const msg = { chat: { id: createChat() }, text: '/watched ', - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -500,10 +506,13 @@ describe('Bot Commands', () => { it('should error if user not in group', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); + const chatId = createChat(); + const user = await createUser(String(chatId)); const msg = { chat: { id: createChat() }, text: '/watched 9998', - } as unknown as TelegramBot.Message; + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await emitMsg(msg); @@ -516,13 +525,14 @@ describe('Bot Commands', () => { it('should error if wrong movie code', async () => { const sendMessage = jest.spyOn(bot, 'sendMessage'); const chatId = createChat(); - const msg = { - chat: { id: chatId }, - text: '/watched 9999', - } as unknown as TelegramBot.Message; const group = await createGroup(); const user = await createUser(String(chatId)); await addUserToGroup(group.id, user?.id ?? 0); + const msg = { + chat: { id: chatId }, + text: '/watched 9999', + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await emitMsg(msg); @@ -539,12 +549,12 @@ describe('Bot Commands', () => { const chatId = createChat(); const group = await createGroup(); const user = await createUser(String(chatId)); + await addUserToGroup(group.id, user?.id ?? 0); const msg = { chat: { id: chatId }, text: '/veto 1', - from: { id: user?.id ?? 0 }, - } as unknown as TelegramBot.Message; - await addUserToGroup(group.id, user?.id ?? 0); + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; const insertedMovie = await suggestMovie( 'Inception', user?.id ?? 0, @@ -573,7 +583,7 @@ describe('Bot Commands', () => { const msg = { chat: { id: chatId }, text: '/veto ', - } as unknown as TelegramBot.Message; + } as TelegramBot.Message; await emitMsg(msg); @@ -591,8 +601,8 @@ describe('Bot Commands', () => { const msg = { chat: { id: chatId }, text: '/veto 9999', - from: { id: user?.id ?? 0 }, - } as unknown as TelegramBot.Message; + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await addUserToGroup(group.id, user?.id ?? 0); await emitMsg(msg); @@ -610,12 +620,12 @@ describe('Bot Commands', () => { const chatId = createChat(); const group = await createGroup(); const user = await createUser(String(chatId)); + await addUserToGroup(group.id, user?.id ?? 0); const msg = { chat: { id: chatId }, text: '/random', - from: { id: user?.id ?? 0 }, - } as unknown as TelegramBot.Message; - await addUserToGroup(group.id, user?.id ?? 0); + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await suggestMovie( 'Inception', user?.id ?? 0, @@ -640,8 +650,8 @@ describe('Bot Commands', () => { const msg = { chat: { id: chatId }, text: '/random', - from: { id: user?.id ?? 0 }, - } as unknown as TelegramBot.Message; + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await emitMsg(msg); @@ -659,8 +669,8 @@ describe('Bot Commands', () => { const msg = { chat: { id: chatId }, text: '/random', - from: { id: user?.id ?? 0 }, - } as unknown as TelegramBot.Message; + from: { username: user?.username ?? '' }, + } as TelegramBot.Message; await addUserToGroup(group.id, user?.id ?? 0); await emitMsg(msg); diff --git a/src/controllers/bot.ts b/src/controllers/bot.ts index 4c8f9ca..f97c18b 100644 --- a/src/controllers/bot.ts +++ b/src/controllers/bot.ts @@ -70,6 +70,7 @@ const rawBotHandlers: TRule[] = [ return; } const group = await createGroup(); + await addUserToGroup(group.id, user.id); bot.sendMessage(chatId, `${texts.group_created} ${group.code}`); }, ], From f5dba010d46ba29eecd1f22954ec6afcdad68462 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Sun, 18 Aug 2024 01:52:08 +0200 Subject: [PATCH 06/11] Remove DS_Store --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 1 + 2 files changed, 1 insertion(+) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 1ad899dbcdc748036dd701eacb0ec11e243703d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyJ`bL3>+mc4$`I(2Sbbi#2M3J zT*oXyY@Q(Y!ZDE|1kgGlC+ZoQs7@HV6)|Fx!@~RZ=JlH_u58Z)4k@C?#6Xc7@{2$qaAbO f?f5y0vab1>=e=-D3_9~cC+cUwb&*MdzgFN1-fR_w diff --git a/.gitignore b/.gitignore index 1a69fbd..6b44ecc 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ coverage/Icov.info db/database.db db/test_database.db .env +.DS_Store From 8f6681e79264dd4a6dcd503c45de6c933209fcb3 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Sun, 18 Aug 2024 01:52:42 +0200 Subject: [PATCH 07/11] Fix gitignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6b44ecc..efa1b05 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ dist coverage/Icon-report/* coverage/coverage-summary.json coverage/Icov.info -db/database.db -db/test_database.db +db/*.db .env .DS_Store From 10a291407967ec32fcf9ac6c70ffea31c1fe1a76 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Sun, 25 Aug 2024 15:02:00 +0200 Subject: [PATCH 08/11] Fix logic and tests --- .gitignore | 4 +- src/controllers/bot.test.ts | 370 +++++++++-------------------------- src/controllers/bot.ts | 34 ++-- src/controllers/checkers.ts | 12 +- src/dbController/database.ts | 1 + src/lib/setupChat.ts | 87 ++++++++ src/lib/testUtils.ts | 27 +++ src/models/types.ts | 1 + src/models/user/model.ts | 22 ++- src/models/user/types.ts | 3 +- src/texts.json | 4 +- 11 files changed, 255 insertions(+), 310 deletions(-) create mode 100644 src/lib/setupChat.ts create mode 100644 src/lib/testUtils.ts diff --git a/.gitignore b/.gitignore index efa1b05..fb67a30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ node_modules dist -coverage/Icon-report/* +coverage/lcov-report/* coverage/coverage-summary.json -coverage/Icov.info +coverage/lcov.info db/*.db .env .DS_Store diff --git a/src/controllers/bot.test.ts b/src/controllers/bot.test.ts index 09590c2..ba79447 100644 --- a/src/controllers/bot.test.ts +++ b/src/controllers/bot.test.ts @@ -3,19 +3,18 @@ import fs from 'fs'; // deprecated Automatic enabling of cancellation // of promises is deprecated In the future process.env.NTBA_FIX_319 = '1'; -import TelegramBot from 'node-telegram-bot-api'; +import TelegramBot, { User } from 'node-telegram-bot-api'; import { - createGroup, - createUser, - addUserToGroup, suggestMovie, findMovieById, - findUserByUsername, listMovies, findGroupByUserId, + getUserByUid, } from '../models'; import { initializeDb } from '../dbController'; import { botHandlers } from './bot'; +import { createCreateChat, createEmit } from '../lib/testUtils'; +import { createSetupChat, TSetupChat } from '../lib/setupChat'; const DATABASE_FILENAME = './db/test_database.db'; @@ -28,29 +27,19 @@ jest.mock('../consts.ts', () => ({ describe('Bot Commands', () => { let bot: TelegramBot; - let chatId = 0; - const emitMsg = async (msg: TelegramBot.Message) => { - const handler = botHandlers.find((handler) => - msg.text ? handler[0].test(msg.text) : false, - ); - if (!handler) { - return; - } - const match = msg.text?.split(' ') ?? null; - const msgHandler = handler[1](bot); - return await msgHandler(msg, match); - }; - const createChat = () => { - chatId += 1; - return chatId; - }; + let emitMsg: (msg: TelegramBot.Message) => Promise; + let setupChat: TSetupChat; + let createChat: () => number; beforeAll(async () => { await initializeDb(); + createChat = createCreateChat(); }); beforeEach(() => { bot = new TelegramBot('test_token', { polling: true }); + emitMsg = createEmit(botHandlers, bot); + setupChat = createSetupChat(bot, createChat); }); afterAll(async () => { @@ -60,16 +49,17 @@ describe('Bot Commands', () => { describe('start', () => { it('should send welcome message and create a user', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const msg = { - chat: { id: createChat() }, - text: '/start', - from: { username: 'test' }, - } as TelegramBot.Message; + const { sendMessage, msg, chatId } = await setupChat('/start', { + createUser: false, + createGroup: false, + }); - await emitMsg(msg); + await emitMsg({ + ...msg, + from: { username: 'test_user', id: chatId } as User, + }); - const user = await findUserByUsername('test'); + const user = await getUserByUid(chatId); expect(user).not.toBeUndefined(); expect(sendMessage).toHaveBeenCalledWith( @@ -81,11 +71,10 @@ describe('Bot Commands', () => { describe('help', () => { it('should send help message', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const msg = { - chat: { id: createChat() }, - text: '/help', - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/help', { + createUser: false, + createGroup: false, + }); await emitMsg(msg); @@ -98,18 +87,13 @@ describe('Bot Commands', () => { describe('create_group', () => { it('should create a new group', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: chatId }, - text: '/create_group', - from: { username: user?.username }, - } as TelegramBot.Message; + const { sendMessage, msg, user } = await setupChat('/create_group', { + createGroup: false, + }); await emitMsg(msg); - const group = await findGroupByUserId(user?.id ?? 0); + const group = await findGroupByUserId(user.id); expect(group).not.toBeNull(); expect(sendMessage).toHaveBeenCalledWith( msg.chat.id, @@ -118,16 +102,7 @@ describe('Bot Commands', () => { }); it('should error with existing group', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const group = await createGroup(); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/create_group', - from: { username: user?.username }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/create_group'); await emitMsg(msg); @@ -139,19 +114,12 @@ describe('Bot Commands', () => { }); describe('join_group', () => { - it('should add user to group', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: chatId }, - text: `/join_group ${group.code}`, - from: { username: user?.username }, - } as TelegramBot.Message; - await addUserToGroup(group.id, user?.id ?? 0); + it('should add user to the group', async () => { + const { sendMessage, msg, group } = await setupChat('/join_group', { + addUserToGroup: false, + }); - await emitMsg(msg); + await emitMsg({ ...msg, text: `/join_group ${group.code}` }); expect(sendMessage).toHaveBeenCalledWith( msg.chat.id, @@ -160,14 +128,9 @@ describe('Bot Commands', () => { }); it('should error without group code', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: createChat() }, - text: '/join_group ', - from: { username: user?.username }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/join_group ', { + addUserToGroup: false, + }); await emitMsg(msg); @@ -177,16 +140,12 @@ describe('Bot Commands', () => { ); }); - it('should error without username', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const group = await createGroup(); - const msg = { - chat: { id: createChat() }, - text: `/join_group ${group.code}`, - from: {}, - } as TelegramBot.Message; + it('should error without user', async () => { + const { sendMessage, msg, group } = await setupChat('/join_group code', { + createUser: false, + }); - await emitMsg(msg); + await emitMsg({ ...msg, text: `/join_group ${group.code}` }); expect(sendMessage).toHaveBeenCalledWith( msg.chat.id, @@ -195,14 +154,9 @@ describe('Bot Commands', () => { }); it('should error with wrong group code', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: chatId }, - text: '/join_group 9999', - from: { username: user?.username }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/join_group 9999', { + addUserToGroup: false, + }); await emitMsg(msg); @@ -214,21 +168,12 @@ describe('Bot Commands', () => { }); describe('leave_group', () => { - it('should remove user from group', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: `/leave_group`, - from: { username: user?.username }, - } as TelegramBot.Message; + it('should remove user from the group', async () => { + const { sendMessage, msg, user } = await setupChat('/leave_group'); await emitMsg(msg); - const userGroup = await findGroupByUserId(user?.id ?? 0); + const userGroup = await findGroupByUserId(user.id); expect(userGroup).toBeUndefined(); expect(sendMessage).toHaveBeenCalledWith( @@ -240,16 +185,7 @@ describe('Bot Commands', () => { describe('suggest', () => { it('should suggest a movie', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/suggest Inception', - from: { username: user?.username ?? 0 }, - } as TelegramBot.Message; + const { sendMessage, msg, group } = await setupChat('/suggest Inception'); await emitMsg(msg); @@ -263,11 +199,9 @@ describe('Bot Commands', () => { }); it('should error if no user', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const msg = { - chat: { id: createChat() }, - text: '/suggest Inception', - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/suggest Inception', { + createUser: false, + }); await emitMsg(msg); @@ -278,15 +212,7 @@ describe('Bot Commands', () => { }); it('should error if no movie name', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: createChat() }, - text: '/suggest ', - from: { username: user?.username ?? 0 }, - } as TelegramBot.Message; - const group = await createGroup(); - await addUserToGroup(group.id, user?.id ?? 0); + const { sendMessage, msg, group } = await setupChat('/suggest '); await emitMsg(msg); @@ -301,18 +227,10 @@ describe('Bot Commands', () => { describe('vote', () => { it('should vote for a movie', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: createChat() }, - text: '/vote 1', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; - const group = await createGroup(); - await addUserToGroup(group.id, user?.id ?? 0); + const { sendMessage, msg, group, user } = await setupChat('/vote 1'); const insertedMovie = await suggestMovie( 'Inception', - user?.id ?? 0, + user.id, group.id, 'https://www.kinopoisk.ru/index.php?kp_query=Inception', 'https://www.imdb.com/find/?q=Inception', @@ -333,20 +251,10 @@ describe('Bot Commands', () => { }); it('should not vote for a movie 2 times', async () => { - bot = new TelegramBot('test_token', { polling: true }); - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/vote 1', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg, group, user } = await setupChat('/vote 1'); const insertedMovie = await suggestMovie( 'Inception', - user?.id ?? 0, + user.id, group.id, 'https://www.kinopoisk.ru/index.php?kp_query=Inception', 'https://www.imdb.com/find/?q=Inception', @@ -368,16 +276,7 @@ describe('Bot Commands', () => { }); it('should error without movie code', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const group = await createGroup(); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/vote', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/vote'); await emitMsg(msg); @@ -388,16 +287,7 @@ describe('Bot Commands', () => { }); it('should error with wrong movie code', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const group = await createGroup(); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/vote qwe', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/vote qwe'); await emitMsg(msg); @@ -410,19 +300,10 @@ describe('Bot Commands', () => { describe('list', () => { it('should print current list of movies', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/list', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg, user, group } = await setupChat('/list'); const movie = await suggestMovie( 'Inception', - user?.id ?? 0, + user.id, group.id, 'https://www.kinopoisk.ru/index.php?kp_query=Inception', 'https://www.imdb.com/find/?q=Inception', @@ -437,14 +318,9 @@ describe('Bot Commands', () => { }); it('should error if user not in group', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: createChat() }, - text: '/list', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/list', { + addUserToGroup: false, + }); await emitMsg(msg); expect(sendMessage).toHaveBeenCalledWith( @@ -456,19 +332,10 @@ describe('Bot Commands', () => { describe('watched', () => { it('should delete a movie from the list', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: chatId }, - text: '/watched 1', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; - await addUserToGroup(group.id, user?.id ?? 0); + const { sendMessage, msg, user, group } = await setupChat('/watched 1'); const insertedMovie = await suggestMovie( 'Inception', - user?.id ?? 0, + user.id, group.id, 'https://www.kinopoisk.ru/index.php?kp_query=Inception', 'https://www.imdb.com/find/?q=Inception', @@ -476,10 +343,10 @@ describe('Bot Commands', () => { await emitMsg({ ...msg, - text: `/watched ${insertedMovie?.id ?? 0}`, + text: `/watched ${insertedMovie.id}`, }); - const movie = await findMovieById(insertedMovie?.id ?? 0, group.id); + const movie = await findMovieById(insertedMovie.id, group.id); expect(movie).toBeUndefined(); expect(sendMessage).toHaveBeenCalledWith( msg.chat.id, @@ -490,11 +357,7 @@ describe('Bot Commands', () => { }); it('should error if no movie id', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const msg = { - chat: { id: createChat() }, - text: '/watched ', - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/watched '); await emitMsg(msg); @@ -505,14 +368,10 @@ describe('Bot Commands', () => { }); it('should error if user not in group', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: createChat() }, - text: '/watched 9998', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/watched 9998', { + createGroup: false, + addUserToGroup: false, + }); await emitMsg(msg); @@ -523,16 +382,7 @@ describe('Bot Commands', () => { }); it('should error if wrong movie code', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/watched 9999', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/watched 9999'); await emitMsg(msg); @@ -545,19 +395,10 @@ describe('Bot Commands', () => { describe('veto', () => { it('veto command should veto a movie', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/veto 1', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg, user, group } = await setupChat('/veto 1'); const insertedMovie = await suggestMovie( 'Inception', - user?.id ?? 0, + user.id, group.id, 'https://www.kinopoisk.ru/index.php?kp_query=Inception', 'https://www.imdb.com/find/?q=Inception', @@ -565,10 +406,10 @@ describe('Bot Commands', () => { await emitMsg({ ...msg, - text: `/veto ${insertedMovie?.id ?? 0}`, + text: `/veto ${insertedMovie.id}`, }); - const movie = await findMovieById(insertedMovie?.id ?? 0, group.id); + const movie = await findMovieById(insertedMovie.id, group.id); expect(movie?.is_vetoed).toBe(1); expect(sendMessage).toHaveBeenCalledWith( @@ -578,12 +419,10 @@ describe('Bot Commands', () => { }); it('should error if no movie id', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const msg = { - chat: { id: chatId }, - text: '/veto ', - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/veto ', { + createGroup: false, + addUserToGroup: false, + }); await emitMsg(msg); @@ -594,16 +433,7 @@ describe('Bot Commands', () => { }); it('should error if wrong movie code', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const group = await createGroup(); - const msg = { - chat: { id: chatId }, - text: '/veto 9999', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; - await addUserToGroup(group.id, user?.id ?? 0); + const { sendMessage, msg } = await setupChat('/veto 9999'); await emitMsg(msg); @@ -616,19 +446,10 @@ describe('Bot Commands', () => { describe('random', () => { it('should send a random movie', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - await addUserToGroup(group.id, user?.id ?? 0); - const msg = { - chat: { id: chatId }, - text: '/random', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg, user, group } = await setupChat('/random'); await suggestMovie( 'Inception', - user?.id ?? 0, + user.id, group.id, 'https://www.kinopoisk.ru/index.php?kp_query=Inception', 'https://www.imdb.com/find/?q=Inception', @@ -644,14 +465,10 @@ describe('Bot Commands', () => { }); it('should error if user not in group', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: chatId }, - text: '/random', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; + const { sendMessage, msg } = await setupChat('/random', { + createGroup: false, + addUserToGroup: false, + }); await emitMsg(msg); @@ -662,16 +479,7 @@ describe('Bot Commands', () => { }); it('should error if list is empty', async () => { - const sendMessage = jest.spyOn(bot, 'sendMessage'); - const chatId = createChat(); - const group = await createGroup(); - const user = await createUser(String(chatId)); - const msg = { - chat: { id: chatId }, - text: '/random', - from: { username: user?.username ?? '' }, - } as TelegramBot.Message; - await addUserToGroup(group.id, user?.id ?? 0); + const { sendMessage, msg } = await setupChat('/random'); await emitMsg(msg); diff --git a/src/controllers/bot.ts b/src/controllers/bot.ts index f97c18b..49af386 100644 --- a/src/controllers/bot.ts +++ b/src/controllers/bot.ts @@ -13,14 +13,15 @@ import { markMovieAsWatched, markMovieAsVetoed, hasUserMovieVote, - findUserByUsername, findGroupByUserId, removeUserFromGroup, + getUserByUid, } from '../models'; import texts from '../texts.json'; import { getImdbUrl, getKinopoiskUrl, getMovieDescription } from './helpers'; import { applyMiddlewares, + CheckError, handleCheckErrors, logger, TRule, @@ -29,7 +30,7 @@ import { checkAndGetArg, checkAndGetGroup, checkAndGetMovie, - checkAndGetUserByUsername, + checkAndGetUser, checkAndGetMoviesList, } from './checkers'; @@ -42,11 +43,15 @@ const rawBotHandlers: TRule[] = [ [ /\/start/, (bot) => async (msg) => { - const username = msg.from?.username ?? ''; + const username = msg.from?.username; + const userId = msg.from?.id; - const user = await findUserByUsername(username); + if (!username || !userId) { + throw new CheckError(texts.invalid_user); + } + const user = await getUserByUid(userId); if (!user) { - await createUser(username); + await createUser(username, userId); } bot.sendMessage(msg.chat.id, texts.start); @@ -62,7 +67,7 @@ const rawBotHandlers: TRule[] = [ /\/create_group/, (bot) => async (msg) => { const chatId = msg.chat.id; - const user = await checkAndGetUserByUsername(msg); + const user = await checkAndGetUser(msg); const foundGroup = await findGroupByUserId(user.id); if (foundGroup) { @@ -85,16 +90,21 @@ const rawBotHandlers: TRule[] = [ bot.sendMessage(chatId, texts.group_not_found); return; } - const user = await checkAndGetUserByUsername(msg); - await addUserToGroup(group.id, user.id); - bot.sendMessage(chatId, texts.joined_group); + const user = await checkAndGetUser(msg); + const userGroup = await findGroupByUserId(user.id); + if (userGroup) { + bot.sendMessage(chatId, texts.already_in_group); + } else { + await addUserToGroup(group.id, user.id); + bot.sendMessage(chatId, texts.joined_group); + } }, ], [ /\/leave_group/, (bot) => async (msg) => { const chatId = msg.chat.id; - const user = await checkAndGetUserByUsername(msg); + const user = await checkAndGetUser(msg); const group = await checkAndGetGroup(msg); await removeUserFromGroup(group.id, user.id); @@ -107,7 +117,7 @@ const rawBotHandlers: TRule[] = [ const chatId = msg.chat.id; const movieName = checkAndGetArg(match, texts.no_movie_name); - const user = await checkAndGetUserByUsername(msg); + const user = await checkAndGetUser(msg); const group = await checkAndGetGroup(msg); const movie = await suggestMovie( @@ -133,7 +143,7 @@ const rawBotHandlers: TRule[] = [ 10, ); - const user = await checkAndGetUserByUsername(msg); + const user = await checkAndGetUser(msg); const group = await checkAndGetGroup(msg); const movie = await checkAndGetMovie(movieId, group.id); diff --git a/src/controllers/checkers.ts b/src/controllers/checkers.ts index e41a561..cf825dd 100644 --- a/src/controllers/checkers.ts +++ b/src/controllers/checkers.ts @@ -8,22 +8,22 @@ import { CheckError } from '../middlewares/errorHandler'; import { findGroupByUserId, findMovieById, - findUserByUsername, + getUserByUid, IGroup, IMovie, IUser, listMovies, } from '../models'; -export const checkAndGetUserByUsername = async ( +export const checkAndGetUser = async ( msg: TelegramBot.Message, ): Promise => { - const username = msg.from?.username; + const userId = msg.from?.id; - if (!username) { + if (!userId) { throw new CheckError(texts.user_not_found); } - const user = await findUserByUsername(username); + const user = await getUserByUid(userId); if (!user) { throw new CheckError(texts.user_not_found); } @@ -33,7 +33,7 @@ export const checkAndGetUserByUsername = async ( export const checkAndGetGroup = async ( msg: TelegramBot.Message, ): Promise => { - const user = await checkAndGetUserByUsername(msg); + const user = await checkAndGetUser(msg); const group = await findGroupByUserId(user.id); if (!group) { diff --git a/src/dbController/database.ts b/src/dbController/database.ts index def8162..4d0b64a 100644 --- a/src/dbController/database.ts +++ b/src/dbController/database.ts @@ -18,6 +18,7 @@ export async function initializeDb() { ); CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, + uid TEXT UNIQUE, username TEXT UNIQUE ); CREATE TABLE IF NOT EXISTS movies ( diff --git a/src/lib/setupChat.ts b/src/lib/setupChat.ts new file mode 100644 index 0000000..49ae719 --- /dev/null +++ b/src/lib/setupChat.ts @@ -0,0 +1,87 @@ +// Fix for error: node-telegram-bot-api +// deprecated Automatic enabling of cancellation +// of promises is deprecated In the future +process.env.NTBA_FIX_319 = '1'; +import TelegramBot from 'node-telegram-bot-api'; +import { + addUserToGroup, + createGroup, + createUser, + IGroup, + IUser, +} from '../models'; + +interface IChatData { + sendMessage: jest.SpyInstance; + chatId: number; + user: IUser; + group: IGroup; + msg: TelegramBot.Message; +} + +interface IAvailableActions { + createGroup?: boolean; + createUser?: boolean; + addUserToGroup?: boolean; +} + +export type TSetupChat = { + (command: string): Promise; + ( + command: string, + actions: IAvailableActions & { + createGroup: false; + }, + ): Promise>; + ( + command: string, + actions: IAvailableActions & { + createUser: false; + }, + ): Promise>; + ( + command: string, + actions: IAvailableActions & { + createUser: false; + createGroup: false; + }, + ): Promise>; + ( + command: string, + actions: IAvailableActions & { + addUserToGroup: false; + }, + ): Promise; +}; + +export const createSetupChat = + (bot: TelegramBot, createChat: () => number): TSetupChat => + async ( + command: string, + actions: IAvailableActions = {}, + ): Promise => { + const sendMessage = jest.spyOn(bot, 'sendMessage'); + const chatId = createChat(); + const user = + actions?.createUser !== false + ? await createUser(String(chatId), chatId) + : undefined; + const group = + actions?.createGroup !== false ? await createGroup() : undefined; + if (actions?.addUserToGroup !== false && user && group) { + await addUserToGroup(group.id, user.id); + } + const msg = { + chat: { id: chatId }, + text: command, + from: user ? { username: user?.username, id: chatId } : undefined, + } as TelegramBot.Message; + + return { + sendMessage, + chatId, + user, + group, + msg, + } as IChatData; + }; diff --git a/src/lib/testUtils.ts b/src/lib/testUtils.ts new file mode 100644 index 0000000..4de64b5 --- /dev/null +++ b/src/lib/testUtils.ts @@ -0,0 +1,27 @@ +// Fix for error: node-telegram-bot-api +// deprecated Automatic enabling of cancellation +// of promises is deprecated In the future +process.env.NTBA_FIX_319 = '1'; +import TelegramBot from 'node-telegram-bot-api'; +import { TRule } from '../middlewares'; + +export const createEmit = + (botHandlers: TRule[], bot: TelegramBot) => + async (msg: TelegramBot.Message) => { + const handler = botHandlers.find((handler) => + msg.text ? handler[0].test(msg.text) : false, + ); + if (!handler) { + return; + } + const match = msg.text?.split(' ') ?? null; + const msgHandler = handler[1](bot); + return await msgHandler(msg, match); + }; +export const createCreateChat = () => { + let chatId = 0; + return () => { + chatId += 1; + return chatId; + }; +}; diff --git a/src/models/types.ts b/src/models/types.ts index fad98a0..e170289 100644 --- a/src/models/types.ts +++ b/src/models/types.ts @@ -1 +1,2 @@ +export type UId = number; // external unique id export type TId = number; diff --git a/src/models/user/model.ts b/src/models/user/model.ts index 40022d9..82b3748 100644 --- a/src/models/user/model.ts +++ b/src/models/user/model.ts @@ -1,14 +1,17 @@ import { openDb } from '../../dbController'; -import { TId } from '../types'; +import { UId } from '../types'; import { IUser } from './types'; -export async function createUser(username: string): Promise { +export async function createUser( + username: string, + uid: UId, +): Promise { const db = await openDb(); - const res = await db.run( - `INSERT OR IGNORE INTO users (username) VALUES (?)`, - [username], - ); - return { id: res.lastID as TId, username }; + await db.run(`INSERT OR IGNORE INTO users (username, uid) VALUES (?, ?)`, [ + username, + uid, + ]); + return await db.get(`SELECT * FROM users WHERE uid = ?`, [uid]); } export async function findUserByUsername( @@ -17,3 +20,8 @@ export async function findUserByUsername( const db = await openDb(); return db.get(`SELECT * FROM users WHERE username = ?`, [username]); } + +export async function getUserByUid(uid: UId): Promise { + const db = await openDb(); + return db.get(`SELECT * FROM users WHERE uid =?`, [uid]); +} diff --git a/src/models/user/types.ts b/src/models/user/types.ts index 5bc7c22..ee017bc 100644 --- a/src/models/user/types.ts +++ b/src/models/user/types.ts @@ -1,6 +1,7 @@ -import { TId } from '../types'; +import { TId, UId } from '../types'; export interface IUser { id: TId; + uid: UId; username: string; } diff --git a/src/texts.json b/src/texts.json index d2f7cfd..bc93999 100644 --- a/src/texts.json +++ b/src/texts.json @@ -3,6 +3,7 @@ "help": "Список команд:\n/create_group - создать группу\n/join_group <код> - присоединиться к группе\n/suggest <название фильма> - предложить фильм\n/vote <номер фильма> - проголосовать за фильм\n/list_movies - показать список фильмов\n/watched <номер фильма> - отметить фильм как просмотренный\n/random - вывести случайный фильм\n/veto <номер фильма> - убрать фильм из случайных фильмов", "group_created": "Группа создана! Код для присоединения:", "joined_group": "Вы присоединились к группе!", + "already_in_group": "Вы уже состоите в группе. Для выхода выполните /leave_group", "group_not_found": "Группа с таким кодом не найдена.", "group_already_created": "Группа уже создана. Код присоединения: ", "left_group": "Вы покинули группу.", @@ -18,5 +19,6 @@ "movie_list": "Список фильмов:\n", "movie_list_empty": "Список фильмов пуст.", "movie_watched": "Фильм отмечен как просмотренный и удален из списка.", - "vetoed": "Фильм удален из случайных фильмов." + "vetoed": "Фильм удален из случайных фильмов.", + "invalid_user": "Вы не залогинены." } From b0cb8d0734a8bff9f1da8f004490cb5a9ed75a23 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Sun, 25 Aug 2024 15:14:42 +0200 Subject: [PATCH 09/11] Up test coverage --- coverage/badge-branches.svg | 2 +- coverage/badge-lines.svg | 2 +- coverage/badge-statements.svg | 2 +- src/controllers/bot.test.ts | 39 +++++++++++++++++++ src/dbController/database.test.ts | 62 ++++++++++++++++++------------- src/models/user/model.ts | 7 ---- 6 files changed, 79 insertions(+), 35 deletions(-) diff --git a/coverage/badge-branches.svg b/coverage/badge-branches.svg index 020b90b..8538b1f 100644 --- a/coverage/badge-branches.svg +++ b/coverage/badge-branches.svg @@ -1 +1 @@ -Coverage: 82.45%Coverage82.45% \ No newline at end of file +Coverage: 84.78%Coverage84.78% \ No newline at end of file diff --git a/coverage/badge-lines.svg b/coverage/badge-lines.svg index e6a7d2a..68a6c96 100644 --- a/coverage/badge-lines.svg +++ b/coverage/badge-lines.svg @@ -1 +1 @@ -Coverage: 99.11%Coverage99.11% \ No newline at end of file +Coverage: 98.93%Coverage98.93% \ No newline at end of file diff --git a/coverage/badge-statements.svg b/coverage/badge-statements.svg index e3d81bb..a3e4a8f 100644 --- a/coverage/badge-statements.svg +++ b/coverage/badge-statements.svg @@ -1 +1 @@ -Coverage: 99.22%Coverage99.22% \ No newline at end of file +Coverage: 99.05%Coverage99.05% \ No newline at end of file diff --git a/src/controllers/bot.test.ts b/src/controllers/bot.test.ts index ba79447..73d7fcd 100644 --- a/src/controllers/bot.test.ts +++ b/src/controllers/bot.test.ts @@ -67,6 +67,20 @@ describe('Bot Commands', () => { expect.stringContaining('Привет!'), ); }); + + it('should error with invalid user', async () => { + const { sendMessage, msg } = await setupChat('/start', { + createUser: false, + createGroup: false, + }); + + await emitMsg(msg); + + expect(sendMessage).toHaveBeenCalledWith( + msg.chat.id, + expect.stringContaining('Вы не залогинены'), + ); + }); }); describe('help', () => { @@ -165,6 +179,18 @@ describe('Bot Commands', () => { expect.stringContaining('Группа с таким кодом не найдена'), ); }); + + it('should error with user already in the group', async () => { + const { sendMessage, msg, group } = await setupChat('/join_group'); + + await emitMsg({ ...msg, text: `/join_group ${group.code}` }); + await emitMsg({ ...msg, text: `/join_group ${group.code}` }); + + expect(sendMessage).toHaveBeenLastCalledWith( + msg.chat.id, + expect.stringContaining('Вы уже состоите в группе'), + ); + }); }); describe('leave_group', () => { @@ -181,6 +207,19 @@ describe('Bot Commands', () => { expect.stringContaining('Вы покинули группу'), ); }); + + it('should error without user', async () => { + const { sendMessage, msg } = await setupChat('/leave_group', { + createUser: false, + }); + + await emitMsg(msg); + + expect(sendMessage).toHaveBeenCalledWith( + msg.chat.id, + expect.stringContaining('Пользователь не найден'), + ); + }); }); describe('suggest', () => { diff --git a/src/dbController/database.test.ts b/src/dbController/database.test.ts index a5cd758..dda95aa 100644 --- a/src/dbController/database.test.ts +++ b/src/dbController/database.test.ts @@ -1,5 +1,5 @@ import fs from 'fs'; -import { openDb, initializeDb } from './database'; +import { openDb, initializeDb, listAllTablesData } from './database'; const DATABASE_FILENAME = './db/test_database.db'; @@ -16,32 +16,44 @@ describe('Database Tests', () => { fs.rmSync(DATABASE_FILENAME); }); - it('should insert and retrieve group', async () => { - const db = await openDb(); - await db.run(`INSERT INTO groups (code) VALUES ('test_code')`); - const group = await db.get(`SELECT * FROM groups WHERE code = 'test_code'`); - expect(group.code).toBe('test_code'); - }); + describe('Tables creation and data insertion', () => { + it('should insert and retrieve group', async () => { + const db = await openDb(); + await db.run(`INSERT INTO groups (code) VALUES ('test_code')`); + const group = await db.get( + `SELECT * FROM groups WHERE code = 'test_code'`, + ); + expect(group.code).toBe('test_code'); + }); + + it('should insert and retrieve user', async () => { + const db = await openDb(); + const res = await db.run(`INSERT INTO users DEFAULT VALUES`); + const user = await db.get(`SELECT * FROM users WHERE id = ?`, [ + res.lastID as number, + ]); + expect(user.id).toBe(res.lastID as number); + }); - it('should insert and retrieve user', async () => { - const db = await openDb(); - const res = await db.run(`INSERT INTO users DEFAULT VALUES`); - const user = await db.get(`SELECT * FROM users WHERE id = ?`, [ - res.lastID as number, - ]); - expect(user.id).toBe(res.lastID as number); + it('should insert and retrieve movie', async () => { + const db = await openDb(); + await db.run( + `INSERT INTO movies (name, suggested_by, group_id, kinopoisk_link, imdb_link) VALUES ('Test Movie', 1, 1, 'http://example1.com', 'http://example2.com')`, + ); + const movie = await db.get( + `SELECT * FROM movies WHERE name = 'Test Movie'`, + ); + expect(movie.name).toBe('Test Movie'); + expect(movie.kinopoisk_link).toBe('http://example1.com'); + expect(movie.imdb_link).toBe('http://example2.com'); + }); }); - it('should insert and retrieve movie', async () => { - const db = await openDb(); - await db.run( - `INSERT INTO movies (name, suggested_by, group_id, kinopoisk_link, imdb_link) VALUES ('Test Movie', 1, 1, 'http://example1.com', 'http://example2.com')`, - ); - const movie = await db.get( - `SELECT * FROM movies WHERE name = 'Test Movie'`, - ); - expect(movie.name).toBe('Test Movie'); - expect(movie.kinopoisk_link).toBe('http://example1.com'); - expect(movie.imdb_link).toBe('http://example2.com'); + describe('List all tables data', () => { + it('should return all tables data', async () => { + jest.spyOn(console, 'log').mockImplementation(() => undefined); + await listAllTablesData(); + expect(console.log).toBeCalledTimes(1); + }); }); }); diff --git a/src/models/user/model.ts b/src/models/user/model.ts index 82b3748..abf30fa 100644 --- a/src/models/user/model.ts +++ b/src/models/user/model.ts @@ -14,13 +14,6 @@ export async function createUser( return await db.get(`SELECT * FROM users WHERE uid = ?`, [uid]); } -export async function findUserByUsername( - username: string, -): Promise { - const db = await openDb(); - return db.get(`SELECT * FROM users WHERE username = ?`, [username]); -} - export async function getUserByUid(uid: UId): Promise { const db = await openDb(); return db.get(`SELECT * FROM users WHERE uid =?`, [uid]); From ce4bfd0736c7db43177abd3316db8857d48a2d29 Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Tue, 27 Aug 2024 11:31:17 +0200 Subject: [PATCH 10/11] Add mock middleware for testing --- nodemon.json | 6 ++ package-lock.json | 149 +++++++++++++++++++++++++++ package.json | 5 +- src/controllers/bot.ts | 2 + src/middlewares/index.ts | 1 + src/middlewares/logger/logger.ts | 11 +- src/middlewares/mockData/index.ts | 1 + src/middlewares/mockData/mock.json | 9 ++ src/middlewares/mockData/mockData.ts | 18 ++++ 9 files changed, 199 insertions(+), 3 deletions(-) create mode 100644 nodemon.json create mode 100644 src/middlewares/mockData/index.ts create mode 100644 src/middlewares/mockData/mock.json create mode 100644 src/middlewares/mockData/mockData.ts diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 0000000..ed4f0f9 --- /dev/null +++ b/nodemon.json @@ -0,0 +1,6 @@ +{ + "watch": ["src"], + "ext": "ts,json", + "ignore": ["src/**/*.test.ts"], + "exec": "npm run start" +} diff --git a/package-lock.json b/package-lock.json index f8499f2..971498a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "eslint": "^7.32.0", "jest": "^27.5.1", "jest-coverage-badges": "^1.0.0", + "nodemon": "^3.1.4", "prettier": "^2.8.8", "ts-jest": "^27.1.5", "ts-node": "^10.9.2", @@ -1965,6 +1966,18 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -2242,6 +2255,30 @@ "node": ">=10" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -3909,6 +3946,12 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -4053,6 +4096,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -5666,6 +5721,55 @@ "ms": "^2.1.1" } }, + "node_modules/nodemon": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", + "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -6133,6 +6237,12 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "node_modules/pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", @@ -6244,6 +6354,18 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -6740,6 +6862,18 @@ "simple-concat": "^1.0.0" } }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -7314,6 +7448,15 @@ "node": ">=8.0" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -7625,6 +7768,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", diff --git a/package.json b/package.json index 8f4f374..41d7504 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "main": "dist/start.js", "scripts": { "init:db": "ts-node src/genDB.ts", - "start:dev": "DEBUG_OUTPUT=1 export $(cat .env | xargs) && ts-node src/start.ts", + "reinit:db": "rm -f db/database.db && npm run init:db", + "start": "ts-node src/start.ts", + "start:dev": "DEBUG_OUTPUT=1 export $(cat .env | xargs) && npm run reinit:db && nodemon", "build": "tsc", "check": "tsc --noEmit", "lint": "eslint 'src/**/*.{ts,tsx}'", @@ -41,6 +43,7 @@ "eslint": "^7.32.0", "jest": "^27.5.1", "jest-coverage-badges": "^1.0.0", + "nodemon": "^3.1.4", "prettier": "^2.8.8", "ts-jest": "^27.1.5", "ts-node": "^10.9.2", diff --git a/src/controllers/bot.ts b/src/controllers/bot.ts index 49af386..5a4f34a 100644 --- a/src/controllers/bot.ts +++ b/src/controllers/bot.ts @@ -24,6 +24,7 @@ import { CheckError, handleCheckErrors, logger, + mockData, TRule, } from '../middlewares'; import { @@ -218,6 +219,7 @@ const rawBotHandlers: TRule[] = [ ]; export const botHandlers = applyMiddlewares(rawBotHandlers, [ + mockData, logger, handleCheckErrors, ]); diff --git a/src/middlewares/index.ts b/src/middlewares/index.ts index 1ba0107..8ddadb4 100644 --- a/src/middlewares/index.ts +++ b/src/middlewares/index.ts @@ -1,4 +1,5 @@ export * from './errorHandler'; export * from './logger'; +export * from './mockData'; export * from './applyMiddlewares'; export * from './controllers.types'; diff --git a/src/middlewares/logger/logger.ts b/src/middlewares/logger/logger.ts index 3c4dc8c..ccb6498 100644 --- a/src/middlewares/logger/logger.ts +++ b/src/middlewares/logger/logger.ts @@ -4,10 +4,17 @@ import { TMiddleware } from '../controllers.types'; export const logger: TMiddleware = (handler) => (bot) => async (msg, match) => { if (process.env.DEBUG_OUTPUT === '1') { - log(`User: ${msg.from?.username}, Command: ${msg.text}`); - log('DB:'); + log( + `User: ${msg.from?.username}, ChatId: ${msg.chat.id}, Command: ${msg.text}`, + ); + log('DB(before):'); await listAllTablesData(); } await handler(bot)(msg, match); + + if (process.env.DEBUG_OUTPUT === '1') { + log('DB(after):'); + await listAllTablesData(); + } }; diff --git a/src/middlewares/mockData/index.ts b/src/middlewares/mockData/index.ts new file mode 100644 index 0000000..c9abc94 --- /dev/null +++ b/src/middlewares/mockData/index.ts @@ -0,0 +1 @@ +export * from './mockData'; diff --git a/src/middlewares/mockData/mock.json b/src/middlewares/mockData/mock.json new file mode 100644 index 0000000..9df4dcc --- /dev/null +++ b/src/middlewares/mockData/mock.json @@ -0,0 +1,9 @@ +{ + "from": { + "id": 987654321, + "username": "john_doe", + "first_name": "John", + "last_name": "Doe", + "is_bot": false + } +} diff --git a/src/middlewares/mockData/mockData.ts b/src/middlewares/mockData/mockData.ts new file mode 100644 index 0000000..77b1db2 --- /dev/null +++ b/src/middlewares/mockData/mockData.ts @@ -0,0 +1,18 @@ +import { TMiddleware } from '../controllers.types'; +import mock from './mock.json'; + +export const mockData: TMiddleware = + (handler) => (bot) => async (msg, match) => { + let newMsg = msg; + if (process.env.DEBUG_OUTPUT === '1') { + newMsg = { + ...msg, + from: { + ...msg.from, + ...mock.from, + }, + }; + } + + await handler(bot)(newMsg, match); + }; From 1284c0f588f8e91f64dd0329c9eb9557bca548cd Mon Sep 17 00:00:00 2001 From: Evgenii Guzhikhin Date: Tue, 27 Aug 2024 11:35:30 +0200 Subject: [PATCH 11/11] Fix --- src/middlewares/logger/logger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middlewares/logger/logger.ts b/src/middlewares/logger/logger.ts index ccb6498..0273b88 100644 --- a/src/middlewares/logger/logger.ts +++ b/src/middlewares/logger/logger.ts @@ -5,7 +5,7 @@ import { TMiddleware } from '../controllers.types'; export const logger: TMiddleware = (handler) => (bot) => async (msg, match) => { if (process.env.DEBUG_OUTPUT === '1') { log( - `User: ${msg.from?.username}, ChatId: ${msg.chat.id}, Command: ${msg.text}`, + `User: ${msg.from?.username}, ChatId: ${msg.chat?.id}, Command: ${msg.text}`, ); log('DB(before):'); await listAllTablesData();