From ce89a4207404701bba7ddd9d97c3f1ff6bfe2bc8 Mon Sep 17 00:00:00 2001 From: Peber Date: Thu, 14 Nov 2024 12:54:51 -0500 Subject: [PATCH 1/7] updating app --- src/app.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/app.js b/src/app.js index 84b51b8..7c77671 100644 --- a/src/app.js +++ b/src/app.js @@ -6,19 +6,9 @@ require('dotenv').config() const { EventsTable } = require('./dbObjects.js'); const { exec } = require('node:child_process'); const { execute } = require('./commands/utility/create_event.js'); -const discordToken = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); -const client = new Client({ intents: [GatewayIntentBits.Guilds] }); - - -// in events table we have -// name, description, location, link, registration_url, event_guide, discipline, date, distances +//const discordToken = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); -try { - const discordToken2 = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); - console.log(discordToken2); -} catch (err) { - console.error(err); -} +const client = new Client({ intents: [GatewayIntentBits.Guilds] }); client.commands = new Collection(); const foldersPath = path.join(__dirname, 'commands'); From 20fbb7ae9d5594dfc8a10d816d62b04b9b1f1902 Mon Sep 17 00:00:00 2001 From: "GitHub-Actions[bot]" Date: Wed, 13 Nov 2024 03:23:08 +0000 Subject: [PATCH 2/7] Bot: Updating CHANGELOG and README for release based on #12 --- CHANGELOG.md | 7 +++++++ config/event-buddy-deployment.yaml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c5285a..0cb0dac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Changelog +### Version 0.0.5 + +#### feature +* PR [#12](https://github.com/petercort/FBF-Event-Buddy/pull/12) - Update 2 + + + ### Version 0.0.4 #### bugfix diff --git a/config/event-buddy-deployment.yaml b/config/event-buddy-deployment.yaml index 8b698e9..0e6cb74 100644 --- a/config/event-buddy-deployment.yaml +++ b/config/event-buddy-deployment.yaml @@ -14,7 +14,7 @@ spec: app: event-buddy spec: containers: - - image: ghcr.io/petercort/event-buddy:0.0.4 + - image: ghcr.io/petercort/event-buddy:0.0.5 name: event-buddy ports: - containerPort: 80 From 150e4a3b21609be02ae1834565050f8dc8dfdb09 Mon Sep 17 00:00:00 2001 From: Peber Date: Thu, 26 Dec 2024 20:46:40 -0500 Subject: [PATCH 3/7] resolving merge --- package-lock.json | 360 +++++++++++++------- package.json | 3 +- src/app.js | 12 +- src/commands.js | 6 +- src/commands/utility/connect_strava.js | 30 ++ src/commands/utility/get_all_bikes.js | 24 ++ src/commands/utility/get_bike_by_name.js | 30 ++ src/commands/utility/get_last_ride.js | 41 +++ src/commands/utility/i_waxed_my_chain.js | 52 +++ src/commands/utility/reload.js | 31 ++ src/commands/utility/sync_bikes.js | 62 ++++ src/dbObjects.js | 5 +- src/models/bikes.js | 37 ++ src/models/users.js | 14 + src/shared_library/strava_authentication.js | 62 ++++ src/strava_webhook.js | 147 ++++++++ src/utils.js | 2 - 17 files changed, 787 insertions(+), 131 deletions(-) create mode 100644 src/commands/utility/connect_strava.js create mode 100644 src/commands/utility/get_all_bikes.js create mode 100644 src/commands/utility/get_bike_by_name.js create mode 100644 src/commands/utility/get_last_ride.js create mode 100644 src/commands/utility/i_waxed_my_chain.js create mode 100644 src/commands/utility/reload.js create mode 100644 src/commands/utility/sync_bikes.js create mode 100644 src/models/bikes.js create mode 100644 src/models/users.js create mode 100644 src/shared_library/strava_authentication.js create mode 100644 src/strava_webhook.js diff --git a/package-lock.json b/package-lock.json index 43e22af..59aa09a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,10 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "axios": "^1.7.9", "discord-interactions": "^4.0.0", "discord.js": "^14.16.3", - "dotenv": "^16.4.5", + "dotenv": "^16.4.7", "express": "^4.18.2", "fbf-event-buddy": "file:", "sequelize": "^6.37.5", @@ -246,11 +247,11 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "22.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", - "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/@types/validator": { @@ -306,9 +307,9 @@ } }, "node_modules/agent-base/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -400,6 +401,21 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -560,16 +576,25 @@ "node": ">= 10" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -628,6 +653,17 @@ "color-support": "bin.js" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -702,20 +738,12 @@ "node": ">=4.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.4.0" } }, "node_modules/delegates": { @@ -788,9 +816,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "engines": { "node": ">=12" }, @@ -803,6 +831,19 @@ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -867,12 +908,9 @@ "optional": true }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "engines": { "node": ">= 0.4" } @@ -885,6 +923,17 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -907,9 +956,9 @@ } }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -930,7 +979,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -945,6 +994,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/fast-deep-equal": { @@ -990,6 +1043,38 @@ "node": ">= 0.8" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1071,15 +1156,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -1127,11 +1217,11 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1152,32 +1242,10 @@ "node": ">=4" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "engines": { "node": ">= 0.4" }, @@ -1238,9 +1306,9 @@ } }, "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -1274,9 +1342,9 @@ } }, "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -1538,6 +1606,14 @@ "node": ">= 10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1805,9 +1881,9 @@ } }, "node_modules/nodemon": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", - "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", "dev": true, "dependencies": { "chokidar": "^3.5.2", @@ -1833,9 +1909,9 @@ } }, "node_modules/nodemon/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "dependencies": { "ms": "^2.1.3" @@ -1958,9 +2034,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "node_modules/pg-connection-string": { "version": "2.7.0", @@ -2035,6 +2111,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -2296,9 +2377,9 @@ } }, "node_modules/sequelize/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { "ms": "^2.1.3" }, @@ -2336,36 +2417,71 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "optional": true }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dependencies": { - "define-data-property": "^1.1.4", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -2474,9 +2590,9 @@ } }, "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -2736,9 +2852,9 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/unique-filename": { "version": "1.1.1", diff --git a/package.json b/package.json index d65df73..04d9add 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,10 @@ "author": "Peter Cort", "license": "MIT", "dependencies": { + "axios": "^1.7.9", "discord-interactions": "^4.0.0", "discord.js": "^14.16.3", - "dotenv": "^16.4.5", + "dotenv": "^16.4.7", "express": "^4.18.2", "fbf-event-buddy": "file:", "sequelize": "^6.37.5", diff --git a/src/app.js b/src/app.js index 7c77671..bc6729c 100644 --- a/src/app.js +++ b/src/app.js @@ -2,11 +2,10 @@ const fs = require('node:fs'); const path = require('node:path'); const { Client, Collection, Events, GatewayIntentBits } = require('discord.js'); const { Op } = require('sequelize'); -require('dotenv').config() -const { EventsTable } = require('./dbObjects.js'); +const { EventsTable, UsersTable, BikesTable } = require('./dbObjects.js'); const { exec } = require('node:child_process'); const { execute } = require('./commands/utility/create_event.js'); -//const discordToken = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); +const discordToken = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); @@ -30,6 +29,10 @@ for (const folder of commandFolders) { client.once(Events.ClientReady, readyClient => { EventsTable.sync({ alter: true }); + //UsersTable.sync({ alter: true, force: true }); + UsersTable.sync(); + //BikesTable.sync({ alter: true, force: true }); + BikesTable.sync(); console.log(`Ready! Logged in as ${readyClient.user.tag}`); }); @@ -54,4 +57,7 @@ client.on(Events.InteractionCreate, async interaction => { } }); +// Start the Strava webhook server +require('./strava_webhook.js'); + client.login(discordToken); diff --git a/src/commands.js b/src/commands.js index 018a655..42ef188 100644 --- a/src/commands.js +++ b/src/commands.js @@ -12,6 +12,7 @@ const foldersPath = path.join(__dirname, 'commands'); const commandFolders = fs.readdirSync(foldersPath); for (const folder of commandFolders) { + console.log(`[INFO] Processing commands in folder: ${folder}`); // Grab all the command files from the commands directory you created earlier const commandsPath = path.join(foldersPath, folder); const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); @@ -40,7 +41,10 @@ const rest = new REST().setToken(discordToken); Routes.applicationGuildCommands(appId, guildId), { body: commands }, ); - + await rest.put( + Routes.applicationCommands(appId), + { body: commands }, + ); console.log(`Successfully reloaded ${data.length} application (/) commands.`); } catch (error) { // And of course, make sure you catch and log any errors! diff --git a/src/commands/utility/connect_strava.js b/src/commands/utility/connect_strava.js new file mode 100644 index 0000000..6997763 --- /dev/null +++ b/src/commands/utility/connect_strava.js @@ -0,0 +1,30 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { EmbedBuilder } = require('discord.js'); +const axios = require('axios'); +const { UsersTable } = require('../../dbObjects.js'); // Assuming you have a UsersTable to store user data +const fs = require('node:fs'); +const path = require('node:path'); +// load strava configuration +const STRAVA_CLIENT_ID = fs.readFileSync("/mnt/secrets-store/STRAVA_CLIENT_ID", 'utf8'); +const STRAVA_REDIRECT_URI = fs.readFileSync("/mnt/secrets-store/STRAVA_REDIRECT_URI", 'utf8'); + + +module.exports = { + data: new SlashCommandBuilder() + .setName('connect_strava') + .setDescription('Connect your Strava account to collect ride data.'), + async execute(interaction) { + const userId = interaction.user.id; + const stravaAuthUrl = `https://www.strava.com/oauth/authorize?client_id=${STRAVA_CLIENT_ID}&response_type=code&redirect_uri=${STRAVA_REDIRECT_URI}/${userId}&scope=read,activity:read_all,profile:read_all`; + + const embed = new EmbedBuilder() + .setTitle('Connect Strava') + .setDescription(`[Click here to connect your Strava account](${stravaAuthUrl})`) + .setColor('#FC4C02'); + + await interaction.reply({ embeds: [embed], ephemeral: true }); + + // Save the user ID to the database to track the connection process + await UsersTable.upsert({ userId, strava_connected: false }); + }, +}; \ No newline at end of file diff --git a/src/commands/utility/get_all_bikes.js b/src/commands/utility/get_all_bikes.js new file mode 100644 index 0000000..8552ccd --- /dev/null +++ b/src/commands/utility/get_all_bikes.js @@ -0,0 +1,24 @@ +const { SlashCommandBuilder } = require('discord.js'); +const { BikesTable } = require('../../dbObjects.js'); +module.exports = { + data: new SlashCommandBuilder() + .setName('get_all_bikes') + .setDescription('Get all your bikes!'), + async execute(interaction) { + const userId = interaction.user.id; + + try { + // Query the BikesTable to get all bikes for the user + const bikes = await BikesTable.findAll({ where: { userId } }); + + if (bikes.length === 0) { + return await interaction.reply('No bikes found.'); + } + const bikeList = bikes.map(bike => `${bike.name} (${bike.brand} ${bike.model})`).join('\n'); + return await interaction.reply(`Your bikes:\n${bikeList}`); + } catch (error) { + console.error('Error fetching bikes:', error); + return await interaction.reply('There was an error fetching your bikes.'); + } + }, +}; \ No newline at end of file diff --git a/src/commands/utility/get_bike_by_name.js b/src/commands/utility/get_bike_by_name.js new file mode 100644 index 0000000..94cc997 --- /dev/null +++ b/src/commands/utility/get_bike_by_name.js @@ -0,0 +1,30 @@ +const { SlashCommandBuilder } = require('discord.js'); +const { BikesTable } = require('../../dbObjects.js'); +module.exports = { + data: new SlashCommandBuilder() + .setName('get_bike_by_name') + .setDescription('Get a bike by it\'s name!') + .addStringOption(option => + option.setName('name') + .setDescription('The name of the bike') + .setRequired(true)), + async execute(interaction) { + const userId = interaction.user.id; + const bikeName = interaction.options.getString('name') + try { + // Query the BikesTable to get the bike by name for the user + const bike = await BikesTable.findOne({ where: { userId, name: bikeName } }); + + if (!bike) { + return await interaction.reply('No bike found with that name.'); + } + const miles = Math.round(bike.lastWaxedDistance * 0.000621371); // equivilant meters to miles + const bikeInfo = `Bike information:\nName: ${bike.name}\nBrand: ${bike.brand}\nModel: ${bike.model}.\nCurrent Mileage: ${Math.round(bike.distance * 0.000621371)}\nThis chain was last waxed on ${bike.lastWaxedDate} at ${miles} miles.`; + + return await interaction.reply(bikeInfo); + } catch (error) { + console.error('Error fetching bike:', error); + return await interaction.reply('There was an error fetching your bike.'); + } + } +}; \ No newline at end of file diff --git a/src/commands/utility/get_last_ride.js b/src/commands/utility/get_last_ride.js new file mode 100644 index 0000000..4195e71 --- /dev/null +++ b/src/commands/utility/get_last_ride.js @@ -0,0 +1,41 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { EmbedBuilder } = require('discord.js'); +const axios = require('axios'); +const getStravaAuthentication = require('../../shared_library/strava_authentication.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('get_latest_ride') + .setDescription('Get your latest ride from Strava.'), + async execute(interaction) { + const userId = interaction.user.id; + + // do some logic here to determine if hte access token is expired if so refresh it and then use it + const strava_access_token = await getStravaAuthentication(userId); + if (!strava_access_token) { + return interaction.reply({ content: 'You need to connect your Strava account first.', ephemeral: true }); + } + try { + const response = await axios.get('https://www.strava.com/api/v3/athlete/activities', { + headers: { Authorization: `Bearer ${strava_access_token}` }, + params: { per_page: 1 } + }); + + const latestRide = response.data[0]; + + if (!latestRide) { + return interaction.reply({ content: 'No rides found.', ephemeral: true }); + } + + const embed = new EmbedBuilder() + .setTitle('Latest Ride') + .setDescription(`**Distance:** ${latestRide.distance} meters\n**Date:** ${new Date(latestRide.start_date).toLocaleString()}`) + .setColor('#FC4C02'); + + return interaction.reply({ embeds: [embed], ephemeral: true }); + } catch (error) { + console.error('Error fetching latest ride:', error); + return interaction.reply({ content: 'There was an error fetching your latest ride.', ephemeral: true }); + } + }, +}; \ No newline at end of file diff --git a/src/commands/utility/i_waxed_my_chain.js b/src/commands/utility/i_waxed_my_chain.js new file mode 100644 index 0000000..bb00d2a --- /dev/null +++ b/src/commands/utility/i_waxed_my_chain.js @@ -0,0 +1,52 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { BikesTable } = require('../../dbObjects.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('i_waxed_my_chain') + .setDescription('Update the date of when you last waxed your chain for a specific bike.') + .addStringOption(option => + option.setName('bike_name') + .setDescription('The name of the bike') + .setRequired(true)) + .addStringOption(option => + option.setName('date') + .setDescription('The date you last waxed your chain (YYYY-MM-DD). If nothing is entered, assuming today.') + .setRequired(false)) + .addStringOption(option => + option.setName('mileage') + .setDescription('The mileage you waxed your chain at. If nothing is entered, assuming current mileage.') + .setRequired(false)), + async execute(interaction) { + const userId = interaction.user.id; + const bikeName = interaction.options.getString('bike_name'); + // if date is null use today + let date = interaction.options.getString('date') + if (!interaction.options.getString('date')) { + const currentDate = new Date(); + const month = currentDate.getMonth() + 1; // Months are zero-based, so add 1 + const day = currentDate.getDate(); + const year = currentDate.getFullYear(); + date = `${month}/${day}/${year}`; + } + const bike = await BikesTable.findOne({ where: { userId: userId, name: bikeName } }); + var mileage = "" + if (interaction.options.getString('mileage')) { + mileage = interaction.options.getString('mileage') * 1609.344; + } else { + mileage = bike.distance; + } + + try { + const output = await BikesTable.update( + { lastWaxedDate: date, lastWaxedDistance: mileage}, + { where: { userId: userId, bikeId: bike.bikeId } } + ); + const distanceMiles = Math.round(mileage * 0.000621371192); + await interaction.reply({ content: `Successfully updated the last waxed date for bike ID ${bike.bikeId} to ${date}, at ${distanceMiles} miles.`}); + } catch (error) { + console.error('Error updating waxed chain date:', error); + await interaction.reply({ content: 'There was an error updating the waxed chain date.', ephemeral: true }); + } + }, +}; \ No newline at end of file diff --git a/src/commands/utility/reload.js b/src/commands/utility/reload.js new file mode 100644 index 0000000..cdf6ad0 --- /dev/null +++ b/src/commands/utility/reload.js @@ -0,0 +1,31 @@ +const { SlashCommandBuilder } = require('discord.js'); + +module.exports = { + category: 'utility', + data: new SlashCommandBuilder() + .setName('reload') + .setDescription('Reloads a command.') + .addStringOption(option => + option.setName('command') + .setDescription('The command to reload.') + .setRequired(true)), + async execute(interaction) { + const commandName = interaction.options.getString('command', true).toLowerCase(); + const command = interaction.client.commands.get(commandName); + + if (!command) { + return interaction.reply(`There is no command with name \`${commandName}\`!`); + } + + delete require.cache[require.resolve(`../${command.category}/${command.data.name}.js`)]; + + try { + const newCommand = require(`../${command.category}/${command.data.name}.js`); + interaction.client.commands.set(newCommand.data.name, newCommand); + await interaction.reply(`Command \`${newCommand.data.name}\` was reloaded!`); + } catch (error) { + console.error(error); + await interaction.reply(`There was an error while reloading a command \`${command.data.name}\`:\n\`${error.message}\``); + } + }, +}; \ No newline at end of file diff --git a/src/commands/utility/sync_bikes.js b/src/commands/utility/sync_bikes.js new file mode 100644 index 0000000..e3d4c64 --- /dev/null +++ b/src/commands/utility/sync_bikes.js @@ -0,0 +1,62 @@ +const { SlashCommandBuilder } = require('discord.js'); +const { BikesTable, UsersTable } = require('../../dbObjects.js'); +const axios = require('axios'); +const {getStravaAuthentication} = require('../../shared_library/strava_authentication.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('sync_bikes') + .setDescription('Sync bike data from Strava!'), + async execute(interaction) { + const userId = interaction.user.id; + const user = await UsersTable.findOne({ where: { userId } }); + const strava_access_token = await getStravaAuthentication(user.dataValues); + if (!strava_access_token) { + return interaction.reply({ content: 'You need to connect your Strava account first.', ephemeral: true }); + } + try { + // Fetch bike data from Strava + const response = await axios.get('https://www.strava.com/api/v3/athlete', { + headers: { + 'Authorization': `Bearer ${strava_access_token}` + } + }); + + const bikes = response.data.bikes; + + if (bikes.length === 0) { + return await interaction.reply('No bikes found on Strava.'); + } + // Take the bike ID and call the gear/{id} endpoint to get the bike's name, brand, and model + + let updatedBikes = []; + // Upsert bike data into the database + for (const bike of bikes) { + try { + const bikeData = await axios.get(`https://www.strava.com/api/v3/gear/${bike.id}`, { + headers: { + 'Authorization': `Bearer ${strava_access_token}` + } + }); + const updatedData = await BikesTable.upsert({ + userId: userId, + bikeId: bike.id, + name: bike.name, + brand: bikeData.data.brand_name, + model: bikeData.data.model_name, + distance: bike.distance + }); + updatedBikes.push(updatedData[0].dataValues); + } catch (error) { + console.error('Error fetching bike data:', error); + return await interaction.reply('There was an error fetching your bike data.'); + } + } + const bikeList = updatedBikes.map(bike => `${bike.name} (${bike.brand} ${bike.model} ${Math.round(bike.distance * 0.000621371)})`).join('\n'); + return await interaction.reply(`Your bikes have been synced:\n${bikeList}`); + } catch (error) { + console.error('Error fetching or syncing bikes:', error); + return await interaction.reply('There was an error syncing your bikes.'); + } + }, +}; \ No newline at end of file diff --git a/src/dbObjects.js b/src/dbObjects.js index 449480f..c7255ee 100644 --- a/src/dbObjects.js +++ b/src/dbObjects.js @@ -8,5 +8,6 @@ const sequelize = new Sequelize('database', 'username', 'password', { }); const EventsTable = require('./models/events.js')(sequelize, Sequelize.DataTypes); - -module.exports = { EventsTable }; \ No newline at end of file +const UsersTable = require('./models/users.js')(sequelize, Sequelize.DataTypes); +const BikesTable = require('./models/bikes.js')(sequelize, Sequelize.DataTypes); +module.exports = { EventsTable, UsersTable, BikesTable }; \ No newline at end of file diff --git a/src/models/bikes.js b/src/models/bikes.js new file mode 100644 index 0000000..51e061d --- /dev/null +++ b/src/models/bikes.js @@ -0,0 +1,37 @@ +module.exports = (sequelize, DataTypes) => { + return sequelize.define('bikes', { + bikeId: { + type: DataTypes.STRING, + primaryKey: true, + }, + userId: { + type: DataTypes.INTEGER, + allowNull: false, + + references: { + model: 'users', + key: 'userId' + } + }, + name: { + type: DataTypes.STRING, + }, + brand: { + type: DataTypes.STRING, + }, + model: { + type: DataTypes.STRING, + }, + distance: { + type: DataTypes.INTEGER, + }, + lastWaxedDate: { + type: DataTypes.STRING, + defaultValue: 'NEVER', + }, + lastWaxedDistance: { + type: DataTypes.INTEGER, + defaultValue: 0, + } + }) +}; \ No newline at end of file diff --git a/src/models/users.js b/src/models/users.js new file mode 100644 index 0000000..ff7c7b4 --- /dev/null +++ b/src/models/users.js @@ -0,0 +1,14 @@ +module.exports = (sequelize, DataTypes) => { + return sequelize.define('users', { + userId: { + type: DataTypes.STRING, + primaryKey: true, + Unique: true, + }, + strava_user_id: DataTypes.STRING, + strava_access_token: DataTypes.TEXT, + strava_connected: DataTypes.BOOLEAN, + strava_refresh_token: DataTypes.TEXT, + strava_expires_at: DataTypes.INTEGER, + }); +}; \ No newline at end of file diff --git a/src/shared_library/strava_authentication.js b/src/shared_library/strava_authentication.js new file mode 100644 index 0000000..f69041c --- /dev/null +++ b/src/shared_library/strava_authentication.js @@ -0,0 +1,62 @@ +const axios = require('axios'); +const { UsersTable } = require('../dbObjects.js'); +const fs = require('node:fs'); +const client_id = fs.readFileSync("/mnt/secrets-store/STRAVA_CLIENT_ID", 'utf8'); +const client_secret = fs.readFileSync("/mnt/secrets-store/STRAVA_CLIENT_SECRET", 'utf8'); + +async function firstTimeAuth(userId, code){ + try { + const response = await axios.post('https://www.strava.com/oauth/token', { + client_id: client_id, + client_secret: client_secret, + code: code, + grant_type: 'authorization_code' + }); + + // Save the access token to the database + await UsersTable.update({ strava_access_token: response.data.access_token, strava_user_id: response.data.athlete.id, strava_connected: true, strava_refresh_token: response.data.refresh_token, strava_expires_at: response.data.expires_at }, { where: { userId: userId } }); + // setup bikes for the user + console.log(response.data.athlete.id) + console.log('Strava account connected successfully!'); + return { + athlete_id: response.data.athlete.id, + strava_access_token: response.data.access_token + }; + } catch (error) { + console.error('Error exchanging authorization code for access token:', error); + } +} +async function getStravaAuthentication(userData) { + const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds + + if (userData.expiresAt <= currentTime) { + // Token is expired, refresh it + console.log('Token is expired, refreshing...'); + const refreshTokenResponse = await axios.post('https://www.strava.com/oauth/token', { + client_id: client_id, + client_secret: client_secret, + grant_type: 'refresh_token', + refresh_token: userData.refreshToken, + }); + + const newAccessToken = refreshTokenResponse.data.access_token; + const newExpiresAt = refreshTokenResponse.data.expires_at; + const newRefreshToken = refreshTokenResponse.data.refresh_token; + + // Update the user record with the new tokens + await UsersTable.update({ + stravaAccessToken: newAccessToken, + expiresAt: newExpiresAt, + refreshToken: newRefreshToken, + }, { + where: { userId: userData.userId } + }); + + return newAccessToken; + } else { + console.log('Token is still valid...'); + return userData.strava_access_token; + } + } + +module.exports = {getStravaAuthentication, firstTimeAuth}; \ No newline at end of file diff --git a/src/strava_webhook.js b/src/strava_webhook.js new file mode 100644 index 0000000..aeb3ea9 --- /dev/null +++ b/src/strava_webhook.js @@ -0,0 +1,147 @@ +const express = require('express'); +const { UsersTable, BikesTable } = require('./dbObjects.js'); +const axios = require('axios'); +const { Client, GatewayIntentBits } = require('discord.js'); +const client = new Client({ intents: [GatewayIntentBits.Guilds] }); +const fs = require('node:fs'); +const { firstTimeAuth, getStravaAuthentication } = require('./shared_library/strava_authentication.js'); +const app = express(); +app.use(express.json()); +const discordToken = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); +client.login(discordToken); + +app.post('/webhook', async (req, res) => { + console.log("webhook event received!", req.body); + // get the object_id and owner id + // call the strava API to get the activity details + // from the activity details get the athlete ID, distance, and gear id + // update the database with the new distance and do a calculation to see if they need to wax their chain + // if they do send a message to the discord user + const event = req.body; + + if (event.object_type === 'activity' && event.aspect_type === 'create') { + const user = await UsersTable.findOne({ where: { strava_user_id: event.owner_id } }); + if (user) { + const stravaAccessToken = await getStravaAuthentication(user.dataValues) + try { + const rideData = await axios.get(`https://www.strava.com/api/v3/activities/${event.object_id}`, { + headers: { Authorization: `Bearer ${stravaAccessToken}` } + }); + const gearId = rideData.data.gear.id; + const currentDistance = rideData.data.gear.distance; + // update the distance for the gear + await syncBike(gearId, currentDistance, user.dataValues.userId); + const lastWaxedDistance = await getLastWaxed(gearId, user.dataValues.userId); + + const totalMiles = Math.round(currentDistance * 0.000621371); + const lastWaxedMiles = Math.round(lastWaxedDistance * 0.000621371); + const currentDiff = totalMiles - lastWaxedMiles; + if (currentDiff > 250) { + const message = `Nice ride and it's time to wax your chain! You've ridden ${currentDiff} miles since your last wax.` + const id = user.dataValues.userId; + const discordUser = await client.users.fetch(id) + discordUser.send(message); + } else if (currentDiff > 150) { + const message = `Nice ride! You're getting close to needing to wax your chain. You've ridden ${currentDiff} miles since your last wax.`; + const id = user.dataValues.userId; + const discordUser = await client.users.fetch(id) + discordUser.send(message); + } + console.log(`Updated distance for gear ${gearId} to ${Math.round(currentDistance * 0.000621371)}`); + } catch (error) { + console.error('Error fetching ride data:', error); + } + } else { + console.log('No user found for strava user id:', event.owner_id); + } + } + res.sendStatus(200); + }); + +// Adds support for GET requests to our webhook +app.get('/webhook', (req, res) => { + // Your verify token. Should be a random string. + const VERIFY_TOKEN = "STRAVA"; + // Parses the query params + let mode = req.query['hub.mode']; + let token = req.query['hub.verify_token']; + let challenge = req.query['hub.challenge']; + // Checks if a token and mode is in the query string of the request + if (mode && token) { + // Verifies that the mode and token sent are valid + if (mode === 'subscribe' && token === VERIFY_TOKEN) { + // Responds with the challenge token from the request + console.log('WEBHOOK_VERIFIED'); + res.json({"hub.challenge":challenge}); + } else { + // Responds with '403 Forbidden' if verify tokens do not match + res.sendStatus(403); + } + } + }); + +app.get('/strava/callback/:userId', async (req, res) => { + const code = req.query.code; + const userId = req.params.userId; + if (!code) { + return res.status(400).send('Missing authorization code'); + } + const { athlete_id, strava_access_token } = await firstTimeAuth(userId, code); + console.log('added strava athlete : ', athlete_id, 'for discord user:' , userId); + await setupBikes(athlete_id, userId, strava_access_token) + + return res.send('Strava account connected successfully!'); +}); + +app.listen(3000, () => { + console.log('Strava webhook server is running on port 3000'); +}); + + +async function setupBikes(athleteId, userId, strava_access_token) { + // Fetch the user's bikes from Strava's /athletes endpoint + try { + const athleteResponse = await axios.get(`https://www.strava.com/api/v3/athletes/${athleteId}`, { + headers: { Authorization: `Bearer ${strava_access_token}` } + }); + // get the athlete page + // Fetch details for each bike from Strava's /gear endpoint and update the database + for (const bike of athleteResponse.data.bikes) { + // Update the database with the bike details + await BikesTable.upsert({ + bikeId: bike.id, + userId: userId, + name: bike.name, + brand: bike.brand_name, + model: bike.model_name, + distance: bike.distance + }); + } + } catch (error) { + console.error('Error fetching athlete data:', error.status, error.message); + } +} + +async function syncBike(bikeId, distance, userId) { + try { + await BikesTable.update( + { distance }, + { where: { bikeId, userId }, + returning: true, + plain: true} + ); + + } catch (error) { + console.error('Error updating data:', error); + } +} + +async function getLastWaxed(bikeId, userId){ + try { + const output = await BikesTable.findOne({ where: { bikeId, userId } }); + return output.dataValues.lastWaxedDistance; + } catch (error) { + console.error('Error finding data:', error); + } + +} \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 6856d87..21d120d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,3 @@ -import 'dotenv/config'; - export async function DiscordRequest(endpoint, options) { const discordToken = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); // append endpoint to root API URL From 468487aadc69e1d49aa4c404ebc4f95a825faf99 Mon Sep 17 00:00:00 2001 From: Peber Date: Thu, 26 Dec 2024 20:43:49 -0500 Subject: [PATCH 4/7] update --- src/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app.js b/src/app.js index bc6729c..800eb9a 100644 --- a/src/app.js +++ b/src/app.js @@ -6,7 +6,6 @@ const { EventsTable, UsersTable, BikesTable } = require('./dbObjects.js'); const { exec } = require('node:child_process'); const { execute } = require('./commands/utility/create_event.js'); const discordToken = fs.readFileSync("/mnt/secrets-store/discordToken", 'utf8'); - const client = new Client({ intents: [GatewayIntentBits.Guilds] }); client.commands = new Collection(); From d0c94311aff0058cb82763f938d52098336bcd6e Mon Sep 17 00:00:00 2001 From: "GitHub-Actions[bot]" Date: Fri, 27 Dec 2024 01:50:08 +0000 Subject: [PATCH 5/7] Bot: Updating CHANGELOG and README for release based on #17 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cb0dac..1e41c8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Changelog +### Version 1.0.0 + +#### feature +* PR [#17](https://github.com/petercort/FBF-Buddy/pull/17) - Add wax utilities + + + ### Version 0.0.5 #### feature From 5c0558216eb4d825699245a488b18dc4ef1d8aab Mon Sep 17 00:00:00 2001 From: Peber Date: Thu, 26 Dec 2024 20:50:50 -0500 Subject: [PATCH 6/7] missed a merge conflict --- src/app.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/app.js b/src/app.js index 6bb8628..dde4633 100644 --- a/src/app.js +++ b/src/app.js @@ -59,15 +59,7 @@ client.on(Events.InteractionCreate, async interaction => { } }); -<<<<<<< HEAD // Start the Strava webhook server require('./strava_webhook.js'); client.login(discordToken); -======= -try { - client.login(discordToken); -} catch (error) { - console.error(error); -} ->>>>>>> 5cb1fdf6d2eec9e256a8b8379201c7d14aded81d From e53b6ba5a131f2109efccef983a8bcb213ffed73 Mon Sep 17 00:00:00 2001 From: Peber Date: Thu, 26 Dec 2024 20:55:57 -0500 Subject: [PATCH 7/7] updating npm packages --- package-lock.json | 391 ++++++++++++++-------------------------------- package.json | 2 +- 2 files changed, 122 insertions(+), 271 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1efda0..f14af5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "sqlite3": "^5.1.7" }, "devDependencies": { - "nodemon": "^3.0.0" + "nodemon": "^3.1.9" }, "engines": { "node": ">=20.x" @@ -175,7 +175,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -188,7 +187,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", "engines": { "node": ">= 8" } @@ -197,7 +195,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -270,7 +267,6 @@ "url": "https://opencollective.com/sequelize" } ], - "license": "MIT", "dependencies": { "@sequelize/utils": "7.0.0-alpha.43", "@types/debug": "^4.1.12", @@ -295,65 +291,10 @@ "node": ">=18.0.0" } }, - "node_modules/@sequelize/core/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@sequelize/core/node_modules/inflection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-3.0.0.tgz", - "integrity": "sha512-1zEJU1l19SgJlmwqsEyFTbScw/tkMHFenUo//Y0i+XEP83gDFdMvPizAD/WGcE+l1ku12PcTVHQhO6g5E0UCMw==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@sequelize/core/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/@sequelize/core/node_modules/sequelize-pool": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-8.0.0.tgz", - "integrity": "sha512-xY04c5ctp6lKE4ZoSVo7YJHN5FHVhoYMoH2Z8jWIJG26c9kJSkIjql5HgD9XG5cwJbYMF0Ko2Fhgws20HC90Ug==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@sequelize/core/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@sequelize/postgres": { "version": "7.0.0-alpha.43", "resolved": "https://registry.npmjs.org/@sequelize/postgres/-/postgres-7.0.0-alpha.43.tgz", "integrity": "sha512-YAkLUMQCurVpgLF5qCKvtuvMYbwU6mgXNdNe/b1UEP+iW4AB06I+MMwfB7WtUak0X7IGld9YjXPOUz4HhDOTFg==", - "license": "MIT", "dependencies": { "@sequelize/core": "7.0.0-alpha.43", "@sequelize/utils": "7.0.0-alpha.43", @@ -371,7 +312,6 @@ "version": "7.0.0-alpha.43", "resolved": "https://registry.npmjs.org/@sequelize/utils/-/utils-7.0.0-alpha.43.tgz", "integrity": "sha512-ex1iVNuqc7db1Il8VGkF4DWDkn7OpEsB4FGvS3OWz8g7blqvlO6T3fP4c+qmOxOrmdzDPWayh43U3xr/F4q3qQ==", - "license": "MIT", "dependencies": { "@types/lodash": "^4.17.0", "lodash": "^4.17.21" @@ -400,8 +340,7 @@ "node_modules/@types/lodash": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", - "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==", - "license": "MIT" + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==" }, "node_modules/@types/ms": { "version": "0.7.34", @@ -420,7 +359,6 @@ "version": "8.11.10", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz", "integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==", - "license": "MIT", "dependencies": { "@types/node": "*", "pg-protocol": "*", @@ -479,29 +417,6 @@ "node": ">= 6.0.0" } }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "optional": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "optional": true - }, "node_modules/agentkeepalive": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", @@ -537,12 +452,11 @@ } }, "node_modules/ansis": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.3.2.tgz", - "integrity": "sha512-cFthbBlt+Oi0i9Pv/j6YdVWJh54CtjGACaMPCIrEV4Ha7HWsIjXDwseYV79TIL0B4+KfSwD5S70PeQDkPUd1rA==", - "license": "ISC", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.5.1.tgz", + "integrity": "sha512-sfej1OZ6XF7964SpnVmj7bIUnN+P3YbnxXiRYxQgjuuWW9uH+a8OVtxX2ToRQoSBBKvdYApgAcDmm2JEh1xr3w==", "engines": { - "node": ">=15" + "node": ">=16" } }, "node_modules/anymatch": { @@ -656,8 +570,7 @@ "node_modules/bnf-parser": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/bnf-parser/-/bnf-parser-3.1.6.tgz", - "integrity": "sha512-3x0ECh6CghmcAYnY6uiVAOfl263XkWffDq5fQS20ac3k0U7TE5rTWNXTnOTckgmfZc94iharwqCyoV8OAYxYoA==", - "license": "ISC" + "integrity": "sha512-3x0ECh6CghmcAYnY6uiVAOfl263XkWffDq5fQS20ac3k0U7TE5rTWNXTnOTckgmfZc94iharwqCyoV8OAYxYoA==" }, "node_modules/body-parser": { "version": "1.20.3", @@ -682,6 +595,19 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -898,15 +824,22 @@ "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", - "license": "MIT" + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/decompress-response": { @@ -1193,6 +1126,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1202,7 +1148,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1215,10 +1160,9 @@ } }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "license": "ISC", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "dependencies": { "reusify": "^1.0.4" } @@ -1260,6 +1204,19 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -1521,29 +1478,6 @@ "node": ">= 6" } }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "optional": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "optional": true - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -1557,29 +1491,6 @@ "node": ">= 6" } }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "optional": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "optional": true - }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -1650,12 +1561,12 @@ "optional": true }, "node_modules/inflection": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", - "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", - "engines": [ - "node >= 0.4.0" - ] + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-3.0.0.tgz", + "integrity": "sha512-1zEJU1l19SgJlmwqsEyFTbScw/tkMHFenUo//Y0i+XEP83gDFdMvPizAD/WGcE+l1ku12PcTVHQhO6g5E0UCMw==", + "engines": { + "node": ">=18.0.0" + } }, "node_modules/inflight": { "version": "1.0.6", @@ -1847,7 +1758,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", "engines": { "node": ">= 8" } @@ -1864,7 +1774,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -2058,9 +1967,9 @@ } }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/napi-build-utils": { "version": "1.0.2", @@ -2143,29 +2052,6 @@ "url": "https://opencollective.com/nodemon" } }, - "node_modules/nodemon/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -2220,8 +2106,7 @@ "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "license": "MIT" + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, "node_modules/on-finished": { "version": "2.4.1", @@ -2283,7 +2168,6 @@ "version": "8.13.1", "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==", - "license": "MIT", "dependencies": { "pg-connection-string": "^2.7.0", "pg-pool": "^3.7.0", @@ -2310,7 +2194,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { @@ -2322,7 +2205,6 @@ "version": "2.3.4", "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.4.tgz", "integrity": "sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA==", - "license": "MIT", "dependencies": { "underscore": "^1.13.1" }, @@ -2334,7 +2216,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "license": "ISC", "engines": { "node": ">=4.0.0" } @@ -2343,7 +2224,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "license": "ISC", "engines": { "node": ">=4" } @@ -2352,7 +2232,6 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz", "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", - "license": "MIT", "peerDependencies": { "pg": ">=8.0" } @@ -2360,14 +2239,12 @@ "node_modules/pg-protocol": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", - "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==", - "license": "MIT" + "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==" }, "node_modules/pg-types": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", - "license": "MIT", "dependencies": { "pg-int8": "1.0.1", "pg-numeric": "1.0.2", @@ -2385,7 +2262,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "license": "MIT", "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", @@ -2401,7 +2277,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", "engines": { "node": ">=4" } @@ -2410,7 +2285,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2419,7 +2293,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2428,7 +2301,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", "dependencies": { "xtend": "^4.0.0" }, @@ -2440,7 +2312,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "license": "MIT", "dependencies": { "split2": "^4.1.0" } @@ -2460,7 +2331,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "license": "MIT", "engines": { "node": ">=12" } @@ -2469,7 +2339,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "license": "MIT", "dependencies": { "obuf": "~1.1.2" }, @@ -2481,7 +2350,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", - "license": "MIT", "engines": { "node": ">=12" } @@ -2490,7 +2358,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "license": "MIT", "engines": { "node": ">=12" } @@ -2498,8 +2365,7 @@ "node_modules/postgres-range": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", - "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==", - "license": "MIT" + "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==" }, "node_modules/prebuild-install": { "version": "7.1.2", @@ -2608,8 +2474,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/range-parser": { "version": "1.2.1", @@ -2690,7 +2555,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2730,7 +2594,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -2793,6 +2656,19 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -2801,11 +2677,6 @@ "node": ">= 0.8" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "node_modules/sequelize": { "version": "6.37.5", "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.5.tgz", @@ -2868,6 +2739,22 @@ } }, "node_modules/sequelize-pool": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-8.0.0.tgz", + "integrity": "sha512-xY04c5ctp6lKE4ZoSVo7YJHN5FHVhoYMoH2Z8jWIJG26c9kJSkIjql5HgD9XG5cwJbYMF0Ko2Fhgws20HC90Ug==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/sequelize/node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/sequelize/node_modules/sequelize-pool": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", @@ -2875,27 +2762,14 @@ "node": ">= 10.0.0" } }, - "node_modules/sequelize/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node_modules/sequelize/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/sequelize/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "node_modules/serve-static": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", @@ -3088,34 +2962,10 @@ "node": ">= 10" } }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "optional": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socks-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "optional": true - }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", "engines": { "node": ">= 10.x" } @@ -3333,10 +3183,9 @@ } }, "node_modules/type-fest": { - "version": "4.27.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.27.0.tgz", - "integrity": "sha512-3IMSWgP7C5KSQqmo1wjhKrwsvXAtF33jO3QY+Uy++ia7hqvgSK6iXbbg5PbDBc1P2ZbNEDgejOrN4YooXvhwCw==", - "license": "(MIT OR CC0-1.0)", + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.31.0.tgz", + "integrity": "sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==", "engines": { "node": ">=16" }, @@ -3365,8 +3214,7 @@ "node_modules/underscore": { "version": "1.13.7", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", - "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", - "license": "MIT" + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==" }, "node_modules/undici": { "version": "6.19.8", @@ -3421,9 +3269,13 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -3505,7 +3357,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", "engines": { "node": ">=0.4" } diff --git a/package.json b/package.json index 275ed6c..0efa5d7 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,6 @@ "sqlite3": "^5.1.7" }, "devDependencies": { - "nodemon": "^3.0.0" + "nodemon": "^3.1.9" } }