From 02939d57a807c7468b7345b2d146a533d47f5eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCller?= Date: Tue, 20 Apr 2021 09:40:15 +0200 Subject: [PATCH] Adding API endpoint for twitch highlights marker --- .gitignore | 1 + app.ts | 16 +- package-lock.json | 170 +++++++++++++++++- package.json | 4 +- .../addHighlight.routes.config.ts | 41 +++++ .../addHighlights.service.ts | 39 ++++ 6 files changed, 262 insertions(+), 9 deletions(-) create mode 100644 src/models/twitch-highlight-marker/addHighlight.routes.config.ts create mode 100644 src/models/twitch-highlight-marker/addHighlights.service.ts diff --git a/.gitignore b/.gitignore index 0c22f4f..b9f9ecd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # IntelliJ Files .idea **/*.iml +.env diff --git a/app.ts b/app.ts index b910137..955faac 100644 --- a/app.ts +++ b/app.ts @@ -1,13 +1,26 @@ import express from 'express'; import * as http from 'http'; import * as bodyparser from 'body-parser'; +import * as dotenv from 'dotenv'; + +dotenv.config(); + +if (!process.env.PORT) { + console.log('No port'); + process.exit(1); +} + +const port: number = parseInt(process.env.PORT as string, 10); import {CommonRoutesConfig} from './src/common/common.routes.config'; +// DHBW Service import {GeneralInfoRoutes} from './src/models/dhbw-service/generalInfo.routes.config'; +// Twitch Highlight Marker +import {AddHighlightRoutes} from './src/models/twitch-highlight-marker/addHighlight.routes.config'; + const app: express.Application = express(); const server: http.Server = http.createServer(app); -const port: Number = 443; const routes: Array = []; // here we are adding middleware to parse all incoming requests as JSON @@ -16,6 +29,7 @@ app.use(bodyparser.json()); // here we are adding the UserRoutes to our array, // after sending the Express.js application object to have the routes added to our app! routes.push(new GeneralInfoRoutes(app)); +routes.push(new AddHighlightRoutes(app)); // this is a simple route to make sure everything is working properly app.get('/', (req: express.Request, res: express.Response) => { diff --git a/package-lock.json b/package-lock.json index ef873fb..f49fd69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,18 @@ { - "name": "PlutoDev ExpressAPI", + "name": "PlutoDevExpressAPI", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "PlutoDev ExpressAPI", + "name": "PlutoDevExpressAPI", "version": "1.0.0", "license": "ISC", "dependencies": { "debug": "^4.3.1", - "express": "^4.17.1" + "dotenv": "^8.2.0", + "express": "^4.17.1", + "mariadb": "^2.5.3" }, "devDependencies": { "@types/debug": "^4.1.5", @@ -94,6 +96,11 @@ "@types/range-parser": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.7", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", + "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==" + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -103,8 +110,7 @@ "node_modules/@types/node": { "version": "14.14.28", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.28.tgz", - "integrity": "sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g==", - "dev": true + "integrity": "sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g==" }, "node_modules/@types/qs": { "version": "6.9.5", @@ -327,6 +333,14 @@ } } }, + "node_modules/denque": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", + "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -349,6 +363,14 @@ "node": ">=0.3.1" } }, + "node_modules/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "engines": { + "node": ">=8" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -629,6 +651,39 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/mariadb": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mariadb/-/mariadb-2.5.3.tgz", + "integrity": "sha512-9ZbQ1zLqasLCQy6KDcPHtX7EUIMBlQ8p64gNR61+yfpCIWjPDji3aR56LvwbOz1QnQbVgYBOJ4J/pHoFN5MR+w==", + "dependencies": { + "@types/geojson": "^7946.0.7", + "@types/node": "^14.14.28", + "denque": "^1.4.1", + "iconv-lite": "^0.6.2", + "long": "^4.0.0", + "moment-timezone": "^0.5.33", + "please-upgrade-node": "^3.2.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "node_modules/mariadb/node_modules/iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -710,6 +765,25 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.33", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", + "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -771,6 +845,14 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dependencies": { + "semver-compare": "^1.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -845,6 +927,11 @@ "semver": "bin/semver" } }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + }, "node_modules/send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -1138,6 +1225,11 @@ "@types/range-parser": "*" } }, + "@types/geojson": { + "version": "7946.0.7", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", + "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==" + }, "@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -1147,8 +1239,7 @@ "@types/node": { "version": "14.14.28", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.28.tgz", - "integrity": "sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g==", - "dev": true + "integrity": "sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g==" }, "@types/qs": { "version": "6.9.5", @@ -1338,6 +1429,11 @@ "ms": "2.1.2" } }, + "denque": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", + "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1354,6 +1450,11 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1583,6 +1684,35 @@ "esprima": "^4.0.0" } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "mariadb": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mariadb/-/mariadb-2.5.3.tgz", + "integrity": "sha512-9ZbQ1zLqasLCQy6KDcPHtX7EUIMBlQ8p64gNR61+yfpCIWjPDji3aR56LvwbOz1QnQbVgYBOJ4J/pHoFN5MR+w==", + "requires": { + "@types/geojson": "^7946.0.7", + "@types/node": "^14.14.28", + "denque": "^1.4.1", + "iconv-lite": "^0.6.2", + "long": "^4.0.0", + "moment-timezone": "^0.5.33", + "please-upgrade-node": "^3.2.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1640,6 +1770,19 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-timezone": { + "version": "0.5.33", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", + "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "requires": { + "moment": ">= 2.9.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1689,6 +1832,14 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "requires": { + "semver-compare": "^1.0.0" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -1745,6 +1896,11 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", diff --git a/package.json b/package.json index 893e93d..9305b32 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "license": "ISC", "dependencies": { "debug": "^4.3.1", - "express": "^4.17.1" + "dotenv": "^8.2.0", + "express": "^4.17.1", + "mariadb": "^2.5.3" }, "devDependencies": { "@types/debug": "^4.1.5", diff --git a/src/models/twitch-highlight-marker/addHighlight.routes.config.ts b/src/models/twitch-highlight-marker/addHighlight.routes.config.ts new file mode 100644 index 0000000..42838b5 --- /dev/null +++ b/src/models/twitch-highlight-marker/addHighlight.routes.config.ts @@ -0,0 +1,41 @@ +import {CommonRoutesConfig} from '../../common/common.routes.config'; +import express from 'express'; +import * as AddHighlightService from './addHighlights.service'; +import * as dotenv from 'dotenv'; + +dotenv.config(); + +export class AddHighlightRoutes extends CommonRoutesConfig { + constructor(app: express.Application) { + super(app, 'AddHighlightRoutes'); + } + + configureRoutes() { + this.app.route(`/twitch-highlight-marker/addHighlight`) + .get((req: express.Request, res: express.Response) => { + res.status(200).send(`GET endpoint not defined.`); + }) + .post((req: express.Request, res: express.Response) => { + // Check input params + const body = req.body; + + if(body.access_key !== process.env.TWITCH_HIGHLIGHTS_ACCESS_KEY){ + // Unauthorized, return error + res.type('application/json'); + res.status(403).send('{"status": "error", "description": "Unauthorized."}'); + } else if(!body.streamer || !body.stream_id || !body.stream_game || !body.timestamp || !body.description || !body.username){ + // Missing params, return error + res.type('application/json'); + res.status(400).send('{"status": "error", "description": "Missing parameters."}'); + } else { + // Everything fine, return success + AddHighlightService.createHighlightEntry(body); + + res.type('application/json'); + res.status(200).send('{"status": "success", "description": ""}'); + } + }); + + return this.app; + } +} diff --git a/src/models/twitch-highlight-marker/addHighlights.service.ts b/src/models/twitch-highlight-marker/addHighlights.service.ts new file mode 100644 index 0000000..dafaa92 --- /dev/null +++ b/src/models/twitch-highlight-marker/addHighlights.service.ts @@ -0,0 +1,39 @@ +import * as dotenv from 'dotenv'; + +dotenv.config(); + +const mariadb = require('mariadb'); +const pool = mariadb.createPool({ + host: process.env.DB_HOST, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.TWITCH_HIGHLIGHTS_DATABASE, + connectionLimit: 5 +}); + +export const createHighlightEntry = async (req_body: any) => { + let conn; + let price: any; + try { + conn = await pool.getConnection(); + + const streamers = await conn.query('SELECT streamer_id FROM streamers WHERE username = ?', req_body.streamer); + let streamer_id: number = -1; + + for (let row in streamers) { + if (row !== 'meta') { + streamer_id = streamers[row].streamer_id; + } + } + + const params = [streamer_id, req_body.stream_id, req_body.description, req_body.timestamp, req_body.username, req_body.stream_game]; + + const rows = await conn.query('INSERT INTO highlights (streamer_id, stream_id, description, stream_timestamp, issuing_user, game) VALUES (?, ?, ?, ?, ?, ?)', params); + } catch (err) { + throw err; + } finally { + if (conn) { + conn.end(); + } + } +}