diff --git a/.gitignore b/.gitignore index 55c52ad..7119cfa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -node_modules -.env -.data +node_modules +.env +.data out \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index eacc6c8..af8dfb2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,23 +1,23 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "shell", - "command":"npx tsc", - "group": { - "kind": "build", - "isDefault": true - }, - "label": "Build (Bot Server)" - }, - { - "type": "shell", - "command":"npx tsc\nnode ./out/index.js\ndel ./out/* -Recurse", - "group": { - "kind": "build", - "isDefault": true - }, - "label": "Build & Test" - } - ] +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "command":"tsc\nsass src/style:out/style\nrollup -c", + "group": { + "kind": "build", + "isDefault": true + }, + "label": "Build (Bot Server)" + }, + { + "type": "shell", + "command":"tsc\nsass src/style:out/style\nrollup -c\nnode ./out/server/index.js\ndel ./out/* -Recurse", + "group": { + "kind": "build", + "isDefault": true + }, + "label": "Build & Test" + } + ] } \ No newline at end of file diff --git a/LICENSE b/LICENSE index 00d2e13..b0a72fb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,24 +1,24 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + For more information, please refer to \ No newline at end of file diff --git a/README.md b/README.md index d6602e9..cc8e371 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,75 @@ -# monofile -File sharing via Discord - -
- -## .env - -``` -TOKEN=KILL-YOURSELF.NOW -``` - -## versions & planned updates - -- [X] 1.0.0 initial release -- [X] 1.1.0 add file cloning endpoint -- [X] 1.1.1 add file cloning webpage -- [X] 1.1.2 fix file cloning with binary data -- [X] 1.1.3 display current version on pages -- [X] 1.1.4 serve /assets as static files & make /server endpoint -- [X] 1.2.0 add file parameters section + custom ids -- [X] 1.2.1 add file counter to main page -- [X] 1.2.2 clean up this shitty code -- [X] 1.2.3 bugfixes -- [ ] 1.2.4 add id locks, allowing you to set a key for a file that allows you to overwrite the file in the future -- [ ] 1.2.5 prevent cloning of local/private ip addresses -- [ ] 1.3.0 add simple moderation tools -- [ ] 2.0.0 rewrite using theUnfunny's code as a base/rewrite using monofile-core - -also todo: monofile-core (written in eris) - -## Disclaimer! -This project does some stuff that can be considered questionable. Discord may not like you uploading files this way, and it's a grey area in Discord's TOS. We take no responsibility if Discord locks your account for API abuse. \ No newline at end of file +# monofile +The open-source, Discord-based file sharing service. +[Live instance](https://fyle.uk) + +
+ +## Setup + +First, install monofile's prerequisites... +``` +npm i +``` + +Then, add your bot token... +``` +echo "TOKEN=INSERT-TOKEN.HERE" > .env +``` +and, in addition, SMTP authentication... +``` +echo "\nMAIL_USER=user@example.com" > .env +echo "\nMAIL_PASS=password here" > .env +``` + +Invite your bot to a server, and create a new `config.json` in the project root: +```js +// config.json +{ + "maxDiscordFiles": 20, + "maxDiscordFileSize": 26214400, + "targetGuild": "1024080490677936248", + "targetChannel": "1024080525993971913", + "requestTimeout":120000, + "maxUploadIdLength":30, + + "accounts": { + "registrationEnabled": true, + "requiredForUpload": false + }, + + "webdrop": { + "accountRequired": false + }, + + "mail": { // nodemailer transport options + "host": "smtp.fastmail.com", // or your mail provider of choice + "port": 465, + "secure": true, + "auth": { + "user": "REPLACE-WITH-YOUR-ALIAS@YOURDOMAIN.COM", + "pass": "REPLACE-WITH-YOUR-GENERATED-PASSWORD" + } + } +} +``` + +Then, compile: +``` +tsc && sass src/style:out/style && rollup -c +``` +and start. +``` +npm start +``` + +monofile should now be running on either `env.MONOFILE_PORT` or port `3000`. + +## Disclaimer + +Although we believe monofile is not against Discord's developer terms of service, monofile's contributors are not liable if Discord takes action against you for running an instance. + +## License + +Code written by monofile's contributors is currently licensed under [Unlicense](https://github.com/nbitzz/monofile/blob/main/LICENSE). + +Icons under `/assets/icons` were created by Microsoft, and as such are licensed under [different terms](https://github.com/nbitzz/monofile/blob/1.3.0/assets/icons/README.md) (MIT). \ No newline at end of file diff --git a/assets/fonts/FiraCode-Bold.ttf b/assets/fonts/FiraCode-Bold.ttf new file mode 100644 index 0000000..837f379 Binary files /dev/null and b/assets/fonts/FiraCode-Bold.ttf differ diff --git a/assets/fonts/FiraCode-Light.ttf b/assets/fonts/FiraCode-Light.ttf new file mode 100644 index 0000000..84801e1 Binary files /dev/null and b/assets/fonts/FiraCode-Light.ttf differ diff --git a/assets/fonts/FiraCode-Medium.ttf b/assets/fonts/FiraCode-Medium.ttf new file mode 100644 index 0000000..dd9cbf9 Binary files /dev/null and b/assets/fonts/FiraCode-Medium.ttf differ diff --git a/assets/fonts/FiraCode-Regular.ttf b/assets/fonts/FiraCode-Regular.ttf new file mode 100644 index 0000000..82baafc Binary files /dev/null and b/assets/fonts/FiraCode-Regular.ttf differ diff --git a/assets/fonts/FiraCode-SemiBold.ttf b/assets/fonts/FiraCode-SemiBold.ttf new file mode 100644 index 0000000..f3a34fa Binary files /dev/null and b/assets/fonts/FiraCode-SemiBold.ttf differ diff --git a/assets/fonts/Inconsolata-Black.ttf b/assets/fonts/Inconsolata-Black.ttf new file mode 100644 index 0000000..869b582 Binary files /dev/null and b/assets/fonts/Inconsolata-Black.ttf differ diff --git a/assets/fonts/Inconsolata-Bold.ttf b/assets/fonts/Inconsolata-Bold.ttf new file mode 100644 index 0000000..4feced9 Binary files /dev/null and b/assets/fonts/Inconsolata-Bold.ttf differ diff --git a/assets/fonts/Inconsolata-ExtraBold.ttf b/assets/fonts/Inconsolata-ExtraBold.ttf new file mode 100644 index 0000000..ce4b64b Binary files /dev/null and b/assets/fonts/Inconsolata-ExtraBold.ttf differ diff --git a/assets/fonts/Inconsolata-ExtraLight.ttf b/assets/fonts/Inconsolata-ExtraLight.ttf new file mode 100644 index 0000000..ea17052 Binary files /dev/null and b/assets/fonts/Inconsolata-ExtraLight.ttf differ diff --git a/assets/fonts/Inconsolata-Light.ttf b/assets/fonts/Inconsolata-Light.ttf new file mode 100644 index 0000000..cae58c0 Binary files /dev/null and b/assets/fonts/Inconsolata-Light.ttf differ diff --git a/assets/fonts/Inconsolata-Medium.ttf b/assets/fonts/Inconsolata-Medium.ttf new file mode 100644 index 0000000..7b22fb7 Binary files /dev/null and b/assets/fonts/Inconsolata-Medium.ttf differ diff --git a/assets/fonts/Inconsolata-Regular.ttf b/assets/fonts/Inconsolata-Regular.ttf new file mode 100644 index 0000000..31e0c14 Binary files /dev/null and b/assets/fonts/Inconsolata-Regular.ttf differ diff --git a/assets/fonts/Inconsolata-SemiBold.ttf b/assets/fonts/Inconsolata-SemiBold.ttf new file mode 100644 index 0000000..b29ec66 Binary files /dev/null and b/assets/fonts/Inconsolata-SemiBold.ttf differ diff --git a/assets/fonts/SourceSansPro-Bold.ttf b/assets/fonts/SourceSansPro-Bold.ttf new file mode 100644 index 0000000..b8879af Binary files /dev/null and b/assets/fonts/SourceSansPro-Bold.ttf differ diff --git a/assets/fonts/SourceSansPro-BoldItalic.ttf b/assets/fonts/SourceSansPro-BoldItalic.ttf new file mode 100644 index 0000000..b38bae9 Binary files /dev/null and b/assets/fonts/SourceSansPro-BoldItalic.ttf differ diff --git a/assets/fonts/SourceSansPro-Italic.ttf b/assets/fonts/SourceSansPro-Italic.ttf new file mode 100644 index 0000000..7dbece7 Binary files /dev/null and b/assets/fonts/SourceSansPro-Italic.ttf differ diff --git a/assets/fonts/SourceSansPro-Regular.ttf b/assets/fonts/SourceSansPro-Regular.ttf new file mode 100644 index 0000000..98e8579 Binary files /dev/null and b/assets/fonts/SourceSansPro-Regular.ttf differ diff --git a/assets/fonts/SourceSansPro-SemiBold.ttf b/assets/fonts/SourceSansPro-SemiBold.ttf new file mode 100644 index 0000000..99dcc81 Binary files /dev/null and b/assets/fonts/SourceSansPro-SemiBold.ttf differ diff --git a/assets/fonts/SourceSansPro-SemiBoldItalic.ttf b/assets/fonts/SourceSansPro-SemiBoldItalic.ttf new file mode 100644 index 0000000..9c3891b Binary files /dev/null and b/assets/fonts/SourceSansPro-SemiBoldItalic.ttf differ diff --git a/assets/fonts/fira_code.css b/assets/fonts/fira_code.css new file mode 100644 index 0000000..52e189a --- /dev/null +++ b/assets/fonts/fira_code.css @@ -0,0 +1,34 @@ +@font-face { + font-family: "Fira Code"; + src: url("/static/assets/fonts/FiraCode-Light.ttf"); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "Fira Code"; + src: url("/static/assets/fonts/FiraCode-Regular.ttf"); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: "Fira Code"; + src: url("/static/assets/fonts/FiraCode-Medium.ttf"); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: "Fira Code"; + src: url("/static/assets/fonts/FiraCode-SemiBold.ttf"); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: "Fira Code"; + src: url("/static/assets/fonts/FiraCode-Bold.ttf"); + font-weight: 700; + font-style: normal; +} \ No newline at end of file diff --git a/assets/fonts/inconsolata.css b/assets/fonts/inconsolata.css new file mode 100644 index 0000000..618becd --- /dev/null +++ b/assets/fonts/inconsolata.css @@ -0,0 +1,55 @@ +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-ExtraLight.ttf"); + font-weight: 200; + font-style: normal; +} + +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-Light.ttf"); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-Regular.ttf"); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-Medium.ttf"); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-SemiBold.ttf"); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-Bold.ttf"); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-ExtraBold.ttf"); + font-weight: 800; + font-style: normal; +} + +@font-face { + font-family: "Inconsolata"; + src: url("/static/assets/fonts/Inconsolata-Black.ttf"); + font-weight: 900; + font-style: normal; +} \ No newline at end of file diff --git a/assets/fonts/license b/assets/fonts/license new file mode 100644 index 0000000..1189429 --- /dev/null +++ b/assets/fonts/license @@ -0,0 +1 @@ +These fonts are licensed under the OFL \ No newline at end of file diff --git a/assets/fonts/source_sans.css b/assets/fonts/source_sans.css new file mode 100644 index 0000000..ef8e7e3 --- /dev/null +++ b/assets/fonts/source_sans.css @@ -0,0 +1,41 @@ +@font-face { + font-family: "Source Sans Pro"; + src: url("/static/assets/fonts/SourceSansPro-Regular.ttf"); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: "Source Sans Pro"; + src: url("/static/assets/fonts/SourceSansPro-Italic.ttf"); + font-weight: 400; + font-style: italic; +} + +@font-face { + font-family: "Source Sans Pro"; + src: url("/static/assets/fonts/SourceSansPro-SemiBold.ttf"); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: "Source Sans Pro"; + src: url("/static/assets/fonts/SourceSansPro-SemiBoldItalic.ttf"); + font-weight: 600; + font-style: italic; +} + +@font-face { + font-family: "Source Sans Pro"; + src: url("/static/assets/fonts/SourceSansPro-Bold.ttf"); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: "Source Sans Pro"; + src: url("/static/assets/fonts/SourceSansPro-BoldItalic.ttf"); + font-weight: 700; + font-style: italic; +} \ No newline at end of file diff --git a/assets/icons/README.md b/assets/icons/README.md new file mode 100644 index 0000000..8611380 --- /dev/null +++ b/assets/icons/README.md @@ -0,0 +1,28 @@ +These icons were originally distributed by Microsoft as part of the Fluent System UI icon collection. +https://github.com/microsoft/fluentui-system-icons + +They are licensed under separate terms, those being: + +``` +MIT License + +Copyright (c) 2020 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` \ No newline at end of file diff --git a/assets/icons/admin/delete_file.svg b/assets/icons/admin/delete_file.svg new file mode 100644 index 0000000..67bb1af --- /dev/null +++ b/assets/icons/admin/delete_file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/admin/elevate_user.svg b/assets/icons/admin/elevate_user.svg new file mode 100644 index 0000000..3eca3ab --- /dev/null +++ b/assets/icons/admin/elevate_user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/anonymous.svg b/assets/icons/anonymous.svg new file mode 100644 index 0000000..5edd746 --- /dev/null +++ b/assets/icons/anonymous.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/change_password.svg b/assets/icons/change_password.svg new file mode 100644 index 0000000..24bd0cd --- /dev/null +++ b/assets/icons/change_password.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/change_username.svg b/assets/icons/change_username.svg new file mode 100644 index 0000000..95f0c52 --- /dev/null +++ b/assets/icons/change_username.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/delete.svg b/assets/icons/delete.svg new file mode 100644 index 0000000..d37dc5e --- /dev/null +++ b/assets/icons/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/delete_account.svg b/assets/icons/delete_account.svg new file mode 100644 index 0000000..97b6049 --- /dev/null +++ b/assets/icons/delete_account.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/error.svg b/assets/icons/error.svg new file mode 100644 index 0000000..3da8be2 --- /dev/null +++ b/assets/icons/error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/file.svg b/assets/icons/file.svg new file mode 100644 index 0000000..364411e --- /dev/null +++ b/assets/icons/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/file_icon.svg b/assets/icons/file_icon.svg new file mode 100644 index 0000000..8fa9530 --- /dev/null +++ b/assets/icons/file_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/icon_temp.svg b/assets/icons/icon_temp.svg new file mode 100644 index 0000000..d0fef9a --- /dev/null +++ b/assets/icons/icon_temp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/image.svg b/assets/icons/image.svg new file mode 100644 index 0000000..f2c72c3 --- /dev/null +++ b/assets/icons/image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/link.svg b/assets/icons/link.svg new file mode 100644 index 0000000..16dfcd6 --- /dev/null +++ b/assets/icons/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/logout.svg b/assets/icons/logout.svg new file mode 100644 index 0000000..9ee4313 --- /dev/null +++ b/assets/icons/logout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/logout_all.svg b/assets/icons/logout_all.svg new file mode 100644 index 0000000..0d3f39f --- /dev/null +++ b/assets/icons/logout_all.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/mail.svg b/assets/icons/mail.svg new file mode 100644 index 0000000..54933b7 --- /dev/null +++ b/assets/icons/mail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/more.svg b/assets/icons/more.svg new file mode 100644 index 0000000..1278f47 --- /dev/null +++ b/assets/icons/more.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/multiselect.svg b/assets/icons/multiselect.svg new file mode 100644 index 0000000..4dbb4d2 --- /dev/null +++ b/assets/icons/multiselect.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/paint.svg b/assets/icons/paint.svg new file mode 100644 index 0000000..8df3929 --- /dev/null +++ b/assets/icons/paint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/person.svg b/assets/icons/person.svg new file mode 100644 index 0000000..96b9302 --- /dev/null +++ b/assets/icons/person.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/pound.svg b/assets/icons/pound.svg new file mode 100644 index 0000000..22cba99 --- /dev/null +++ b/assets/icons/pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/private.svg b/assets/icons/private.svg new file mode 100644 index 0000000..8e47575 --- /dev/null +++ b/assets/icons/private.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/public.svg b/assets/icons/public.svg new file mode 100644 index 0000000..0a6fcd2 --- /dev/null +++ b/assets/icons/public.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/refresh.svg b/assets/icons/refresh.svg new file mode 100644 index 0000000..d415d66 --- /dev/null +++ b/assets/icons/refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/small_image.svg b/assets/icons/small_image.svg new file mode 100644 index 0000000..ba66d1e --- /dev/null +++ b/assets/icons/small_image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/tag.svg b/assets/icons/tag.svg new file mode 100644 index 0000000..f1d9042 --- /dev/null +++ b/assets/icons/tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/tag_remove.svg b/assets/icons/tag_remove.svg new file mode 100644 index 0000000..83ca233 --- /dev/null +++ b/assets/icons/tag_remove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/update.svg b/assets/icons/update.svg new file mode 100644 index 0000000..9622d7f --- /dev/null +++ b/assets/icons/update.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/script/clone_file.js b/assets/script/clone_file.js deleted file mode 100644 index 5b31f64..0000000 --- a/assets/script/clone_file.js +++ /dev/null @@ -1,30 +0,0 @@ -document.getElementById("uploadButton").addEventListener("click",() => { - let ask = prompt("Input a URL to clone.") - - if (ask) { - let opt = getOptionsForUploading() - updateBtnTxt("Requesting clone. Please wait.") - - let xmlhttp = new XMLHttpRequest() - - xmlhttp.addEventListener("error",function(e) { - updateBtnTxt(`Upload failed.
${e.toString()}`) - console.error(e) - }) - - xmlhttp.addEventListener("load",function() { - if (xmlhttp.status == 200) { - document.getElementById("CopyTB").value = `https://${location.hostname}/download/${xmlhttp.responseText}` - updateBtnTxt(`Upload complete.
Copy URL View URL`) - } else { - updateBtnTxt(`Upload failed.
${xmlhttp.responseText}`) - } - }) - - xmlhttp.open("POST","/clone") - xmlhttp.send(JSON.stringify({ - url: ask, - ...opt - })) - } -}) \ No newline at end of file diff --git a/assets/script/upload_file.js b/assets/script/upload_file.js deleted file mode 100644 index 9bf54c3..0000000 --- a/assets/script/upload_file.js +++ /dev/null @@ -1,37 +0,0 @@ -let FileUpload = document.createElement("input") -FileUpload.setAttribute("type","file") - -document.getElementById("uploadButton").addEventListener("click",() => FileUpload.click()) - -FileUpload.addEventListener("input",() => { - if (FileUpload.files[0]) { - let opt = getOptionsForUploading() - let file = FileUpload.files[0] - - updateBtnTxt("Uploading file. This may take a while, so stay put.") - - let xmlhttp = new XMLHttpRequest() - - xmlhttp.addEventListener("error",function(e) { - updateBtnTxt(`Upload failed.
${e.toString()}`) - console.error(e) - }) - - xmlhttp.addEventListener("load",function() { - if (xmlhttp.status == 200) { - document.getElementById("CopyTB").value = `https://${location.hostname}/download/${xmlhttp.responseText}` - updateBtnTxt(`Upload complete.
Copy URL View URL`) - } else { - updateBtnTxt(`Upload failed.
${xmlhttp.responseText}`) - } - }) - - let fd = new FormData() - fd.append('file',file) - - xmlhttp.open("POST","/upload") - xmlhttp.setRequestHeader("monofile-upload-id",opt.uploadId) - xmlhttp.send(fd) - - } -}) \ No newline at end of file diff --git a/config.json b/config.json index 40180d4..3409ed3 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,28 @@ -{ - "maxDiscordFiles": 20, - "maxDiscordFileSize": 8388608, - "targetGuild": "1024080490677936248", - "targetChannel": "1024080525993971913", - "requestTimeout":120000 +{ + "maxDiscordFiles": 20, + "maxDiscordFileSize": 26214400, + "targetGuild": "1024080490677936248", + "targetChannel": "1024080525993971913", + "requestTimeout":120000, + "maxUploadIdLength":30, + + "accounts": { + "registrationEnabled": true, + "requiredForUpload": false + }, + + "webdrop": { + "accountRequired": false + }, + + "mail": { + "transport": { + "host": "smtp.fastmail.com", + "port": 465, + "secure": true + }, + "send": { + "from": "mono@fyle.uk" + } + } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3dc9115..455e4c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,2073 +1,2948 @@ -{ - "name": "monofile", - "version": "1.2.2", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "monofile", - "version": "1.2.2", - "license": "Unlicense", - "dependencies": { - "@types/body-parser": "^1.19.2", - "@types/express": "^4.17.14", - "@types/multer": "^1.4.7", - "axios": "^0.27.2", - "body-parser": "^1.20.0", - "discord.js": "^14.7.1", - "dotenv": "^16.0.2", - "express": "^4.18.1", - "multer": "^1.4.5-lts.1", - "typescript": "^4.8.3" - }, - "engines": { - "node": ">=v16.9.0" - } - }, - "node_modules/@discordjs/builders": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", - "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", - "dependencies": { - "@discordjs/util": "^0.1.0", - "@sapphire/shapeshift": "^3.7.1", - "discord-api-types": "^0.37.20", - "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.2", - "tslib": "^2.4.1" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@discordjs/collection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", - "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==", - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@discordjs/rest": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz", - "integrity": "sha512-lXgNFqHnbmzp5u81W0+frdXN6Etf4EUi8FAPcWpSykKd8hmlWh1xy6BmE0bsJypU1pxohaA8lQCgp70NUI3uzA==", - "dependencies": { - "@discordjs/collection": "^1.3.0", - "@discordjs/util": "^0.1.0", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.37.23", - "file-type": "^18.0.0", - "tslib": "^2.4.1", - "undici": "^5.13.0" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@discordjs/util": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.1.0.tgz", - "integrity": "sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==", - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@sapphire/shapeshift": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz", - "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@sapphire/snowflake": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz", - "integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==", - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.31", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", - "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" - }, - "node_modules/@types/multer": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", - "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/node": { - "version": "18.7.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz", - "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==" - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "node_modules/@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", - "dependencies": { - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "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": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "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/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.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/discord-api-types": { - "version": "0.37.25", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.25.tgz", - "integrity": "sha512-aCwA2sWnL1zPQgTELkkMzQneuWyCXXUjZCUKswesiE6RDCfOfxAPXOHg6ZTlBA5layPSikGCBBRjyh8S3Wzd+A==" - }, - "node_modules/discord.js": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", - "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", - "dependencies": { - "@discordjs/builders": "^1.4.0", - "@discordjs/collection": "^1.3.0", - "@discordjs/rest": "^1.4.0", - "@discordjs/util": "^0.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.20", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.4.1", - "undici": "^5.13.0", - "ws": "^8.11.0" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/dotenv": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", - "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/file-type": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", - "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", - "dependencies": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0", - "token-types": "^5.0.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "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", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "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==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dependencies": { - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "dependencies": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/ts-mixer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", - "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" - }, - "node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "node_modules/typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/undici": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz", - "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==", - "dependencies": { - "busboy": "^1.6.0" - }, - "engines": { - "node": ">=12.18" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - } - }, - "dependencies": { - "@discordjs/builders": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", - "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", - "requires": { - "@discordjs/util": "^0.1.0", - "@sapphire/shapeshift": "^3.7.1", - "discord-api-types": "^0.37.20", - "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.2", - "tslib": "^2.4.1" - } - }, - "@discordjs/collection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", - "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==" - }, - "@discordjs/rest": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz", - "integrity": "sha512-lXgNFqHnbmzp5u81W0+frdXN6Etf4EUi8FAPcWpSykKd8hmlWh1xy6BmE0bsJypU1pxohaA8lQCgp70NUI3uzA==", - "requires": { - "@discordjs/collection": "^1.3.0", - "@discordjs/util": "^0.1.0", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.37.23", - "file-type": "^18.0.0", - "tslib": "^2.4.1", - "undici": "^5.13.0" - } - }, - "@discordjs/util": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.1.0.tgz", - "integrity": "sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==" - }, - "@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" - }, - "@sapphire/shapeshift": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz", - "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==", - "requires": { - "fast-deep-equal": "^3.1.3", - "lodash": "^4.17.21" - } - }, - "@sapphire/snowflake": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz", - "integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==" - }, - "@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.31", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", - "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" - }, - "@types/multer": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", - "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", - "requires": { - "@types/express": "*" - } - }, - "@types/node": { - "version": "18.7.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz", - "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==" - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", - "requires": { - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "requires": { - "@types/node": "*" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "discord-api-types": { - "version": "0.37.25", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.25.tgz", - "integrity": "sha512-aCwA2sWnL1zPQgTELkkMzQneuWyCXXUjZCUKswesiE6RDCfOfxAPXOHg6ZTlBA5layPSikGCBBRjyh8S3Wzd+A==" - }, - "discord.js": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", - "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", - "requires": { - "@discordjs/builders": "^1.4.0", - "@discordjs/collection": "^1.3.0", - "@discordjs/rest": "^1.4.0", - "@discordjs/util": "^0.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.20", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.4.1", - "undici": "^5.13.0", - "ws": "^8.11.0" - } - }, - "dotenv": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", - "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "file-type": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", - "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", - "requires": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0", - "token-types": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", - "requires": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "requires": { - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "requires": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "requires": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - } - }, - "ts-mixer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", - "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" - }, - "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==" - }, - "undici": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz", - "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==", - "requires": { - "busboy": "^1.6.0" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "requires": {} - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - } - } -} +{ + "name": "monofile", + "version": "1.3.0-beta", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "monofile", + "version": "1.3.0-beta", + "license": "Unlicense", + "dependencies": { + "@fontsource/fira-code": "^5.0.8", + "@fontsource/inconsolata": "^5.0.8", + "@fontsource/source-sans-pro": "^5.0.8", + "@types/body-parser": "^1.19.2", + "@types/express": "^4.17.14", + "@types/multer": "^1.4.7", + "@types/nodemailer": "^6.4.8", + "axios": "^0.27.2", + "body-parser": "^1.20.0", + "bytes": "^3.1.2", + "cookie-parser": "^1.4.6", + "discord.js": "^14.7.1", + "dotenv": "^16.0.2", + "express": "^4.18.1", + "multer": "^1.4.5-lts.1", + "nodemailer": "^6.9.3", + "typescript": "^4.8.3" + }, + "devDependencies": { + "@rollup/plugin-node-resolve": "^15.0.1", + "@types/bytes": "^3.1.1", + "@types/cookie-parser": "^1.4.3", + "rollup": "^3.11.0", + "rollup-plugin-svelte": "^7.1.0", + "sass": "^1.57.1", + "svelte": "^3.55.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@discordjs/builders": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", + "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", + "dependencies": { + "@discordjs/util": "^0.1.0", + "@sapphire/shapeshift": "^3.7.1", + "discord-api-types": "^0.37.20", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.2", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@discordjs/collection": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", + "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@discordjs/rest": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz", + "integrity": "sha512-lXgNFqHnbmzp5u81W0+frdXN6Etf4EUi8FAPcWpSykKd8hmlWh1xy6BmE0bsJypU1pxohaA8lQCgp70NUI3uzA==", + "dependencies": { + "@discordjs/collection": "^1.3.0", + "@discordjs/util": "^0.1.0", + "@sapphire/async-queue": "^1.5.0", + "@sapphire/snowflake": "^3.2.2", + "discord-api-types": "^0.37.23", + "file-type": "^18.0.0", + "tslib": "^2.4.1", + "undici": "^5.13.0" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@discordjs/util": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.1.0.tgz", + "integrity": "sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@fontsource/fira-code": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-5.0.8.tgz", + "integrity": "sha512-kp/tJUVnjaZeLHENMBFTTSgP2B7+/rIboeofuMfoGB40s2U0DKXNqQcOqIF5PtDhJ5QTG1LcviYXMnc1yG6oYQ==" + }, + "node_modules/@fontsource/inconsolata": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/inconsolata/-/inconsolata-5.0.8.tgz", + "integrity": "sha512-KpBU6q1yCovfycaFprVEauh8U5RsWty3konFfUukyRRxZBK4Sf73XmGQc8iJ4CPrOP4dplGfdX2kjbRgdymajA==" + }, + "node_modules/@fontsource/source-sans-pro": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/source-sans-pro/-/source-sans-pro-5.0.8.tgz", + "integrity": "sha512-5U2UvIYRkCMozZ388gCE73PEpa2MFgN/0t9O4a1FF7bGT/MIneQWSL1XpWZ8iMVYdh6ntxRf3iFA6slCIuFgkg==" + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.1.tgz", + "integrity": "sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.0", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@sapphire/async-queue": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", + "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@sapphire/shapeshift": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz", + "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@sapphire/snowflake": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz", + "integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-lOGyCnw+2JVPKU3wIV0srU0NyALwTBJlVSx5DfMQOFuuohA8y9S8orImpuIQikZ0uIQ8gehrRjxgQC1rLRi11w==", + "dev": true + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "node_modules/@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "18.7.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz", + "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==" + }, + "node_modules/@types/nodemailer": { + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.8.tgz", + "integrity": "sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "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": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "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-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "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/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/discord-api-types": { + "version": "0.37.25", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.25.tgz", + "integrity": "sha512-aCwA2sWnL1zPQgTELkkMzQneuWyCXXUjZCUKswesiE6RDCfOfxAPXOHg6ZTlBA5layPSikGCBBRjyh8S3Wzd+A==" + }, + "node_modules/discord.js": { + "version": "14.7.1", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", + "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", + "dependencies": { + "@discordjs/builders": "^1.4.0", + "@discordjs/collection": "^1.3.0", + "@discordjs/rest": "^1.4.0", + "@discordjs/util": "^0.1.0", + "@sapphire/snowflake": "^3.2.2", + "@types/ws": "^8.5.3", + "discord-api-types": "^0.37.20", + "fast-deep-equal": "^3.1.3", + "lodash.snakecase": "^4.1.1", + "tslib": "^2.4.1", + "undici": "^5.13.0", + "ws": "^8.11.0" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/dotenv": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", + "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/file-type": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", + "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.2", + "strtok3": "^7.0.0", + "token-types": "^5.0.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "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", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/immutable": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", + "integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==", + "dev": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-builtin-module": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz", + "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemailer": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.3.tgz", + "integrity": "sha512-fy9v3NgTzBngrMFkDsKEj0r02U7jm6XfC3b52eoNV+GCrGj+s8pt5OqhiJdWKuw51zCTdiNR/IUD1z33LIIGpg==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/peek-readable": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", + "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.11.0.tgz", + "integrity": "sha512-+uWPPkpWQ2H3Qi7sNBcRfhhHJyUNgBYhG4wKe5wuGRj2m55kpo+0p5jubKNBjQODyPe6tSBE3tNpdDwEisQvAQ==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-svelte": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", + "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", + "dev": true, + "dependencies": { + "require-relative": "^0.8.7", + "rollup-pluginutils": "^2.8.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "rollup": ">=2.0.0", + "svelte": ">=3.5.0" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sass": { + "version": "1.57.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz", + "integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/strtok3": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", + "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svelte": { + "version": "3.55.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.55.1.tgz", + "integrity": "sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", + "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/ts-mixer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", + "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undici": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz", + "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==", + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + } + }, + "dependencies": { + "@discordjs/builders": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", + "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", + "requires": { + "@discordjs/util": "^0.1.0", + "@sapphire/shapeshift": "^3.7.1", + "discord-api-types": "^0.37.20", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.2", + "tslib": "^2.4.1" + } + }, + "@discordjs/collection": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", + "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==" + }, + "@discordjs/rest": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz", + "integrity": "sha512-lXgNFqHnbmzp5u81W0+frdXN6Etf4EUi8FAPcWpSykKd8hmlWh1xy6BmE0bsJypU1pxohaA8lQCgp70NUI3uzA==", + "requires": { + "@discordjs/collection": "^1.3.0", + "@discordjs/util": "^0.1.0", + "@sapphire/async-queue": "^1.5.0", + "@sapphire/snowflake": "^3.2.2", + "discord-api-types": "^0.37.23", + "file-type": "^18.0.0", + "tslib": "^2.4.1", + "undici": "^5.13.0" + } + }, + "@discordjs/util": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.1.0.tgz", + "integrity": "sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==" + }, + "@fontsource/fira-code": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-5.0.8.tgz", + "integrity": "sha512-kp/tJUVnjaZeLHENMBFTTSgP2B7+/rIboeofuMfoGB40s2U0DKXNqQcOqIF5PtDhJ5QTG1LcviYXMnc1yG6oYQ==" + }, + "@fontsource/inconsolata": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/inconsolata/-/inconsolata-5.0.8.tgz", + "integrity": "sha512-KpBU6q1yCovfycaFprVEauh8U5RsWty3konFfUukyRRxZBK4Sf73XmGQc8iJ4CPrOP4dplGfdX2kjbRgdymajA==" + }, + "@fontsource/source-sans-pro": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/source-sans-pro/-/source-sans-pro-5.0.8.tgz", + "integrity": "sha512-5U2UvIYRkCMozZ388gCE73PEpa2MFgN/0t9O4a1FF7bGT/MIneQWSL1XpWZ8iMVYdh6ntxRf3iFA6slCIuFgkg==" + }, + "@rollup/plugin-node-resolve": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.1.tgz", + "integrity": "sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.0", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + } + }, + "@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "dependencies": { + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } + } + }, + "@sapphire/async-queue": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", + "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" + }, + "@sapphire/shapeshift": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz", + "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==", + "requires": { + "fast-deep-equal": "^3.1.3", + "lodash": "^4.17.21" + } + }, + "@sapphire/snowflake": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz", + "integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==" + }, + "@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-lOGyCnw+2JVPKU3wIV0srU0NyALwTBJlVSx5DfMQOFuuohA8y9S8orImpuIQikZ0uIQ8gehrRjxgQC1rLRi11w==", + "dev": true + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/cookie-parser": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true + }, + "@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "requires": { + "@types/express": "*" + } + }, + "@types/node": { + "version": "18.7.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz", + "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==" + }, + "@types/nodemailer": { + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.8.tgz", + "integrity": "sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, + "@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "requires": { + "@types/node": "*" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + } + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "discord-api-types": { + "version": "0.37.25", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.25.tgz", + "integrity": "sha512-aCwA2sWnL1zPQgTELkkMzQneuWyCXXUjZCUKswesiE6RDCfOfxAPXOHg6ZTlBA5layPSikGCBBRjyh8S3Wzd+A==" + }, + "discord.js": { + "version": "14.7.1", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", + "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", + "requires": { + "@discordjs/builders": "^1.4.0", + "@discordjs/collection": "^1.3.0", + "@discordjs/rest": "^1.4.0", + "@discordjs/util": "^0.1.0", + "@sapphire/snowflake": "^3.2.2", + "@types/ws": "^8.5.3", + "discord-api-types": "^0.37.20", + "fast-deep-equal": "^3.1.3", + "lodash.snakecase": "^4.1.1", + "tslib": "^2.4.1", + "undici": "^5.13.0", + "ws": "^8.11.0" + } + }, + "dotenv": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", + "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "file-type": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", + "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", + "requires": { + "readable-web-to-node-stream": "^3.0.2", + "strtok3": "^7.0.0", + "token-types": "^5.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + } + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "immutable": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", + "integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-builtin-module": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz", + "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==", + "dev": true, + "requires": { + "builtin-modules": "^3.3.0" + } + }, + "is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "nodemailer": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.3.tgz", + "integrity": "sha512-fy9v3NgTzBngrMFkDsKEj0r02U7jm6XfC3b52eoNV+GCrGj+s8pt5OqhiJdWKuw51zCTdiNR/IUD1z33LIIGpg==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "peek-readable": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", + "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "requires": { + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==", + "dev": true + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.11.0.tgz", + "integrity": "sha512-+uWPPkpWQ2H3Qi7sNBcRfhhHJyUNgBYhG4wKe5wuGRj2m55kpo+0p5jubKNBjQODyPe6tSBE3tNpdDwEisQvAQ==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-svelte": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", + "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", + "dev": true, + "requires": { + "require-relative": "^0.8.7", + "rollup-pluginutils": "^2.8.2" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass": { + "version": "1.57.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz", + "integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "strtok3": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", + "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", + "requires": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "svelte": { + "version": "3.55.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.55.1.tgz", + "integrity": "sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "token-types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", + "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "requires": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + } + }, + "ts-mixer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", + "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==" + }, + "undici": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz", + "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==", + "requires": { + "busboy": "^1.6.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } +} diff --git a/package.json b/package.json index f3ccbe8..d3f5775 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,41 @@ -{ - "name": "monofile", - "version": "1.2.3", - "description": "Discord-based file sharing", - "main": "index.js", - "scripts": { - "start": "node ./out/index.js", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "Unlicense", - "engines": { - "node": ">=v18" - }, - "dependencies": { - "@types/body-parser": "^1.19.2", - "@types/express": "^4.17.14", - "@types/multer": "^1.4.7", - "axios": "^0.27.2", - "body-parser": "^1.20.0", - "discord.js": "^14.7.1", - "dotenv": "^16.0.2", - "express": "^4.18.1", - "multer": "^1.4.5-lts.1", - "typescript": "^4.8.3" - } -} +{ + "name": "monofile", + "version": "1.3.0", + "description": "Discord-based file sharing", + "main": "index.js", + "scripts": { + "start": "node ./out/server/index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "nbitzz", + "license": "Unlicense", + "engines": { + "node": ">=v18" + }, + "dependencies": { + "@types/body-parser": "^1.19.2", + "@types/express": "^4.17.14", + "@types/multer": "^1.4.7", + "@types/nodemailer": "^6.4.8", + "axios": "^0.27.2", + "body-parser": "^1.20.0", + "bytes": "^3.1.2", + "cookie-parser": "^1.4.6", + "discord.js": "^14.7.1", + "dotenv": "^16.0.2", + "express": "^4.18.1", + "multer": "^1.4.5-lts.1", + "nodemailer": "^6.9.3", + "typescript": "^4.8.3" + }, + "devDependencies": { + "@rollup/plugin-node-resolve": "^15.0.1", + "@types/bytes": "^3.1.1", + "@types/cookie-parser": "^1.4.3", + "rollup": "^3.11.0", + "rollup-plugin-svelte": "^7.1.0", + "sass": "^1.57.1", + "svelte": "^3.55.1" + } +} diff --git a/pages/base.html b/pages/base.html deleted file mode 100644 index 36ddfcc..0000000 --- a/pages/base.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - monofile - - - - - - - - - -
-

- monofile $Version -

-

Discord-based file sharing

-
- Before sharing files, please remember: -
    -
  • Do NOT share sensitive information via monofile
  • -
  • Do NOT share illegal content via monofile
  • -
  • The owner of this instance reserves the right to remove your files
  • -
-
-
-
- - -
-
- -
-

- Max filesize on instance: $MaxInstanceFilesize -
- Hosting $FileNum files -

-

made by nbitzz — github$otherText

-
-
- - - - - - - - - \ No newline at end of file diff --git a/pages/download.html b/pages/download.html index 41fff40..d2cec08 100644 --- a/pages/download.html +++ b/pages/download.html @@ -1,102 +1,54 @@ - - - - - - - monofile - - - - - - - - -
-

- $FileName -

-

file id: $FileId

- -

- May take a while to download. Stay put. -

-
-
- - + + + + + + + $FileId + + + + + + + + + + + + + + + +
+
+

+ $FileName +

+

+ $FileSize  —  uploaded by $Uploader +

+ + + + + +
+
+
+ + \ No newline at end of file diff --git a/pages/error.html b/pages/error.html index b8422b8..228bb87 100644 --- a/pages/error.html +++ b/pages/error.html @@ -1,72 +1,41 @@ - - - - - - - - - - - - monofile - - - - -
-

- monofile $Version -

-

Discord-based file sharing

-
-

$ErrorCode

-

$ErrorMessage

-
-
-
- - + + + + + + + + + + + + + + + $code + + + + + + +

+ $code +  $text +

+ + \ No newline at end of file diff --git a/pages/index.html b/pages/index.html new file mode 100644 index 0000000..453434d --- /dev/null +++ b/pages/index.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + monofile + + + + + + + + + + + + \ No newline at end of file diff --git a/rollup.config.mjs b/rollup.config.mjs new file mode 100644 index 0000000..b8f64fd --- /dev/null +++ b/rollup.config.mjs @@ -0,0 +1,17 @@ +import svelte from 'rollup-plugin-svelte' +import resolve from "@rollup/plugin-node-resolve" + +export default [ + { + input: "src/client/index.js", + output: { + file: 'out/client/index.js', + format: 'esm', + sourcemap:true + }, + plugins: [ + resolve({ browser: true }), + svelte({}) + ] + } +] \ No newline at end of file diff --git a/src/client/index.js b/src/client/index.js new file mode 100644 index 0000000..f8e4e62 --- /dev/null +++ b/src/client/index.js @@ -0,0 +1,5 @@ +import App from "../svelte/App.svelte" + +new App({ + target: document.body +}) \ No newline at end of file diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 5d32061..0000000 --- a/src/index.ts +++ /dev/null @@ -1,172 +0,0 @@ -/* - i really should split this up into different modules -*/ - -import bodyParser from "body-parser" -import multer, {memoryStorage} from "multer" -import Discord, { IntentsBitField, Client } from "discord.js" -import express from "express" -import fs from "fs" -import axios, { AxiosResponse } from "axios" - -import Files from "./lib/files" -require("dotenv").config() - -const multerSetup = multer({storage:memoryStorage()}) -let pkg = require(`${process.cwd()}/package.json`) -let app = express() -let config = require(`${process.cwd()}/config.json`) - -app.use("/static",express.static("assets")) -app.use(bodyParser.text({limit:(config.maxDiscordFileSize*config.maxDiscordFiles)+1048576,type:["application/json","text/plain"]})) -// funcs - -function ThrowError(response:express.Response,code:number,errorMessage:string) { - fs.readFile(__dirname+"/../pages/error.html",(err,buf) => { - if (err) {response.sendStatus(500);console.log(err);return} - response.status(code) - response.send(buf.toString().replace(/\$ErrorCode/g,code.toString()).replace(/\$ErrorMessage/g,errorMessage).replace(/\$Version/g,pkg.version)) - }) -} - -// init data - -if (!fs.existsSync(__dirname+"/../.data/")) fs.mkdirSync(__dirname+"/../.data/") - - - -// discord - -let client = new Client({intents:[ - IntentsBitField.Flags.GuildMessages, - IntentsBitField.Flags.MessageContent -],rest:{timeout:config.requestTimeout}}) - -let files = new Files(client,config) - -// routes (could probably make these use routers) - -// index, clone - -app.get("/", function(req,res) { - fs.readFile(__dirname+"/../pages/base.html",(err,buf) => { - if (err) {res.sendStatus(500);console.log(err);return} - res.send( - buf.toString() - .replace("$MaxInstanceFilesize",`${(config.maxDiscordFileSize*config.maxDiscordFiles)/1048576}MB`) - .replace(/\$Version/g,pkg.version) - .replace(/\$Handler/g,"upload_file") - .replace(/\$UploadButtonText/g,"Upload file") - .replace(/\$otherPath/g,"/clone") - .replace(/\$otherText/g,"clone from url...") - .replace(/\$FileNum/g,Object.keys(files.files).length.toString()) - ) - }) -}) - -app.get("/clone", function(req,res) { - fs.readFile(__dirname+"/../pages/base.html",(err,buf) => { - if (err) {res.sendStatus(500);console.log(err);return} - res.send( - buf.toString() - .replace("$MaxInstanceFilesize",`${(config.maxDiscordFileSize*config.maxDiscordFiles)/1048576}MB`) - .replace(/\$Version/g,pkg.version) - .replace(/\$Handler/g,"clone_file") - .replace(/\$UploadButtonText/g,"Input a URL") - .replace(/\$otherPath/g,"/") - .replace(/\$otherText/g,"upload file...") - .replace(/\$FileNum/g,Object.keys(files.files).length.toString()) - ) - }) -}) - -// upload handlers - -app.post("/upload",multerSetup.single('file'),async (req,res) => { - if (req.file) { - try { - files.uploadFile({name:req.file.originalname,mime:req.file.mimetype,uploadId:req.header("monofile-upload-id")},req.file.buffer) - .then((uID) => res.send(uID)) - .catch((stat) => {res.status(stat.status);res.send(`[err] ${stat.message}`)}) - } catch { - res.status(400) - res.send("[err] bad request") - } - } else { - res.status(400) - res.send("[err] bad request") - } -}) - -app.post("/clone",(req,res) => { - try { - let j = JSON.parse(req.body) - if (!j.url) { - res.status(400) - res.send("[err] invalid url") - } - axios.get(j.url,{responseType:"arraybuffer"}).then((data:AxiosResponse) => { - files.uploadFile({name:j.url.split("/")[req.body.split("/").length-1] || "generic",mime:data.headers["content-type"],uploadId:j.uploadId},Buffer.from(data.data)) - .then((uID) => res.send(uID)) - .catch((stat) => {res.status(stat.status);res.send(`[err] ${stat.message}`)}) - }).catch((err) => { - console.log(err) - res.status(400) - res.send(`[err] failed to fetch data`) - }) - } catch { - res.status(500) - res.send("[err] an error occured") - } -}) - -// serve files & download page - -app.get("/download/:fileId",(req,res) => { - if (files.getFilePointer(req.params.fileId)) { - let file = files.getFilePointer(req.params.fileId) - - fs.readFile(__dirname+"/../pages/download.html",(err,buf) => { - if (err) {res.sendStatus(500);console.log(err);return} - res.send( - buf.toString() - .replace(/\$FileId/g,req.params.fileId) - .replace(/\$Version/g,pkg.version) - .replace(/\$FileName/g, - file.filename - .replace(/\&/g,"&") - .replace(/\/g,">") - ) - ) - }) - } else { - ThrowError(res,404,"File not found.") - } -}) - -app.get("/file/:fileId",async (req,res) => { - files.readFileStream(req.params.fileId).then(f => { - res.setHeader("Content-Type",f.contentType) - res.status(200) - f.dataStream.pipe(res) - }).catch((err) => { - ThrowError(res,err.status,err.message) - }) -}) - -app.get("*",(req,res) => { - ThrowError(res,404,"Page not found.") -}) - -app.get("/server",(req,res) => { - res.send(JSON.stringify({...config,version:pkg.version})) -}) - -// listen on 3000 or MONOFILE_PORT - -app.listen(process.env.MONOFILE_PORT || 3000,function() { - console.log("Web OK!") -}) - -client.login(process.env.TOKEN) \ No newline at end of file diff --git a/src/lib/files.ts b/src/lib/files.ts deleted file mode 100644 index 8eb0f42..0000000 --- a/src/lib/files.ts +++ /dev/null @@ -1,246 +0,0 @@ -import axios from "axios"; -import Discord, { Client, TextBasedChannel } from "discord.js"; -import { readFile, writeFile } from "fs"; -import { Readable } from "node:stream" - -export let id_check_regex = /[A-Za-z0-9_\-\.]+/ - - -export interface FileUploadSettings { - name?: string, - mime: string, - uploadId?: string -} - -export interface Configuration { - maxDiscordFiles: number, - maxDiscordFileSize: number, - targetGuild: string, - targetChannel: string, - requestTimeout: number -} - -export interface FilePointer { - filename:string, - mime:string, - messageids:string[] -} - -export interface StatusCodeError { - status: number, - message: string -} - -/* */ - -export default class Files { - - config: Configuration - client: Client - files: {[key:string]:FilePointer} = {} - uploadChannel?: TextBasedChannel - - constructor(client: Client, config: Configuration) { - - this.config = config; - this.client = client; - - client.on("ready",() => { - console.log("Discord OK!") - - client.guilds.fetch(config.targetGuild).then((g) => { - g.channels.fetch(config.targetChannel).then((a) => { - if (a?.isTextBased()) { - this.uploadChannel = a - } - }) - }) - }) - - readFile(process.cwd()+"/.data/files.json",(err,buf) => { - if (err) {console.log(err);return} - this.files = JSON.parse(buf.toString() || "{}") - }) - - } - - uploadFile(settings:FileUploadSettings,fBuffer:Buffer):Promise { - return new Promise(async (resolve,reject) => { - if (!this.uploadChannel) { - reject({status:503,message:"server is not ready - please try again later"}) - return - } - - if (!settings.name || !settings.mime) { - reject({status:400,message:"missing name/mime"}); - return - } - - let uploadId = (settings.uploadId || Math.random().toString().slice(2)).toString(); - - if ((uploadId.match(id_check_regex) || [])[0] != uploadId || uploadId.length > 30) { - reject({status:400,message:"invalid id"});return - } - - if (this.files[uploadId]) { - reject({status:400,message:"a file with this id already exists"}); - return - } - - if (settings.name.length > 128) { - reject({status:400,message:"name too long"}); - return - } - - if (settings.mime.length > 128) { - reject({status:400,message:"mime too long"}); - return - } - - // get buffer - if (fBuffer.byteLength >= (this.config.maxDiscordFileSize*this.config.maxDiscordFiles)) { - reject({status:400,message:"file too large"}); - return - } - - // generate buffers to upload - let toUpload = [] - for (let i = 0; i < Math.ceil(fBuffer.byteLength/this.config.maxDiscordFileSize); i++) { - toUpload.push( - fBuffer.subarray( - i*this.config.maxDiscordFileSize, - Math.min( - fBuffer.byteLength, - (i+1)*this.config.maxDiscordFileSize - ) - ) - ) - } - - // begin uploading - let uploadTmplt:Discord.AttachmentBuilder[] = toUpload.map((e) => { - return new Discord.AttachmentBuilder(e) - .setName(Math.random().toString().slice(2)) - }) - let uploadGroups = [] - for (let i = 0; i < Math.ceil(uploadTmplt.length/10); i++) { - uploadGroups.push(uploadTmplt.slice(i*10,((i+1)*10))) - } - - let msgIds = [] - - for (let i = 0; i < uploadGroups.length; i++) { - - let ms = await this.uploadChannel.send({ - files:uploadGroups[i] - }).catch((e) => {console.error(e)}) - - if (ms) { - msgIds.push(ms.id) - } else { - reject({status:500,message:"please try again"}); return - } - } - - // save - - resolve(await this.writeFile( - uploadId, - { - filename:settings.name, - messageids:msgIds, - mime:settings.mime - } - )) - }) - } - - // fs - - writeFile(uploadId: string, file: FilePointer):Promise { - return new Promise((resolve, reject) => { - - this.files[uploadId] = file - - writeFile(process.cwd()+"/.data/files.json",JSON.stringify(this.files),(err) => { - - if (err) { - reject({status:500,message:"please try again"}); - delete this.files[uploadId]; - return - } - - resolve(uploadId) - - }) - - }) - } - - // todo: move read code here - - readFileStream(uploadId: string):Promise<{dataStream:Readable,contentType:string}> { - return new Promise(async (resolve,reject) => { - if (!this.uploadChannel) { - reject({status:503,message:"server is not ready - please try again later"}) - return - } - - if (this.files[uploadId]) { - let file = this.files[uploadId] - - let dataStream = new Readable({ - read(){} - }) - - resolve({ - contentType: file.mime, - dataStream: dataStream - }) - - for (let i = 0; i < file.messageids.length; i++) { - let msg = await this.uploadChannel.messages.fetch(file.messageids[i]).catch(() => {return null}) - if (msg?.attachments) { - let attach = Array.from(msg.attachments.values()) - for (let i = 0; i < attach.length; i++) { - let d = await axios.get(attach[i].url,{responseType:"arraybuffer"}).catch((e:Error) => {console.error(e)}) - if (d) { - dataStream.push(d.data) - } else { - reject({status:500,message:"internal server error"}) - dataStream.destroy(new Error("file read error")) - return - } - } - } - } - - dataStream.push(null) - - } else { - reject({status:404,message:"not found"}) - } - }) - } - - unlink(uploadId:string):Promise { - return new Promise((resolve,reject) => { - let tmp = this.files[uploadId]; - delete this.files[uploadId]; - writeFile(process.cwd()+"/.data/files.json",JSON.stringify(this.files),(err) => { - if (err) { - this.files[uploadId] = tmp - reject() - } else { - resolve() - } - }) - - }) - } - - getFilePointer(uploadId:string):FilePointer { - return this.files[uploadId] - } - -} diff --git a/src/server/index.ts b/src/server/index.ts new file mode 100644 index 0000000..3abd277 --- /dev/null +++ b/src/server/index.ts @@ -0,0 +1,164 @@ +import cookieParser from "cookie-parser"; +import { IntentsBitField, Client } from "discord.js" +import express from "express" +import fs from "fs" +import bytes from "bytes"; + +import ServeError from "./lib/errors" +import Files from "./lib/files" +import * as auth from "./lib/auth" +import * as Accounts from "./lib/accounts" + +import * as authRoutes from "./routes/authRoutes"; +import * as fileApiRoutes from "./routes/fileApiRoutes"; +import * as adminRoutes from "./routes/adminRoutes"; +import * as primaryApi from "./routes/primaryApi"; + +require("dotenv").config() + +let pkg = require(`${process.cwd()}/package.json`) +let app = express() +let config = require(`${process.cwd()}/config.json`) + +app.use("/static/assets",express.static("assets")) +app.use("/static/style",express.static("out/style")) +app.use("/static/js",express.static("out/client")) + +//app.use(bodyParser.text({limit:(config.maxDiscordFileSize*config.maxDiscordFiles)+1048576,type:["application/json","text/plain"]})) + +app.use(cookieParser()) + +app.get("/server",(req,res) => { + res.send(JSON.stringify({ + ...config, + version:pkg.version, + files:Object.keys(files.files).length + })) +}) + +app + .use("/auth",authRoutes.authRoutes) + .use("/admin",adminRoutes.adminRoutes) + .use("/files", fileApiRoutes.fileApiRoutes) + .use(primaryApi.primaryApi) +// funcs + +// init data + +if (!fs.existsSync(__dirname+"/../.data/")) fs.mkdirSync(__dirname+"/../.data/") + + + +// discord + +let client = new Client({intents:[ + IntentsBitField.Flags.GuildMessages, + IntentsBitField.Flags.MessageContent +],rest:{timeout:config.requestTimeout}}) + +let files = new Files(client,config) + +authRoutes.setFilesObj(files) +adminRoutes.setFilesObj(files) +fileApiRoutes.setFilesObj(files) +primaryApi.setFilesObj(files) + +// routes (could probably make these use routers) + +// index, clone + +app.get("/", function(req,res) { + res.sendFile(process.cwd()+"/pages/index.html") +}) + +// serve download page + +app.get("/download/:fileId",(req,res) => { + if (files.getFilePointer(req.params.fileId)) { + let file = files.getFilePointer(req.params.fileId) + + if (file.visibility == "private" && Accounts.getFromToken(req.cookies.auth)?.id != file.owner) { + ServeError(res,403,"you do not own this file") + return + } + + fs.readFile(process.cwd()+"/pages/download.html",(err,buf) => { + let fileOwner = file.owner ? Accounts.getFromId(file.owner) : undefined; + if (err) {res.sendStatus(500);console.log(err);return} + res.send( + buf.toString() + .replace(/\$FileId/g,req.params.fileId) + .replace(/\$Version/g,pkg.version) + .replace(/\$FileSize/g,file.sizeInBytes ? bytes(file.sizeInBytes) : "[File size unknown]") + .replace(/\$FileName/g, + file.filename + .replace(/\&/g,"&") + .replace(/\/g,">") + ) + .replace(/\<\!\-\-metaTags\-\-\>/g, + ( + file.mime.startsWith("image/") + ? `` + : ( + file.mime.startsWith("video/") + ? ( + ` + + + + ` + // quick lazy fix as a fallback + // maybe i'll improve this later, but probably not. + + ((file.sizeInBytes||0) >= 26214400 ? ` + + ` : "") + ) + : "" + ) + ) + + ( + fileOwner?.embed?.largeImage && file.visibility!="anonymous" + ? `` + : "" + ) + + `\n` + ) + .replace(/\<\!\-\-preview\-\-\>/g, + file.mime.startsWith("image/") + ? `
` + : ( + file.mime.startsWith("video/") + ? `
` + : ( + file.mime.startsWith("audio/") + ? `
` + : "" + ) + ) + ) + .replace(/\$Uploader/g,!file.owner||file.visibility=="anonymous" ? "Anonymous" : `@${fileOwner?.username || "Deleted User"}`) + ) + }) + } else { + ServeError(res,404,"file not found") + } +}) + + +/* + routes should be in this order: + + index + api + dl pages + file serving +*/ + +// listen on 3000 or MONOFILE_PORT + +app.listen(process.env.MONOFILE_PORT || 3000,function() { + console.log("Web OK!") +}) + +client.login(process.env.TOKEN) \ No newline at end of file diff --git a/src/server/lib/accounts.ts b/src/server/lib/accounts.ts new file mode 100644 index 0000000..270ed18 --- /dev/null +++ b/src/server/lib/accounts.ts @@ -0,0 +1,132 @@ +import crypto from "crypto" +import * as auth from "./auth"; +import { readFile, writeFile } from "fs/promises" +import { FileVisibility } from "./files"; + +// this is probably horrible +// but i don't even care anymore + +export let Accounts: Account[] = [] + +export interface Account { + id : string + username : string + email? : string + password : { + hash : string + salt : string + } + files : string[] + admin : boolean + defaultFileVisibility : FileVisibility + customCSS? : string + + embed? : { + color? : string + largeImage? : boolean + } +} + +export function create(username:string,pwd:string,admin:boolean=false):Promise { + return new Promise((resolve,reject) => { + let accId = crypto.randomBytes(12).toString("hex") + + Accounts.push( + { + id: accId, + username: username, + password: password.hash(pwd), + files: [], + admin: admin, + defaultFileVisibility: "public" + } + ) + + save().then(() => resolve(accId)) + }) +} + +export function getFromUsername(username:string) { + return Accounts.find(e => e.username == username) +} + +export function getFromId(id:string) { + return Accounts.find(e => e.id == id) +} + +export function getFromToken(token:string) { + let accId = auth.validate(token) + if (!accId) return + return getFromId(accId) +} + +export function deleteAccount(id:string) { + Accounts.splice(Accounts.findIndex(e => e.id == id),1) + return save() +} + +export namespace password { + export function hash(password:string,_salt?:string) { + let salt = _salt || crypto.randomBytes(12).toString('base64') + let hash = crypto.createHash('sha256').update(`${salt}${password}`).digest('hex') + + return { + salt:salt, + hash:hash + } + } + + export function set(id:string,password:string) { + let acc = Accounts.find(e => e.id == id) + if (!acc) return + + acc.password = hash(password) + return save() + } + + export function check(id:string,password:string) { + let acc = Accounts.find(e => e.id == id) + if (!acc) return + + return acc.password.hash == hash(password,acc.password.salt).hash + } +} + +export namespace files { + export function index(accountId:string,fileId:string) { + // maybe replace with a obj like + // { x:true } + // for faster lookups? not sure if it would be faster + let acc = Accounts.find(e => e.id == accountId) + if (!acc) return + if (acc.files.find(e => e == fileId)) return + + acc.files.push(fileId) + return save() + } + + export function deindex(accountId:string,fileId:string, noWrite:boolean=false) { + let acc = Accounts.find(e => e.id == accountId) + if (!acc) return + let fi = acc.files.findIndex(e => e == fileId) + if (fi) { + acc.files.splice(fi,1) + if (!noWrite) return save() + } + } +} + +export function save() { + return writeFile(`${process.cwd()}/.data/accounts.json`,JSON.stringify(Accounts)) + .catch((err) => console.error(err)) +} + +readFile(`${process.cwd()}/.data/accounts.json`) + .then((buf) => { + Accounts = JSON.parse(buf.toString()) + }).catch(err => console.error(err)) + .finally(() => { + if (!Accounts.find(e => e.admin)) { + create("admin","admin",true) + } + }) \ No newline at end of file diff --git a/src/server/lib/auth.ts b/src/server/lib/auth.ts new file mode 100644 index 0000000..e477cba --- /dev/null +++ b/src/server/lib/auth.ts @@ -0,0 +1,58 @@ +import crypto from "crypto" +import { readFile, writeFile } from "fs/promises" +export let AuthTokens: AuthToken[] = [] +export let AuthTokenTO:{[key:string]:NodeJS.Timeout} = {} + +export interface AuthToken { + account: string, + token: string, + expire: number +} + +export function create(id:string,expire:number=(24*60*60*1000)) { + let token = { + account:id, + token:crypto.randomBytes(12).toString('hex'), + expire:Date.now()+expire + } + + AuthTokens.push(token) + tokenTimer(token) + + save() + + return token.token +} + +export function validate(token:string) { + return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.account +} + +export function tokenTimer(token:AuthToken) { + if (Date.now() >= token.expire) { + invalidate(token.token) + return + } + + AuthTokenTO[token.token] = setTimeout(() => invalidate(token.token),token.expire-Date.now()) +} + +export function invalidate(token:string) { + if (AuthTokenTO[token]) { + clearTimeout(AuthTokenTO[token]) + } + + AuthTokens.splice(AuthTokens.findIndex(e => e.token == token),1) + save() +} + +export function save() { + writeFile(`${process.cwd()}/.data/tokens.json`,JSON.stringify(AuthTokens)) + .catch((err) => console.error(err)) +} + +readFile(`${process.cwd()}/.data/tokens.json`) + .then((buf) => { + AuthTokens = JSON.parse(buf.toString()) + AuthTokens.forEach(e => tokenTimer(e)) + }).catch(err => console.error(err)) \ No newline at end of file diff --git a/src/server/lib/errors.ts b/src/server/lib/errors.ts new file mode 100644 index 0000000..6e67f33 --- /dev/null +++ b/src/server/lib/errors.ts @@ -0,0 +1,37 @@ +import { Response } from "express"; +import { readFile } from "fs/promises" + +let errorPage:string + +export default async function ServeError( + res:Response, + code:number, + reason:string +) { + // fetch error page if not cached + if (!errorPage) { + errorPage = + ( + await readFile(`${process.cwd()}/pages/error.html`) + .catch((err) => console.error(err)) + || "
$code $text
" + ) + .toString() + } + + // serve error + res.statusMessage = reason + res.status(code) + res.header("x-backup-status-message", reason) // glitch default nginx configuration + res.send( + errorPage + .replace(/\$code/g,code.toString()) + .replace(/\$text/g,reason) + ) +} + +export function Redirect(res:Response,url:string) { + res.status(302) + res.header("Location",url) + res.send() +} \ No newline at end of file diff --git a/src/server/lib/files.ts b/src/server/lib/files.ts new file mode 100644 index 0000000..40fd33d --- /dev/null +++ b/src/server/lib/files.ts @@ -0,0 +1,437 @@ +import axios from "axios"; +import Discord, { Client, TextBasedChannel } from "discord.js"; +import { readFile, writeFile } from "fs"; +import { Readable } from "node:stream"; +import { files } from "./accounts"; + +import * as Accounts from "./accounts"; + +export let id_check_regex = /[A-Za-z0-9_\-\.\!]+/ +export let alphanum = Array.from("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") + +// bad solution but whatever + +export type FileVisibility = "public" | "anonymous" | "private" + +export function generateFileId(length:number=5) { + let fid = "" + for (let i = 0; i < length; i++) { + fid += alphanum[Math.floor(Math.random()*alphanum.length)] + } + return fid +} + +export interface FileUploadSettings { + name?: string, + mime: string, + uploadId?: string, + owner?:string +} + +export interface Configuration { + maxDiscordFiles: number, + maxDiscordFileSize: number, + targetGuild: string, + targetChannel: string, + requestTimeout: number, + maxUploadIdLength: number, + + accounts: { + registrationEnabled: boolean, + requiredForUpload: boolean + } +} + +export interface FilePointer { + filename:string, + mime:string, + messageids:string[], + owner?:string, + sizeInBytes?:number, + tag?:string, + visibility?:FileVisibility, + reserved?: boolean, + chunkSize?: number +} + +export interface StatusCodeError { + status: number, + message: string +} + +/* */ + +export default class Files { + + config: Configuration + client: Client + files: {[key:string]:FilePointer} = {} + uploadChannel?: TextBasedChannel + + constructor(client: Client, config: Configuration) { + + this.config = config; + this.client = client; + + client.on("ready",() => { + console.log("Discord OK!") + + client.guilds.fetch(config.targetGuild).then((g) => { + g.channels.fetch(config.targetChannel).then((a) => { + if (a?.isTextBased()) { + this.uploadChannel = a + } + }) + }) + }) + + readFile(process.cwd()+"/.data/files.json",(err,buf) => { + if (err) {console.log(err);return} + this.files = JSON.parse(buf.toString() || "{}") + }) + + } + + uploadFile(settings:FileUploadSettings,fBuffer:Buffer):Promise { + return new Promise(async (resolve,reject) => { + if (!this.uploadChannel) { + reject({status:503,message:"server is not ready - please try again later"}) + return + } + + if (!settings.name || !settings.mime) { + reject({status:400,message:"missing name/mime"}); + return + } + + if (!settings.owner && this.config.accounts.requiredForUpload) { + reject({status:401,message:"an account is required for upload"}); + return + } + + let uploadId = (settings.uploadId || generateFileId()).toString(); + + if ((uploadId.match(id_check_regex) || [])[0] != uploadId || uploadId.length > this.config.maxUploadIdLength) { + reject({status:400,message:"invalid id"});return + } + + if (this.files[uploadId] && (settings.owner ? this.files[uploadId].owner != settings.owner : true)) { + reject({status:400,message:"you are not the owner of this file id"}); + return + } + + if (this.files[uploadId] && this.files[uploadId].reserved) { + reject({status:400,message:"already uploading this file. if your file is stuck in this state, contact an administrator"}); + return + } + + if (settings.name.length > 128) { + reject({status:400,message:"name too long"}); + return + } + + if (settings.mime.length > 128) { + reject({status:400,message:"mime too long"}); + return + } + + // reserve file, hopefully should prevent + // large files breaking + + let ogf = this.files[uploadId] + + this.files[uploadId] = { + filename:settings.name, + messageids:[], + mime:settings.mime, + sizeInBytes:0, + + owner:settings.owner, + visibility: settings.owner ? "private" : "public", + reserved: true, + + chunkSize: this.config.maxDiscordFileSize + } + + // save + + if (settings.owner) { + await files.index(settings.owner,uploadId) + } + + // get buffer + if (fBuffer.byteLength >= (this.config.maxDiscordFileSize*this.config.maxDiscordFiles)) { + reject({status:400,message:"file too large"}); + return + } + + // generate buffers to upload + let toUpload = [] + for (let i = 0; i < Math.ceil(fBuffer.byteLength/this.config.maxDiscordFileSize); i++) { + toUpload.push( + fBuffer.subarray( + i*this.config.maxDiscordFileSize, + Math.min( + fBuffer.byteLength, + (i+1)*this.config.maxDiscordFileSize + ) + ) + ) + } + + // begin uploading + let uploadTmplt:Discord.AttachmentBuilder[] = toUpload.map((e) => { + return new Discord.AttachmentBuilder(e) + .setName(Math.random().toString().slice(2)) + }) + let uploadGroups = [] + for (let i = 0; i < Math.ceil(uploadTmplt.length/10); i++) { + uploadGroups.push(uploadTmplt.slice(i*10,((i+1)*10))) + } + + let msgIds = [] + + for (let i = 0; i < uploadGroups.length; i++) { + + let ms = await this.uploadChannel.send({ + files:uploadGroups[i] + }).catch((e) => {console.error(e)}) + + if (ms) { + msgIds.push(ms.id) + } else { + if (!ogf) delete this.files[uploadId] + else this.files[uploadId] = ogf + reject({status:500,message:"please try again"}); return + } + } + + // this code deletes the files from discord, btw + // if need be, replace with job queue system + + if (ogf&&this.uploadChannel) { + for (let x of ogf.messageids) { + this.uploadChannel.messages.delete(x).catch(err => console.error(err)) + } + } + + resolve(await this.writeFile( + uploadId, + { + filename:settings.name, + messageids:msgIds, + mime:settings.mime, + sizeInBytes:fBuffer.byteLength, + + owner:settings.owner, + visibility: ogf ? ogf.visibility + : ( + settings.owner + ? Accounts.getFromId(settings.owner)?.defaultFileVisibility + : undefined + ), + // so that json.stringify doesnt include tag:undefined + ...((ogf||{}).tag ? {tag:ogf.tag} : {}), + + chunkSize: this.config.maxDiscordFileSize + } + )) + + + }) + } + + // fs + + writeFile(uploadId: string, file: FilePointer):Promise { + return new Promise((resolve, reject) => { + + this.files[uploadId] = file + + writeFile(process.cwd()+"/.data/files.json",JSON.stringify(this.files),(err) => { + + if (err) { + reject({status:500,message:"server may be misconfigured, contact admin for help"}); + delete this.files[uploadId]; + return + } + + resolve(uploadId) + + }) + + }) + } + + // todo: move read code here + + readFileStream(uploadId: string, range?: {start:number, end:number}):Promise { + return new Promise(async (resolve,reject) => { + if (!this.uploadChannel) { + reject({status:503,message:"server is not ready - please try again later"}) + return + } + + if (this.files[uploadId]) { + let file = this.files[uploadId] + + let + scan_msg_begin = 0, + scan_msg_end = file.messageids.length-1, + scan_files_begin = 0, + scan_files_end = -1 + + let useRanges = range && file.chunkSize && file.sizeInBytes; + + // todo: figure out how to get typesccript to accept useRanges + // i'm too tired to look it up or write whatever it wnats me to do + if (range && file.chunkSize && file.sizeInBytes) { + + // Calculate where to start file scans... + + scan_files_begin = Math.floor(range.start / file.chunkSize) + scan_files_end = Math.ceil(range.end / file.chunkSize) - 1 + + scan_msg_begin = Math.floor(scan_files_begin / 10) + scan_msg_end = Math.ceil(scan_files_end / 10) + + } + + let attachments: Discord.Attachment[] = []; + + /* File updates */ + let file_updates: Pick = {} + let atSIB: number[] = [] // kepes track of the size of each file... + + for (let xi = scan_msg_begin; xi < scan_msg_end+1; xi++) { + + let msg = await this.uploadChannel.messages.fetch(file.messageids[xi]).catch(() => {return null}) + if (msg?.attachments) { + + let attach = Array.from(msg.attachments.values()) + for (let i = (useRanges && xi == scan_msg_begin ? ( scan_files_begin - (xi*10) ) : 0); i < (useRanges && xi == scan_msg_end ? ( scan_files_end - (xi*10) + 1 ) : attach.length); i++) { + + attachments.push(attach[i]) + atSIB.push(attach[i].size) + + } + + } + + } + + if (!file.sizeInBytes) file_updates.sizeInBytes = atSIB.reduce((a,b) => a+b); + if (!file.chunkSize) file_updates.chunkSize = atSIB[0] + if (Object.keys(file_updates).length) { // if file_updates not empty + // i gotta do these weird workarounds, ts is weird sometimes + // originally i was gonna do key is keyof FilePointer but for some reason + // it ended up making typeof file[key] never??? so + // its 10pm and chinese people suck at being quiet so i just wanna get this over with + // chinese is the worst language in terms of volume lmao + let valid_fp_keys = ["sizeInBytes", "chunkSize"] + let isValidFilePointerKey = (key: string): key is "sizeInBytes" | "chunkSize" => valid_fp_keys.includes(key) + + for (let [key,value] of Object.entries(file_updates)) { + if (isValidFilePointerKey(key)) file[key] = value + } + + writeFile(process.cwd()+"/.data/files.json",JSON.stringify(this.files),(err) => {}) + } + + let position = 0; + + let getNextChunk = async () => { + let scanning_chunk = attachments[position] + if (!scanning_chunk) { + return null + } + + let d = await axios.get( + scanning_chunk.url, + { + responseType:"arraybuffer", + headers: { + ...(useRanges ? { + "Range": `bytes=${position == 0 && range && file.chunkSize ? range.start-(scan_files_begin*file.chunkSize) : "0"}-${position == attachments.length-1 && range && file.chunkSize ? range.end-(scan_files_end*file.chunkSize) : ""}` + } : {}) + } + } + ).catch((e:Error) => {console.error(e)}) + + position++; + + if (d) { + return d.data + } else { + reject({status:500,message:"internal server error"}) + return "__ERR" + } + } + + let ord:number[] = [] + // hopefully this regulates it? + let lastChunkSent = true + + let dataStream = new Readable({ + read(){ + if (!lastChunkSent) return + lastChunkSent = false + getNextChunk().then(async (nextChunk) => { + if (nextChunk == "__ERR") {this.destroy(new Error("file read error")); return} + let response = this.push(nextChunk) + + if (!nextChunk) return // EOF + + while (response) { + let nextChunk = await getNextChunk() + response = this.push(nextChunk) + if (!nextChunk) return + } + lastChunkSent = true + }) + } + }) + + resolve(dataStream) + + } else { + reject({status:404,message:"not found"}) + } + }) + } + + unlink(uploadId:string, noWrite: boolean = false):Promise { + return new Promise(async (resolve,reject) => { + let tmp = this.files[uploadId]; + if (!tmp) {resolve(); return} + if (tmp.owner) { + let id = files.deindex(tmp.owner,uploadId,noWrite); + if (id) await id + } + // this code deletes the files from discord, btw + // if need be, replace with job queue system + + if (!this.uploadChannel) {reject(); return} + for (let x of tmp.messageids) { + this.uploadChannel.messages.delete(x).catch(err => console.error(err)) + } + + delete this.files[uploadId]; + if (noWrite) {resolve(); return} + writeFile(process.cwd()+"/.data/files.json",JSON.stringify(this.files),(err) => { + if (err) { + this.files[uploadId] = tmp // !! this may not work, since tmp is a link to this.files[uploadId]? + reject() + } else { + resolve() + } + }) + + }) + } + + getFilePointer(uploadId:string):FilePointer { + return this.files[uploadId] + } + +} diff --git a/src/server/lib/mail.ts b/src/server/lib/mail.ts new file mode 100644 index 0000000..4fdbb3e --- /dev/null +++ b/src/server/lib/mail.ts @@ -0,0 +1,38 @@ +import { createTransport } from "nodemailer"; + +// required i guess +require("dotenv").config() + +let +mailConfig = + require( process.cwd() + "/config.json" ).mail, +transport = + createTransport( + { + ...mailConfig.transport, + auth: { + user: process.env.MAIL_USER, + pass: process.env.MAIL_PASS + } + } + ) + +// lazy but + +export function sendMail(to: string, subject: string, content: string) { + return new Promise((resolve,reject) => { + transport.sendMail({ + to, + subject, + "from": mailConfig.send.from, + "html": `monofile accounts
Gain control of your uploads.

${ + content + .replace(/\/g, `@`) + .replace(/\/g,``) + }

If you do not believe that you are the intended recipient of this email, please disregard this message.` + }, (err, info) => { + if (err) reject(err) + else resolve(info) + }) + }) +} \ No newline at end of file diff --git a/src/server/lib/middleware.ts b/src/server/lib/middleware.ts new file mode 100644 index 0000000..a56ba95 --- /dev/null +++ b/src/server/lib/middleware.ts @@ -0,0 +1,24 @@ +import * as Accounts from "./accounts"; +import express, { type RequestHandler } from "express" +import ServeError from "../lib/errors"; + +export let getAccount: RequestHandler = function(req, res, next) { + res.locals.acc = Accounts.getFromToken(req.cookies.auth) + next() +} + +export let requiresAccount: RequestHandler = function(_req, res, next) { + if (!res.locals.acc) { + ServeError(res, 401, "not logged in") + return + } + next() +} + +export let requiresAdmin: RequestHandler = function(_req, res, next) { + if (!res.locals.acc.admin) { + ServeError(res, 403, "you are not an administrator") + return + } + next() +} \ No newline at end of file diff --git a/src/server/lib/ratelimit.ts b/src/server/lib/ratelimit.ts new file mode 100644 index 0000000..a53533a --- /dev/null +++ b/src/server/lib/ratelimit.ts @@ -0,0 +1,45 @@ +import { RequestHandler } from "express" +import { type Account } from "./accounts" +import ServeError from "./errors" + +interface ratelimitSettings { + + requests: number + per: number + +} + +export function accountRatelimit( settings: ratelimitSettings ): RequestHandler { + let activeLimits: { + [ key: string ]: { + requests: number, + expirationHold: NodeJS.Timeout + } + } = {} + + return (req, res, next) => { + if (res.locals.acc) { + let accId = res.locals.acc.id + let aL = activeLimits[accId] + + if (!aL) { + activeLimits[accId] = { + requests: 0, + expirationHold: setTimeout(() => delete activeLimits[accId], settings.per) + } + aL = activeLimits[accId] + } + + if (aL.requests < settings.requests) { + res.locals.undoCount = () => { + if (activeLimits[accId]) { + activeLimits[accId].requests-- + } + } + next() + } else { + ServeError(res, 429, "too many requests") + } + } + } +} \ No newline at end of file diff --git a/src/server/routes/adminRoutes.ts b/src/server/routes/adminRoutes.ts new file mode 100644 index 0000000..7b24baa --- /dev/null +++ b/src/server/routes/adminRoutes.ts @@ -0,0 +1,195 @@ +import bodyParser from "body-parser"; +import { Router } from "express"; +import * as Accounts from "../lib/accounts"; +import * as auth from "../lib/auth"; +import bytes from "bytes" +import {writeFile} from "fs"; +import { sendMail } from "../lib/mail"; +import { getAccount, requiresAccount, requiresAdmin } from "../lib/middleware" + +import ServeError from "../lib/errors"; +import Files from "../lib/files"; + +let parser = bodyParser.json({ + type: ["text/plain","application/json"] +}) + +export let adminRoutes = Router(); +adminRoutes + .use(getAccount) + .use(requiresAccount) + .use(requiresAdmin) +let files:Files + +export function setFilesObj(newFiles:Files) { + files = newFiles +} + +let config = require(`${process.cwd()}/config.json`) + +adminRoutes.post("/reset", parser, (req,res) => { + + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.target !== "string" || typeof req.body.password !== "string") { + res.status(404) + res.send() + return + } + + let targetAccount = Accounts.getFromUsername(req.body.target) + if (!targetAccount) { + res.status(404) + res.send() + return + } + + Accounts.password.set ( targetAccount.id, req.body.password ) + auth.AuthTokens.filter(e => e.account == targetAccount?.id).forEach((v) => { + auth.invalidate(v.token) + }) + + if (targetAccount.email) { + sendMail(targetAccount.email, `Your login details have been updated`, `Hello there! This email is to notify you of a password change that an administrator, ${acc.username}, has initiated. You have been logged out of your devices. Thank you for using monofile.`).then(() => { + res.send("OK") + }).catch((err) => {}) + } + + + res.send() + +}) + +adminRoutes.post("/elevate", parser, (req,res) => { + + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.target !== "string") { + res.status(404) + res.send() + return + } + + let targetAccount = Accounts.getFromUsername(req.body.target) + if (!targetAccount) { + res.status(404) + res.send() + return + } + + targetAccount.admin = true; + Accounts.save() + res.send() + +}) + +adminRoutes.post("/delete", parser, (req,res) => { + + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.target !== "string") { + res.status(404) + res.send() + return + } + + let targetFile = files.getFilePointer(req.body.target) + + if (!targetFile) { + res.status(404) + res.send() + return + } + + files.unlink(req.body.target).then(() => { + res.status(200) + }).catch(() => { + res.status(500) + }).finally(() => res.send()) + +}) + +adminRoutes.post("/delete_account", parser, async (req,res) => { + + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.target !== "string") { + res.status(404) + res.send() + return + } + + let targetAccount = Accounts.getFromUsername(req.body.target) + if (!targetAccount) { + res.status(404) + res.send() + return + } + + let accId = targetAccount.id + + auth.AuthTokens.filter(e => e.account == accId).forEach((v) => { + auth.invalidate(v.token) + }) + + let cpl = () => Accounts.deleteAccount(accId).then(_ => { + if (targetAccount?.email) { + sendMail(targetAccount.email, "Notice of account deletion", `Your account, ${targetAccount.username}, has been deleted by ${acc.username} for the following reason:

${req.body.reason || "(no reason specified)"}

Your files ${req.body.deleteFiles ? "have been deleted" : "have not been modified"}. Thank you for using monofile.`) + } + res.send("account deleted") + }) + + if (req.body.deleteFiles) { + let f = targetAccount.files.map(e=>e) // make shallow copy so that iterating over it doesnt Die + for (let v of f) { + files.unlink(v,true).catch(err => console.error(err)) + } + + writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => { + if (err) console.log(err) + cpl() + }) + } else cpl() +}) + +adminRoutes.post("/transfer", parser, (req,res) => { + + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.target !== "string" || typeof req.body.owner !== "string") { + res.status(404) + res.send() + return + } + + let targetFile = files.getFilePointer(req.body.target) + if (!targetFile) { + res.status(404) + res.send() + return + } + + let newOwner = Accounts.getFromUsername(req.body.owner || "") + + // clear old owner + + if (targetFile.owner) { + let oldOwner = Accounts.getFromId(targetFile.owner) + if (oldOwner) { + Accounts.files.deindex(oldOwner.id, req.body.target) + } + } + + if (newOwner) { + Accounts.files.index(newOwner.id, req.body.target) + } + targetFile.owner = newOwner ? newOwner.id : undefined; + + files.writeFile(req.body.target, targetFile).then(() => { + res.send() + }).catch(() => { + res.status(500) + res.send() + }) // wasting a reassignment but whatee + +}) \ No newline at end of file diff --git a/src/server/routes/authRoutes.ts b/src/server/routes/authRoutes.ts new file mode 100644 index 0000000..39e84e4 --- /dev/null +++ b/src/server/routes/authRoutes.ts @@ -0,0 +1,461 @@ +import bodyParser from "body-parser"; +import { Router } from "express"; +import * as Accounts from "../lib/accounts"; +import * as auth from "../lib/auth"; +import { sendMail } from "../lib/mail"; +import { getAccount, requiresAccount } from "../lib/middleware" +import { accountRatelimit } from "../lib/ratelimit" + +import ServeError from "../lib/errors"; +import Files, { FileVisibility, generateFileId, id_check_regex } from "../lib/files"; + +import { writeFile } from "fs"; + +let parser = bodyParser.json({ + type: ["text/plain","application/json"] +}) + +export let authRoutes = Router(); +authRoutes.use(getAccount) + +let config = require(`${process.cwd()}/config.json`) + +let files:Files + +export function setFilesObj(newFiles:Files) { + files = newFiles +} + +authRoutes.post("/login", parser, (req,res) => { + if (typeof req.body.username != "string" || typeof req.body.password != "string") { + ServeError(res,400,"please provide a username or password") + return + } + + if (auth.validate(req.cookies.auth)) return + + /* + check if account exists + */ + + let acc = Accounts.getFromUsername(req.body.username) + + if (!acc) { + ServeError(res,401,"username or password incorrect") + return + } + + if (!Accounts.password.check(acc.id,req.body.password)) { + ServeError(res,401,"username or password incorrect") + return + } + + /* + assign token + */ + + res.cookie("auth",auth.create(acc.id,(3*24*60*60*1000))) + res.status(200) + res.end() +}) + +authRoutes.post("/create", parser, (req,res) => { + if (!config.accounts.registrationEnabled) { + ServeError(res,403,"account registration disabled") + return + } + + if (auth.validate(req.cookies.auth)) return + + if (typeof req.body.username != "string" || typeof req.body.password != "string") { + ServeError(res,400,"please provide a username or password") + return + } + + /* + check if account exists + */ + + let acc = Accounts.getFromUsername(req.body.username) + + if (acc) { + ServeError(res,400,"account with this username already exists") + return + } + + if (req.body.username.length < 3 || req.body.username.length > 20) { + ServeError(res,400,"username must be over or equal to 3 characters or under or equal to 20 characters in length") + return + } + + if ((req.body.username.match(/[A-Za-z0-9_\-\.]+/) || [])[0] != req.body.username) { + ServeError(res,400,"username contains invalid characters") + return + } + + if (req.body.password.length < 8) { + ServeError(res,400,"password must be 8 characters or longer") + return + } + + Accounts.create(req.body.username,req.body.password) + .then((newAcc) => { + /* + assign token + */ + + res.cookie("auth",auth.create(newAcc,(3*24*60*60*1000))) + res.status(200) + res.end() + }) + .catch(() => { + ServeError(res,500,"internal server error") + }) +}) + +authRoutes.post("/logout", (req,res) => { + if (!auth.validate(req.cookies.auth)) { + ServeError(res, 401, "not logged in") + return + } + + auth.invalidate(req.cookies.auth) + res.send("logged out") +}) + +authRoutes.post("/dfv", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + if (['public','private','anonymous'].includes(req.body.defaultFileVisibility)) { + acc.defaultFileVisibility = req.body.defaultFileVisibility + Accounts.save() + res.send(`dfv has been set to ${acc.defaultFileVisibility}`) + } else { + res.status(400) + res.send("invalid dfv") + } +}) + +authRoutes.post("/customcss", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.fileId != "string") req.body.fileId = undefined; + + if ( + + !req.body.fileId + || (req.body.fileId.match(id_check_regex) == req.body.fileId + && req.body.fileId.length <= config.maxUploadIdLength) + + ) { + acc.customCSS = req.body.fileId || undefined + if (!req.body.fileId) delete acc.customCSS + Accounts.save() + res.send(`custom css saved`) + } else { + res.status(400) + res.send("invalid fileid") + } +}) + +authRoutes.post("/embedcolor", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.color != "string") req.body.color = undefined; + + if ( + + !req.body.color + || (req.body.color.toLowerCase().match(/[a-f0-9]+/) == req.body.color) + && req.body.color.length == 6 + + ) { + if (!acc.embed) acc.embed = {} + acc.embed.color = req.body.color || undefined + if (!req.body.color) delete acc.embed.color + Accounts.save() + res.send(`custom embed color saved`) + } else { + res.status(400) + res.send("invalid hex code") + } +}) + +authRoutes.post("/embedsize", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.largeImage != "boolean") req.body.color = false; + + if (!acc.embed) acc.embed = {} + acc.embed.largeImage = req.body.largeImage + if (!req.body.largeImage) delete acc.embed.largeImage + Accounts.save() + res.send(`custom embed image size saved`) +}) + +authRoutes.post("/delete_account", requiresAccount, parser, async (req,res) => { + let acc = res.locals.acc as Accounts.Account + + let accId = acc.id + + auth.AuthTokens.filter(e => e.account == accId).forEach((v) => { + auth.invalidate(v.token) + }) + + let cpl = () => Accounts.deleteAccount(accId).then(_ => res.send("account deleted")) + + if (req.body.deleteFiles) { + let f = acc.files.map(e=>e) // make shallow copy so that iterating over it doesnt Die + for (let v of f) { + files.unlink(v,true).catch(err => console.error(err)) + } + + writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => { + if (err) console.log(err) + cpl() + }) + } else cpl() +}) + +authRoutes.post("/change_username", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.username != "string" || req.body.username.length < 3 || req.body.username.length > 20) { + ServeError(res,400,"username must be between 3 and 20 characters in length") + return + } + + let _acc = Accounts.getFromUsername(req.body.username) + + if (_acc) { + ServeError(res,400,"account with this username already exists") + return + } + + if ((req.body.username.match(/[A-Za-z0-9_\-\.]+/) || [])[0] != req.body.username) { + ServeError(res,400,"username contains invalid characters") + return + } + + acc.username = req.body.username + Accounts.save() + + if (acc.email) { + sendMail(acc.email, `Your login details have been updated`, `Hello there! Your username has been updated to ${req.body.username}. Please update your devices accordingly. Thank you for using monofile.`).then(() => { + res.send("OK") + }).catch((err) => {}) + } + + res.send("username changed") +}) + +// shit way to do this but... + +let verificationCodes = new Map() + +authRoutes.post("/request_email_change", requiresAccount, accountRatelimit({ requests: 4, per: 60*60*1000 }), parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + + if (typeof req.body.email != "string" || !req.body.email) { + ServeError(res,400, "supply an email") + return + } + + let vcode = verificationCodes.get(acc.id) + + // delete previous if any + let e = vcode?.expiry + if (e) clearTimeout(e) + verificationCodes.delete(acc?.id||"") + + let code = generateFileId(12).toUpperCase() + + // set + + verificationCodes.set(acc.id, { + code, + email: req.body.email, + expiry: setTimeout( () => verificationCodes.delete(acc?.id||""), 15*60*1000) + }) + + // this is a mess but it's fine + + sendMail(req.body.email, `Hey there, ${acc.username} - let's connect your email`, `Hello there! You are recieving this message because you decided to link your email, ${req.body.email.split("@")[0]}@${req.body.email.split("@")[1]}, to your account, ${acc.username}. If you would like to continue, please click here, or go to https://${req.header("Host")}/auth/confirm_email/${code}.`).then(() => { + res.send("OK") + }).catch((err) => { + let e = verificationCodes.get(acc?.id||"")?.expiry + if (e) clearTimeout(e) + verificationCodes.delete(acc?.id||"") + res.locals.undoCount(); + ServeError(res, 500, err?.toString()) + }) +}) + +authRoutes.get("/confirm_email/:code", requiresAccount, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + + let vcode = verificationCodes.get(acc.id) + + if (!vcode) { ServeError(res, 400, "nothing to confirm"); return } + + if (typeof req.params.code == "string" && req.params.code.toUpperCase() == vcode.code) { + acc.email = vcode.email + Accounts.save(); + + let e = verificationCodes.get(acc?.id||"")?.expiry + if (e) clearTimeout(e) + verificationCodes.delete(acc?.id||"") + + res.redirect("/") + } else { + ServeError(res, 400, "invalid code") + } +}) + +let pwReset = new Map() +let prcIdx = new Map() + +authRoutes.post("/request_emergency_login", parser, (req,res) => { + if (auth.validate(req.cookies.auth || "")) return + + if (typeof req.body.account != "string" || !req.body.account) { + ServeError(res,400, "supply a username") + return + } + + let acc = Accounts.getFromUsername(req.body.account) + if (!acc || !acc.email) { + ServeError(res, 400, "this account either does not exist or does not have an email attached; please contact the server's admin for a reset if you would still like to access it") + return + } + + let pResetCode = pwReset.get(acc.id) + + if (pResetCode && pResetCode.requestedAt+(15*60*1000) > Date.now()) { + ServeError(res, 429, `Please wait a few moments to request another emergency login.`) + return + } + + + // delete previous if any + let e = pResetCode?.expiry + if (e) clearTimeout(e) + pwReset.delete(acc?.id||"") + prcIdx.delete(pResetCode?.code||"") + + let code = generateFileId(12).toUpperCase() + + // set + + pwReset.set(acc.id, { + code, + expiry: setTimeout( () => { pwReset.delete(acc?.id||""); prcIdx.delete(pResetCode?.code||"") }, 15*60*1000), + requestedAt: Date.now() + }) + + prcIdx.set(code, acc.id) + + // this is a mess but it's fine + + sendMail(acc.email, `Emergency login requested for ${acc.username}`, `Hello there! You are recieving this message because you forgot your password to your monofile account, ${acc.username}. To log in, please click here, or go to https://${req.header("Host")}/auth/emergency_login/${code}. If it doesn't appear that you are logged in after visiting this link, please try refreshing. Once you have successfully logged in, you may reset your password.`).then(() => { + res.send("OK") + }).catch((err) => { + let e = pwReset.get(acc?.id||"")?.expiry + if (e) clearTimeout(e) + pwReset.delete(acc?.id||"") + prcIdx.delete(code||"") + ServeError(res, 500, err?.toString()) + }) +}) + +authRoutes.get("/emergency_login/:code", (req,res) => { + if (auth.validate(req.cookies.auth || "")) { + ServeError(res, 403, "already logged in") + return + } + + let vcode = prcIdx.get(req.params.code) + + if (!vcode) { ServeError(res, 400, "invalid emergency login code"); return } + + if (typeof req.params.code == "string" && vcode) { + res.cookie("auth",auth.create(vcode,(3*24*60*60*1000))) + res.redirect("/") + + let e = pwReset.get(vcode)?.expiry + if (e) clearTimeout(e) + pwReset.delete(vcode) + prcIdx.delete(req.params.code) + } else { + ServeError(res, 400, "invalid code") + } +}) + +authRoutes.post("/change_password", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + if (typeof req.body.password != "string" || req.body.password.length < 8) { + ServeError(res,400,"password must be 8 characters or longer") + return + } + + let accId = acc.id + + Accounts.password.set(accId,req.body.password) + + auth.AuthTokens.filter(e => e.account == accId).forEach((v) => { + auth.invalidate(v.token) + }) + + if (acc.email) { + sendMail(acc.email, `Your login details have been updated`, `Hello there! This email is to notify you of a password change that you have initiated. You have been logged out of your devices. Thank you for using monofile.`).then(() => { + res.send("OK") + }).catch((err) => {}) + } + + res.send("password changed - logged out all sessions") +}) + +authRoutes.post("/logout_sessions", requiresAccount, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + let accId = acc.id + + auth.AuthTokens.filter(e => e.account == accId).forEach((v) => { + auth.invalidate(v.token) + }) + + res.send("logged out all sessions") +}) + +authRoutes.get("/me", requiresAccount, (req,res) => { + let acc = res.locals.acc as Accounts.Account + + let accId = acc.id + res.send({ + ...acc, + sessionCount: auth.AuthTokens.filter(e => e.account == accId && e.expire > Date.now()).length, + sessionExpires: auth.AuthTokens.find(e => e.token == req.cookies.auth)?.expire, + password: undefined + }) +}) + +authRoutes.get("/customCSS", (req,res) => { + if (!auth.validate(req.cookies.auth)) { + ServeError(res, 401, "not logged in") + return + } + + // lazy rn so + + let acc = Accounts.getFromToken(req.cookies.auth) + if (acc) { + if (acc.customCSS) { + res.redirect(`/file/${acc.customCSS}`) + } else { + res.send("") + } + } else res.send("") +}) \ No newline at end of file diff --git a/src/server/routes/fileApiRoutes.ts b/src/server/routes/fileApiRoutes.ts new file mode 100644 index 0000000..be461c9 --- /dev/null +++ b/src/server/routes/fileApiRoutes.ts @@ -0,0 +1,104 @@ +import bodyParser from "body-parser"; +import { Router } from "express"; +import * as Accounts from "../lib/accounts"; +import * as auth from "../lib/auth"; +import bytes from "bytes" +import {writeFile} from "fs"; + +import ServeError from "../lib/errors"; +import Files from "../lib/files"; + +let parser = bodyParser.json({ + type: ["text/plain","application/json"] +}) + +export let fileApiRoutes = Router(); +let files:Files + +export function setFilesObj(newFiles:Files) { + files = newFiles +} + +let config = require(`${process.cwd()}/config.json`) + +fileApiRoutes.get("/list", (req,res) => { + + if (!auth.validate(req.cookies.auth)) { + ServeError(res, 401, "not logged in") + return + } + + let acc = Accounts.getFromToken(req.cookies.auth) + + if (!acc) return + let accId = acc.id + + res.send(acc.files.map((e) => { + let fp = files.getFilePointer(e) + if (!fp) { Accounts.files.deindex(accId, e); return null } + return { + ...fp, + messageids: null, + owner: null, + id:e + } + }).filter(e=>e)) + +}) + +fileApiRoutes.post("/manage", parser, (req,res) => { + + if (!auth.validate(req.cookies.auth)) { + ServeError(res, 401, "not logged in") + return + } + + let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account + + if (!acc) return + if (!req.body.target || !(typeof req.body.target == "object") || req.body.target.length < 1) return + + let modified = 0 + + req.body.target.forEach((e:string) => { + if (!acc.files.includes(e)) return + + let fp = files.getFilePointer(e) + + if (fp.reserved) { + return + } + + switch( req.body.action ) { + case "delete": + files.unlink(e, true) + modified++; + break; + + case "changeFileVisibility": + if (!["public","anonymous","private"].includes(req.body.value)) return; + files.files[e].visibility = req.body.value; + modified++; + break; + + case "setTag": + if (!req.body.value) delete files.files[e].tag + else { + if (req.body.value.toString().length > 30) return + files.files[e].tag = req.body.value.toString().toLowerCase() + } + modified++; + break; + } + }) + + Accounts.save().then(() => { + writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => { + if (err) console.log(err) + res.contentType("text/plain") + res.send(`modified ${modified} files`) + }) + }).catch((err) => console.error(err)) + + +}) \ No newline at end of file diff --git a/src/server/routes/primaryApi.ts b/src/server/routes/primaryApi.ts new file mode 100644 index 0000000..5ce01bb --- /dev/null +++ b/src/server/routes/primaryApi.ts @@ -0,0 +1,171 @@ +import bodyParser from "body-parser"; +import express, { Router } from "express"; +import * as Accounts from "../lib/accounts"; +import * as auth from "../lib/auth"; +import axios, { AxiosResponse } from "axios" +import { type Range } from "range-parser"; +import multer, {memoryStorage} from "multer" + +import ServeError from "../lib/errors"; +import Files from "../lib/files"; + +let parser = bodyParser.json({ + type: ["text/plain","application/json"] +}) + +export let primaryApi = Router(); +let files:Files + +export function setFilesObj(newFiles:Files) { + files = newFiles +} + +const multerSetup = multer({storage:memoryStorage()}) + +let config = require(`${process.cwd()}/config.json`) + + +primaryApi.get(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"], async (req:express.Request,res:express.Response) => { + + let file = files.getFilePointer(req.params.fileId) + res.setHeader("Access-Control-Allow-Origin", "*") + res.setHeader("Content-Security-Policy","sandbox allow-scripts") + if (req.query.attachment == "1") res.setHeader("Content-Disposition", "attachment") + + if (file) { + + if (file.visibility == "private" && Accounts.getFromToken(req.cookies.auth)?.id != file.owner) { + ServeError(res,403,"you do not own this file") + return + } + + let range: Range | undefined + + res.setHeader("Content-Type",file.mime) + if (file.sizeInBytes) { + res.setHeader("Content-Length",file.sizeInBytes) + + if (file.chunkSize) { + let rng = req.range(file.sizeInBytes) + if (rng) { + + // error handling + if (typeof rng == "number") { + res.status(rng == -1 ? 416 : 400).send() + return + } + if (rng.type != "bytes") { + res.status(400).send(); + return + } + + // set ranges var + let rngs = Array.from(rng) + if (rngs.length != 1) { res.status(400).send(); return } + range = rngs[0] + + } + } + } + + // supports ranges + + + files.readFileStream(req.params.fileId, range).then(async stream => { + + if (range) { + res.status(206) + res.header("Content-Length", (range.end-range.start + 1).toString()) + res.header("Content-Range", `bytes ${range.start}-${range.end}/${file.sizeInBytes}`) + } + stream.pipe(res) + + }).catch((err) => { + ServeError(res,err.status,err.message) + }) + + } else { + ServeError(res, 404, "file not found") + } + +}) + +primaryApi.head(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"], (req: express.Request, res:express.Response) => { + let file = files.getFilePointer(req.params.fileId) + res.setHeader("Access-Control-Allow-Origin", "*") + res.setHeader("Content-Security-Policy","sandbox allow-scripts") + if (req.query.attachment == "1") res.setHeader("Content-Disposition", "attachment") + if (!file) { + res.status(404) + res.send() + } else { + res.setHeader("Content-Type",file.mime) + if (file.sizeInBytes) { + res.setHeader("Content-Length",file.sizeInBytes) + } + if (file.chunkSize) { + res.setHeader("Accept-Ranges", "bytes") + } + } +}) + +// upload handlers + +primaryApi.post("/upload",multerSetup.single('file'),async (req,res) => { + if (req.file) { + try { + let prm = req.header("monofile-params") + let params:{[key:string]:any} = {} + if (prm) { + params = JSON.parse(prm) + } + + files.uploadFile({ + owner: auth.validate(req.cookies.auth), + + uploadId:params.uploadId, + name:req.file.originalname, + mime:req.file.mimetype + },req.file.buffer) + .then((uID) => res.send(uID)) + .catch((stat) => { + res.status(stat.status); + res.send(`[err] ${stat.message}`) + }) + } catch { + res.status(400) + res.send("[err] bad request") + } + } else { + res.status(400) + res.send("[err] bad request") + } +}) + +primaryApi.post("/clone", bodyParser.json({type: ["text/plain","application/json"]}) ,(req,res) => { + try { + axios.get(req.body.url,{responseType:"arraybuffer"}).then((data:AxiosResponse) => { + + files.uploadFile({ + owner: auth.validate(req.cookies.auth), + + name:req.body.url.split("/")[req.body.url.split("/").length-1] || "generic", + mime:data.headers["content-type"], + uploadId:req.body.uploadId + },Buffer.from(data.data)) + .then((uID) => res.send(uID)) + .catch((stat) => { + res.status(stat.status); + res.send(`[err] ${stat.message}`) + }) + + }).catch((err) => { + console.log(err) + res.status(400) + res.send(`[err] failed to fetch data`) + }) + } catch { + res.status(500) + res.send("[err] an error occured") + } +}) \ No newline at end of file diff --git a/src/style/_base.scss b/src/style/_base.scss new file mode 100644 index 0000000..b354665 --- /dev/null +++ b/src/style/_base.scss @@ -0,0 +1,85 @@ +/* + could probably replace this with fonts served directly + from the server but it's fine for now +*/ + +@import url("/static/assets/fonts/inconsolata.css"); +@import url("/static/assets/fonts/source_sans.css"); +@import url("/static/assets/fonts/fira_code.css"); + +$FallbackFonts: + -apple-system, + system-ui, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + sans-serif; + +%normal { + font-family: "Source Sans Pro", $FallbackFonts +} + +/* + everything that's not a span + and/or has the normal class + (it's just in case) +*/ + +*:not(span), .normal { @extend %normal; } + +/* + for code blocks / terminal +*/ + +.monospace { + font-family: "Fira Code", monospace +} + +/* + colors +*/ + +$Background: #252525; +/* hsl(210,12.9,24.3) */ +$darkish: rgb(54, 62, 70); + +/* + then other stuff +*/ + +body { + background-color: rgb(30, 33, 36); // this is here so that + // pulling down to refresh + // on mobile looks good +} + +#appContent { + background-color: $Background +} + +/* + scrollbars +*/ + +* { + /* nice scrollbars aren't needed on mobile so */ + @media screen and (min-width:500px) { + + &::-webkit-scrollbar { + width:5px; + } + + &::-webkit-scrollbar-track { + background-color:#191919; + } + + &::-webkit-scrollbar-thumb { + background-color:#333; + + &:hover { + background-color:#373737; + } + } + + } +} \ No newline at end of file diff --git a/src/style/app.scss b/src/style/app.scss new file mode 100644 index 0000000..886c792 --- /dev/null +++ b/src/style/app.scss @@ -0,0 +1,41 @@ +@use "base"; +@use "app/topbar"; +@use "app/pulldown"; +@use "app/uploads"; + +.menuBtn { + text-decoration:none; + font-size:16px; + transition-duration: 100ms; + + color:#555555; + background-color: #00000000; + border:none; + margin:0 0 0 0; + cursor:pointer; + + position:relative; + top:-1px; + + &:hover { + color:slategray; + transition-duration: 100ms; + } +} + +#appContent { + position:absolute; + left:0px; + top:40px; + width:100%; + height: calc( 100% - 40px ); + background-image: linear-gradient(#333,base.$Background); + + @media screen and (max-width:500px) { + background-image: linear-gradient(#303030,base.$Background); + } +} + +.number { + font-family: "Inconsolata", monospace; +} \ No newline at end of file diff --git a/src/style/app/pulldown.scss b/src/style/app/pulldown.scss new file mode 100644 index 0000000..9d37ecc --- /dev/null +++ b/src/style/app/pulldown.scss @@ -0,0 +1,49 @@ +@use "../base"; +@use "pulldown/help"; +@use "pulldown/accounts"; +@use "pulldown/files"; +@use "pulldown/modals"; + +#overlay, .modalContainer { + position:absolute; + left:0px; + height: 100%; + width:100%; + top:0px; + border:none; + outline:none; + background-color:rgba(170, 170, 170, 0.25); + + z-index: 1000; +} + +.pulldown { + position: absolute; + width: 300px; + height: 400px; + background-color: #191919; + color: #dddddd; + + top:0px; + left:50%; + transform:translateX(-50%); + + @media screen and (max-width: 500px) { + width: 100%; + height: 100%; + } + + p, h1, h2 { + margin:0px; + } + + z-index: 1001; +} + +.pulldown_display { + position:absolute; + left:0px; + top:0px; + width:100%; + height:100%; +} \ No newline at end of file diff --git a/src/style/app/pulldown/accounts.scss b/src/style/app/pulldown/accounts.scss new file mode 100644 index 0000000..b6fe02b --- /dev/null +++ b/src/style/app/pulldown/accounts.scss @@ -0,0 +1,187 @@ +.pulldown_display[name=accounts] { + .notLoggedIn { + .container_div { + position:absolute; + top:50%; + transform:translateY(-50%); + width:100%; + text-align:center; + + h1 { + font-weight:600; + font-size:24px; + + @media screen and (max-width:500px) { + font-size:30px; + } + } + + .flavor { + font-size:14px; + + /* good enoough */ + + @media screen and (max-width:500px) { + font-size:16px; + } + + color:#999999; + margin: 0 0 10px 0; + } + + button { + cursor:pointer; + background-color:#393939; + color:#DDDDDD; + border:none; + outline:none; + padding:5px; + transition-duration: 250ms; + /*overflow:clip;*/ + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + + &:hover { + transition-duration: 250ms; + background-color:#434343; + color: #ffffff; + } + + flex-basis:50%; + flex-grow:1; + } + + button.flavor { + + padding: 0; + background: none; + + } + + input[type=text],input[type=password] { + border:none; + border-radius:0; + width:100%; + padding:5px; + background-color:#333333; + color:#dddddd; + outline:none; + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + } + + .pwError { + div { + border:none; + border-radius:0; + width:100%; + padding:5px; + background-color:#663333; + color:#dddddd; + outline:none; + font-size:14px; + text-align:left; + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + } + } + + .lgBtnContainer { + display:flex; + position:relative; + left:20px; + width:calc( 100% - 40px ); + gap:10px; + overflow:clip; + } + + .fields { + display:flex; + flex-direction:column; + position:relative; + left:20px; + width:calc( 100% - 40px ); + gap:5px; + overflow:clip; + } + + /* + a { + text-decoration: none; + color:#999999; + font-size:14px; + + @media screen and (max-width:500px) { + font-size:16px; + } + + &::after { + content:" ➜"; + font-size:0px; + opacity: 0; + transition-duration:250ms; + } + + &:hover { + &::after { + font-size:13px; + opacity: 1; + transition-duration:250ms; + } + } + } + */ + } + + } + + .loggedIn { + position:absolute; + + /* + left:10px; + top:10px; + */ + + left:0px; + top:0px; + width:calc( 100% - 20px ); + height:calc( 100% - 20px ); + padding:10px; + + overflow-y:auto; + + h1 { + font-weight:600; + font-size:20px; + color: #AAAAAA; + + @media screen and (max-width:500px) { + font-size:24px; + } + + .monospace { + font-size:18px; + @media screen and (max-width:500px) { + font-size:22px; + } + } + } + + .category { + + p { + text-align:left; + } + } + } +} \ No newline at end of file diff --git a/src/style/app/pulldown/files.scss b/src/style/app/pulldown/files.scss new file mode 100644 index 0000000..24787d1 --- /dev/null +++ b/src/style/app/pulldown/files.scss @@ -0,0 +1,160 @@ +.pulldown_display[name=files] { + .notLoggedIn { + position:absolute; + top:50%; + left:0px; + transform:translateY(-50%); + width:100%; + text-align:center; + + .flavor { + font-size:16px; + color:#999999; + margin: 0 0 10px 0; + } + + button { + --col: #999999; + + background-color: #232323; + color:var(--col); + font-size:14px; + border:1px solid var(--col); + padding:2px 20px 2px 20px; + cursor:pointer; + transition-duration:250ms; + + &:hover { + background-color:#333333; + transition-duration:250ms; + --col:#BBBBBB; + } + } + } + + .loggedIn { + display: flex; + flex-direction: column; + max-height:100%; + overflow:hidden; + + .searchBar { + transition-duration:150ms; + background-color:#171717; + width:100%; + padding:8px; + color:#dddddd; + border:none; + border-bottom: 1px solid #aaaaaa; + outline: none; + border-radius:0px; + font-size:14px; + + &:focus { + transition-duration:150ms; + border-bottom: 1px solid #dddddd; + } + + @media screen and (max-width: 500px) { + padding:12px; + font-size:16px; + } + } + + .fileList { + overflow-y:auto; + overflow-x:hidden; + padding:5px 0; + + .flFile { + padding: 3px 8px; + position:relative; + + @media screen and (max-width: 500px) { + padding:7px 12px; + } + + .detail { + color:#777777; + font-size:14px; + position:relative; + + @media screen and (max-width: 500px) { + font-size:16px; + } + + img { + width: 14px; + height: 14px; + + /* this is shit but it's the best way i can think of to do this */ + /* other than flexbox but i don't feel like doing that rn */ + + position:relative; + top:2px; + } + } + + h2 { + font-size:18px; + text-overflow:ellipsis; + overflow:hidden; + font-weight:600; + + @media screen and (max-width: 500px) { + font-size:20px; + } + } + + p, h2 { + margin:0 0 0 0; + white-space: nowrap; + } + + button { + background-color:#00000000; + border:none; + outline:none; + cursor:pointer; + + &.hitbox { + position:absolute; + left:0px; + top:0px; + height:100%; + width:100%; + z-index:10; + } + + &.more { + min-height:100%; + width:auto; + aspect-ratio: 1 / 1; + z-index:11; + position:relative; + + img { + margin:auto; + } + } + } + + .flexCont { + display: flex; + + .fileInfo { + width:100%; + min-width:0; + } + } + + @media screen and (min-width:500px) { + &:hover { + background-color: #252525; + } + } + + } + } + } +} \ No newline at end of file diff --git a/src/style/app/pulldown/help.scss b/src/style/app/pulldown/help.scss new file mode 100644 index 0000000..d9effa2 --- /dev/null +++ b/src/style/app/pulldown/help.scss @@ -0,0 +1,22 @@ +.pulldown_display[name=help] { + + overflow-y:auto; + + .faqGroup { + padding:6px 10px 4px 10px; + + h2 { + font-weight: 400; + color:#DDDDDD; + font-size:16px; + margin:0 0 0 0; + } + + p { + color:#999999; + font-size:16px; + margin:0 0 0 0; + } + } + +} \ No newline at end of file diff --git a/src/style/app/pulldown/modals.scss b/src/style/app/pulldown/modals.scss new file mode 100644 index 0000000..492384b --- /dev/null +++ b/src/style/app/pulldown/modals.scss @@ -0,0 +1,115 @@ +.optPicker { + + button, .inp { + position:relative; + width:100%; + height:50px; + background-color: #191919; + border:none; + border-bottom:1px solid #AAAAAA; + transition-duration:150ms; + + img { + position:absolute; + left:13px; + top:50%; + transform:translateY(-50%); + } + + p,input { + text-align:left; + position:absolute; + top:50%; + left:50px; + color:#DDDDDD; + transform:translateY(-50%); + font-size:14px; + background-color:#00000000; + border:none; + + span { + color:#777777; + font-size:12px; + } + } + + input { + height:100%; + width:calc(100% - 50px); + outline:none; /* bad idea but i don't even care anymore */ + margin:0px; + padding:0px; + } + + @media screen and (max-width:500px) { + height:70px; + p,input { + font-size:16px; + left:70px; + + span { + font-size:14px; + } + } + + input { + width:calc( 100% - 70px ); + } + + img { + width:30px; + height:30px; + left:20px; + } + } + + } + + button { + cursor:pointer; + + &:hover { + transition-duration:150ms; + background-color: #252525; + } + } + + .category { + border-bottom: 1px solid #AAAAAA; + + p { + color: #AAAAAA; + font-size: 14px; + margin: 10px 0px 3px 0px; + text-align:center; + + @media screen and (max-width:500px) { + font-size:16px; + } + } + } + +} + +.mdHitbox { + position:absolute; + width:100%; + height:100%; + top:0%; + left:0%; + cursor:pointer; + z-index: 0; + border:none; + background-color: #00000000; + outline:none; +} + +.modal { + position:absolute; + background-color:#191919; + width:100%; + transform:translateY(-100%); + top:100%; + left:0%; + z-index: 1; +} diff --git a/src/style/app/topbar.scss b/src/style/app/topbar.scss new file mode 100644 index 0000000..8016dc7 --- /dev/null +++ b/src/style/app/topbar.scss @@ -0,0 +1,21 @@ +@use "../base"; + +#topbar { + position:absolute; + left:0px; + top:0px; + + width:100%; + height:40px; + + /* hsl(210,9.1,12.9) */ + background-color: rgb(30, 33, 36); + + display:flex; + flex-direction: row; + justify-content: center; + align-items: center; + + column-gap:5px; + +} \ No newline at end of file diff --git a/src/style/app/uploader/add_new_files.scss b/src/style/app/uploader/add_new_files.scss new file mode 100644 index 0000000..598bcbe --- /dev/null +++ b/src/style/app/uploader/add_new_files.scss @@ -0,0 +1,115 @@ +#uploadWindow { + #add_new_files { + background-color:#191919; + border: 1px solid gray; + padding: 0px 0px 10px 0px; + + p { + font-family: "Fira Code", monospace; + text-align: left; + margin: 0px 0px 0px 10px; + font-size: 30px; + + span { + position:relative; + + &._add_files_txt { + font-size:16px; + top:-4px; + left:10px; + + @media screen and (max-width:500px) { + font-size:20px; + top:-6px; + left:10px; + } + } + } + + @media screen and (max-width:500px) { + font-size: 40px; + + span._add_files_txt { + font-size:20px; + top:-6px; + left:10px; + } + } + } + + #file_add_btns { + width:calc( 100% - 20px ); + margin:auto; + position:relative; + display:flex; + flex-direction:row; + column-gap:10px; + + button, input[type=text] { + background-color:#333333; + color:#DDDDDD; + border:none; + border-radius: 0px; + outline:none; + padding:5px; + + flex-basis:50%; + flex-grow:1; + transition-duration:250ms; + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + } + + button { + cursor:pointer; + + &:hover { + @media screen and (min-width: 500px) { + transition-duration:250ms; + flex-basis: 60%; + } + background-color:#393939; + color: #ffffff; + } + } + + .fileUpload { + width:100%; + height:100px; + position:relative; + + background-color:#262626; + transition-duration:250ms; + + input[type=file] { + opacity: 0; + position:absolute; + left:0px; + top:0px; + width:100%; + height:100%; + cursor:pointer; + } + + p { + position:absolute; + top:50%; + transform:translateY(-50%); + font-size:12px; + width:100%; + text-align:center; + padding:0px; + margin: 0px; + } + + &:hover { + transition-duration:250ms; + background-color:#292929; + } + } + } + } +} \ No newline at end of file diff --git a/src/style/app/uploader/file.scss b/src/style/app/uploader/file.scss new file mode 100644 index 0000000..54e3f32 --- /dev/null +++ b/src/style/app/uploader/file.scss @@ -0,0 +1,59 @@ +// should probably start using mixins for thingss like this + +#uploadWindow { + .file { + background-color:#191919; + border: 1px solid gray; + padding: 10px; + overflow:clip; + position:relative; + + h2 { + font-size: 16px; + margin: 0px; + font-weight:600; + width:calc( 100% - 20px ); + } + + input[type=text] { + background-color:#333333; + color:#DDDDDD; + border:none; + outline:none; + padding:5px; + position:relative; + + width:100%; + transition-duration:250ms; + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + } + + .buttonContainer { + display:flex; + column-gap:10px; + + button { + flex-basis: 50%; + flex-grow: 1; + padding:5px; + } + } + + .uploadingContainer { + color: #AAAAAA; + } + + .hitbox { + opacity:0; + position:absolute; + left:0px; + top:0px; + height:100%; + width:100%; + } + } +} \ No newline at end of file diff --git a/src/style/app/uploads.scss b/src/style/app/uploads.scss new file mode 100644 index 0000000..73268e9 --- /dev/null +++ b/src/style/app/uploads.scss @@ -0,0 +1,72 @@ +@use "uploader/add_new_files"; +@use "uploader/file"; + +#uploadWindow { + position:absolute; + left:50%; + top:50%; + transform:translate(-50%,-50%); + padding:10px 15px 10px 15px; + display:flex; + flex-direction: column; + + width:350px; + @media screen and (min-width:500px) { + max-height: calc( 100% - 80px ); + } + + background-color:#222222; + color:#ddd; + + h1, p, a { + margin: 0px; + font-size: 14px; + } + + a { + color:#999; + } + + h1 { + font-weight:600; + font-size: 25px; + } + + .uploadContainer { + overflow:auto; + } + + button { + cursor:pointer; + background-color:#393939; + color:#DDDDDD; + border:none; + outline:none; + padding:5px; + transition-duration: 250ms; + /*overflow:clip;*/ + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + + &:hover { + transition-duration: 250ms; + background-color:#434343; + color: #ffffff; + } + } + + @media screen and (max-width: 500px) { + width: calc( 100% - 20px ); + height: calc( 100% - 20px ); + border-radius:0px; + background-color:#00000000; + + transform:none; + left:10px; + top:10px; + padding:0px; + } +} \ No newline at end of file diff --git a/src/style/downloads.scss b/src/style/downloads.scss new file mode 100644 index 0000000..81ff36e --- /dev/null +++ b/src/style/downloads.scss @@ -0,0 +1,26 @@ +// probably dont need to import the entire +// uploads css file +// so i might just make a separate file with mixins +// and import them + +@use "app/uploads"; +@use "base"; + +#appContent { + position:absolute; + left:0px; + top:0px; + width:100%; + height:100%; + background-image: linear-gradient(#333,base.$Background); + + @media screen and (max-width:500px) { + background-image: linear-gradient(#303030,base.$Background); + } +} + +#uploadWindow { + img, video, audio { + width:100%; + } +} \ No newline at end of file diff --git a/src/style/error.scss b/src/style/error.scss new file mode 100644 index 0000000..d40188a --- /dev/null +++ b/src/style/error.scss @@ -0,0 +1,20 @@ +@use "_base"; + +.error { + font-size:20px; + color: lightslategray; + + position: fixed; + left: 50%; + top: 50%; + transform: translate(-50%,-50%); + + text-align:center; + + .code { + font-size:25px; + font-family: "Inconsolata", monospace; + color: white; + } +} + diff --git a/src/style/themes/classy.scss b/src/style/themes/classy.scss new file mode 100644 index 0000000..7bdd382 --- /dev/null +++ b/src/style/themes/classy.scss @@ -0,0 +1,168 @@ +#uploadWindow { + color: #FFFFFF +} + +body { + background-color:#DDDDDD; +} + +#appContent { + background: darkgray; + @media screen and (max-width:500px) { + background:white; + } +} + +#uploadWindow { + background: white; + + color:black; + + h1, p, a { + margin: 0px; + font-size: 14px; + } + + a { + color:rgb(153, 153, 153); + } + + h1 { + font-weight:600; + font-size: 25px; + text-align:center; + + @media screen and (max-width:500px) { + font-size: 30px; + } + } + + & > p:nth-of-type(1) { + text-align:center; + font-style: italic; + font-weight:600; + font-size: 16px; + color:black !important; + @media screen and (max-width:500px) { + font-size: 21px; + } + } + + button { + cursor:pointer; + color:black; + border:none; + outline:none; + padding:5px; + background: #AAAAAA; + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + + &:hover { + outline: 1px solid #333333; + color: black; + background-color:#AAAAAA; + } + } + + & > button:nth-last-of-type(1) { + background-color:#66AAFF; + &:hover { + background-color:#66AAFF; + } + } + + #add_new_files { + background-color: #AAAAAA66; + border:1px solid #AAAAAA; + + #file_add_btns { + button, input[type=text] { + transition-duration:0s; + + @media screen and (max-width: 500px) { + font-size:16px; + padding:10px; + } + } + + input[type=text] { + font-family: "Fira Code", monospace; + background-color:#AAAAAA; + color:black; + } + + button { + cursor:pointer; + background-color:#AAAAAA; + color: black; + + &:hover { + flex-basis: 50%; + transition-duration:0s; + background-color:#AAAAAA; + color: black; + outline: 1px solid #333333; + } + } + + .fileUpload { + background-color:#AAAAAA; + transition-duration:250ms; + + &:hover { + transition-duration:0s; + background-color:#AAAAAA; + } + } + } + } + + .file { + background-color: #AAAAAA66; + border: 1px solid #AAAAAA; + + input[type=text] { + font-family: "Fira Code", monospace; + background-color:#AAAAAA; + color:black; + } + } + +} + +* { + /* nice scrollbars aren't needed on mobile so */ + @media screen and (min-width:500px) { + + &::-webkit-scrollbar { + width:5px; + } + + &::-webkit-scrollbar-track { + background-color:#AAAAAA; + } + + &::-webkit-scrollbar-thumb { + background-color:#DDDDDD; + + &:hover { + background-color:#FFFFFF; + } + } + + } +} + +#topbar { + background-color: #DDDDDD; +} + +.error { + .code { + color: black; + } +} \ No newline at end of file diff --git a/src/svelte/App.svelte b/src/svelte/App.svelte new file mode 100644 index 0000000..0f63334 --- /dev/null +++ b/src/svelte/App.svelte @@ -0,0 +1,28 @@ + + + +
+ + + +
\ No newline at end of file diff --git a/src/svelte/elem/PulldownManager.svelte b/src/svelte/elem/PulldownManager.svelte new file mode 100644 index 0000000..b3c23f9 --- /dev/null +++ b/src/svelte/elem/PulldownManager.svelte @@ -0,0 +1,49 @@ + + + +{#if $pulldownOpen} +
+ +
+ + + {/if} + + + + + + + +
+
\ No newline at end of file diff --git a/src/svelte/elem/UploadWindow.svelte b/src/svelte/elem/UploadWindow.svelte new file mode 100644 index 0000000..0b2b136 --- /dev/null +++ b/src/svelte/elem/UploadWindow.svelte @@ -0,0 +1,231 @@ + + +
+

monofile

+

+ {$serverStats.version ? `v${$serverStats.version}` : "•••"}  —  Discord based file sharing +

+ +
+ + + +
+ {#each Object.entries(uploads) as upload (upload[0])} + +
+
+

{upload[1].name} {upload[1].type}{@html upload[1].type == "upload" ? ` (${Math.round(upload[1].file.size/1048576)}MiB)` : ""}

+ + {#if upload[1].maximized && !uploadInProgress} +
+
+ +
+
+ + +
+
+ {:else if !uploadInProgress} + + {:else} +
+ {#if !upload[1].uploadStatus.fileId} +

{upload[1].uploadStatus.error ?? "Uploading..."}

+ {/if} + + {#if upload[1].uploadStatus.fileId} +
+ {#if !upload[1].viewingUrl} +
+ + +
+ {:else} +
+ + +
+ {/if} + {/if} +
+ {/if} +
+
+
+ {/each} +
+ + {#if uploadInProgress == false} + + + {#if ($serverStats.accounts||{}).requiredForUpload ? !!$account.username : true} + + +
+ {#if Object.keys(uploads).length > 0} + +
+ {/if} + + {:else} + +

Please log in to upload files.

+
+ + {/if} + + {/if} + +

+ Hosting {$serverStats.files || "•••"} files + — + Maximum filesize is {(($serverStats.maxDiscordFileSize || 0)*($serverStats.maxDiscordFiles || 0))/1048576 || "•••"}MiB +
+

+ +

+ Made with {Math.floor(Math.random()*10)==0 ? "🐟" : "❤"} by @nbitzzsource +

+
+
\ No newline at end of file diff --git a/src/svelte/elem/prompts/OptionPicker.svelte b/src/svelte/elem/prompts/OptionPicker.svelte new file mode 100644 index 0000000..68cef38 --- /dev/null +++ b/src/svelte/elem/prompts/OptionPicker.svelte @@ -0,0 +1,78 @@ + + +{#if activeModal} +
+ + +
+{/if} \ No newline at end of file diff --git a/src/svelte/elem/prompts/account.js b/src/svelte/elem/prompts/account.js new file mode 100644 index 0000000..940f830 --- /dev/null +++ b/src/svelte/elem/prompts/account.js @@ -0,0 +1,270 @@ +import { fetchAccountData, account, refreshNeeded } from "../stores.mjs" +import { get } from "svelte/store"; + +export function deleteAccount(optPicker) { + optPicker.picker("What should we do with your files?",[ + { + name: "Delete my files", + icon: "/static/assets/icons/admin/delete_file.svg", + description: "Your files will be permanently deleted", + id: true + }, + { + name: "Do nothing", + icon: "/static/assets/icons/file.svg", + description: "Your files will not be affected", + id: false + } + ]).then((exp) => { + if (exp) { + let deleteFiles = exp.selected + + optPicker.picker(`Enter your username to continue.`,[ + { + name: "Enter your username", + icon: "/static/assets/icons/person.svg", + inputSettings: {}, + id:"username" + }, + { + name: `Delete account ${deleteFiles ? "& files" : ""}`, + icon: "/static/assets/icons/delete_account.svg", + description: `This cannot be undone.`, + id: true + } + ]).then((fin) => { + if (fin && fin.selected) { + if (fin.username != (get(account)||{}).username) { + optPicker.picker("Incorrect username. Please try again.",[]) + return + } + + fetch(`/auth/delete_account`,{method:"POST", body:JSON.stringify({ + deleteFiles + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + + } + }) + } + }) +} + +export function userChange(optPicker) { + optPicker.picker("Change username",[ + { + name: "New username", + icon: "/static/assets/icons/person.svg", + id: "username", + inputSettings: {} + }, + { + name: "Update username", + icon: "/static/assets/icons/update.svg", + description: "", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/auth/change_username`,{method:"POST", body:JSON.stringify({ + username:exp.username + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + } + }) +} + +export function forgotPassword(optPicker) { + optPicker.picker("Forgot your password?",[ + { + name: "Username", + icon: "/static/assets/icons/person.svg", + id: "user", + inputSettings: {} + }, + { + name: "OK", + icon: "/static/assets/icons/update.svg", + description: "", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/auth/request_emergency_login`,{method:"POST", body:JSON.stringify({ + account:exp.user + })}).then((response) => { + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } else { + optPicker.picker(`Please follow the instructions sent to your inbox.`,[]) + } + }) + } + }) +} + +export function emailChange(optPicker) { + optPicker.picker("Change email",[ + { + name: "New email", + icon: "/static/assets/icons/mail.svg", + id: "email", + inputSettings: {} + }, + { + name: "Request email change", + icon: "/static/assets/icons/update.svg", + description: "", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/auth/request_email_change`,{method:"POST", body:JSON.stringify({ + email:exp.email + })}).then((response) => { + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } else { + optPicker.picker(`Please continue to your inbox at ${exp.email.split("@")[1]} and click on the attached link.`,[]) + } + }) + } + }) +} + +export function pwdChng(optPicker) { + optPicker.picker("Change password",[ + { + name: "New password", + icon: "/static/assets/icons/change_password.svg", + id: "password", + inputSettings: { + password: true + } + }, + { + name: "Update password", + icon: "/static/assets/icons/update.svg", + description: "This will log you out of all sessions", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/auth/change_password`,{method:"POST", body:JSON.stringify({ + password:exp.password + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + } + }) +} + +export function customcss(optPicker) { + optPicker.picker("Set custom CSS",[ + { + name: "Enter a file ID", + icon: "/static/assets/icons/file.svg", + id: "fileid", + inputSettings: {} + }, + { + name: "OK", + icon: "/static/assets/icons/update.svg", + description: "Refresh to apply changes", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/auth/customcss`,{method:"POST", body:JSON.stringify({ + fileId:exp.fileid + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + refreshNeeded.set(true); + }) + } + }) +} + + +export function embedColor(optPicker) { + optPicker.picker("Set embed color",[ + { + name: "FFFFFF", + icon: "/static/assets/icons/pound.svg", + id: "color", + inputSettings: {} + }, + { + name: "OK", + icon: "/static/assets/icons/update.svg", + description: "", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/auth/embedcolor`,{method:"POST", body:JSON.stringify({ + color:exp.color + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + } + }) +} + + +export function embedSize(optPicker) { + optPicker.picker("Set embed image size",[ + { + name: "Large", + icon: "/static/assets/icons/image.svg", + description: "", + id: true + }, + { + name: "Small", + icon: "/static/assets/icons/small_image.svg", + description: "", + id: false + } + ]).then((exp) => { + if (exp && exp.selected !== null) { + fetch(`/auth/embedsize`,{method:"POST", body:JSON.stringify({ + largeImage:exp.selected + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + } + }) +} \ No newline at end of file diff --git a/src/svelte/elem/prompts/admin.js b/src/svelte/elem/prompts/admin.js new file mode 100644 index 0000000..b0156f3 --- /dev/null +++ b/src/svelte/elem/prompts/admin.js @@ -0,0 +1,194 @@ +import { fetchAccountData, fetchFilePointers, account } from "../stores.mjs" +import { get } from "svelte/store"; + +export function pwdReset(optPicker) { + optPicker.picker("Reset password",[ + { + name: "Target user", + icon: "/static/assets/icons/person.svg", + id: "target", + inputSettings: {} + }, + { + name: "New password", + icon: "/static/assets/icons/change_password.svg", + id: "password", + inputSettings: { + password: true + } + }, + { + name: "Update password", + icon: "/static/assets/icons/update.svg", + description: "This will log the target user out of all sessions", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/admin/reset`,{method:"POST", body:JSON.stringify({ + target: exp.target, + password:exp.password + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + }) + } + }) +} + +export function chgOwner(optPicker) { + optPicker.picker("Transfer file ownership",[ + { + name: "File ID", + icon: "/static/assets/icons/file.svg", + id: "file", + inputSettings: {} + }, + { + name: "New owner", + icon: "/static/assets/icons/person.svg", + id: "owner", + inputSettings: {} + }, + { + name: "Transfer file ownership", + icon: "/static/assets/icons/update.svg", + description: "This will transfer the file to this user", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/admin/transfer`,{method:"POST", body:JSON.stringify({ + owner: exp.owner, + target: exp.file + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + }) + } + }) +} + +export function delFile(optPicker) { + optPicker.picker("Delete file",[ + { + name: "File ID", + icon: "/static/assets/icons/file.svg", + id: "file", + inputSettings: {} + }, + { + name: "Delete", + icon: "/static/assets/icons/admin/delete_file.svg", + description: "This can't be undone", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/admin/delete`,{method:"POST", body:JSON.stringify({ + target: exp.file + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + }) + } + }) +} + +export function elevateUser(optPicker) { + optPicker.picker("Elevate user",[ + { + name: "Username", + icon: "/static/assets/icons/person.svg", + id: "user", + inputSettings: {} + }, + { + name: "Elevate to admin", + icon: "/static/assets/icons/update.svg", + description: "", + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/admin/elevate`,{method:"POST", body:JSON.stringify({ + target: exp.user + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + }) + } + }) +} + +// im really lazy so i just stole this from account.js + +export function deleteAccount(optPicker) { + optPicker.picker("What should we do with the target account's files?",[ + { + name: "Delete files", + icon: "/static/assets/icons/admin/delete_file.svg", + description: "Files will be permanently deleted", + id: true + }, + { + name: "Do nothing", + icon: "/static/assets/icons/file.svg", + description: "Files will not be affected", + id: false + } + ]).then((exp) => { + if (exp) { + let deleteFiles = exp.selected + + optPicker.picker(`Enter the target account's username to continue.`,[ + { + name: "Enter account username", + icon: "/static/assets/icons/person.svg", + inputSettings: {}, + id:"username" + }, + { + name: "Optional reason", + icon: "/static/assets/icons/more.svg", + inputSettings: {}, + id:"reason" + }, + { + name: `Delete account ${deleteFiles ? "& its files" : ""}`, + icon: "/static/assets/icons/delete_account.svg", + description: `This cannot be undone.`, + id: true + } + ]).then((fin) => { + if (fin && fin.selected) { + fetch(`/admin/delete_account`,{method:"POST", body:JSON.stringify({ + target: fin.username, + reason: fin.reason, + deleteFiles + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + + } + }) + } + }) +} \ No newline at end of file diff --git a/src/svelte/elem/prompts/uploads.js b/src/svelte/elem/prompts/uploads.js new file mode 100644 index 0000000..a9fae01 --- /dev/null +++ b/src/svelte/elem/prompts/uploads.js @@ -0,0 +1,218 @@ +import { fetchAccountData, fetchFilePointers, account } from "../stores.mjs" +import { get } from "svelte/store"; + +export let options = { + FV: [ + { + name: "Public", + icon: "/static/assets/icons/public.svg", + description: "Everyone can view your uploads", + id: "public" + }, + { + name: "Anonymous", + icon: "/static/assets/icons/anonymous.svg", + description: "Your username will be hidden", + id: "anonymous" + }, + { + name: "Private", + icon: "/static/assets/icons/private.svg", + description: "Nobody but you can view your uploads", + id: "private" + } + ], + FV2: [ + { + name: "Public", + icon: "/static/assets/icons/public.svg", + description: "Everyone can view this file", + id: "public" + }, + { + name: "Anonymous", + icon: "/static/assets/icons/anonymous.svg", + description: "Your username will be hidden", + id: "anonymous" + }, + { + name: "Private", + icon: "/static/assets/icons/private.svg", + description: "Nobody but you can view this file", + id: "private" + } + ], + AYS: [ + { + name: "Yes", + icon: "/static/assets/icons/update.svg", + id: true + } + ] +} + +export function dfv(optPicker) { + optPicker.picker("Default file visibility",options.FV).then((exp) => { + if (exp && exp.selected) { + fetch(`/auth/dfv`,{method:"POST", body:JSON.stringify({ + defaultFileVisibility: exp.selected + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + } + }) +} + +export function update_all_files(optPicker) { + optPicker.picker("You sure?",[ + { + name: "Yeah", + icon: "/static/assets/icons/update.svg", + description: `This will make all of your files ${get(account).defaultFileVisibility || "public"}`, + id: true + } + ]).then((exp) => { + if (exp && exp.selected) { + fetch(`/files/manage`,{method:"POST", body:JSON.stringify({ + target:get(account).files, + action: "changeFileVisibility", + + value: get(account).defaultFileVisibility + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchAccountData() + }) + } + }) +} + +export function fileOptions(optPicker,file) { + optPicker.picker(file.filename,[ + { + name: file.tag ? "Remove tag" : "Tag file", + icon: `/static/assets/icons/${file.tag ? "tag_remove" : "tag"}.svg`, + description: file.tag || `File has no tag`, + id: "tag" + }, + { + name: "Change file visibility", + icon: `/static/assets/icons/${file.visibility||"public"}.svg`, + description: `File is currently ${file.visibility||"public"}`, + id: "changeFileVisibility" + }, + { + name: "Delete file", + icon: `/static/assets/icons/admin/delete_file.svg`, + description: ``, + id: "delete" + } + ]).then((exp) => { + + if (exp && exp.selected) { + + switch( exp.selected ) { + + case "delete": + + fetch(`/files/manage`,{method:"POST", body:JSON.stringify({ + target: [ file.id ], + action: "delete", + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchFilePointers(); + }) + + break; + + case "changeFileVisibility": + + optPicker.picker("Set file visibility", options.FV2).then((exp) => { + + if (exp && exp.selected) { + + fetch(`/files/manage`, {method: "POST", body: JSON.stringify({ + target: [ file.id ], + action: "changeFileVisibility", + + value: exp.selected + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchFilePointers(); + }) + + } + + }) + + break; + + case "tag": + + if (file.tag) { + fetch(`/files/manage`, {method: "POST", body: JSON.stringify({ + target: [ file.id ], + action: "setTag" + })}).then(fetchFilePointers) + return + } + + optPicker.picker("Enter a tag (max 30char)",[ + { + name: "Tag name", + icon: "/static/assets/icons/tag.svg", + id: "tag", + inputSettings: {} + }, + { + name: "OK", + icon: "/static/assets/icons/update.svg", + description: "", + id: true + } + ]).then((exp) => { + + if (exp && exp.selected) { + + fetch(`/files/manage`, {method: "POST", body: JSON.stringify({ + target: [ file.id ], + action: "setTag", + + value: exp.tag || null + })}).then((response) => { + + if (response.status != 200) { + optPicker.picker(`${response.status} ${response.headers.get("x-backup-status-message") || response.statusText || ""}`,[]) + } + + fetchFilePointers(); + }) + + } + + }) + + break + + } + + } + + }) +} \ No newline at end of file diff --git a/src/svelte/elem/pulldowns/Accounts.svelte b/src/svelte/elem/pulldowns/Accounts.svelte new file mode 100644 index 0000000..f02efc3 --- /dev/null +++ b/src/svelte/elem/pulldowns/Accounts.svelte @@ -0,0 +1,242 @@ + + + + + {#if Object.keys($account).length == 0} + +
+
+

monofile accounts

+

Gain control of your uploads.

+ + {#if targetAction} + +
+ {#if !$serverStats.accounts.registrationEnabled && targetAction == "create"} +
+
+

Account registration has been disabled by this instance's owner

+
+
+ {/if} + + {#if authError} +
+
+

{authError.status} {authError.message}

+
+
+ {/if} + + + + + + {#if targetAction == "login"} + + {/if} + +
+ + {:else} + +
+ + +
+ + {/if} +
+
+ + {:else} + +
+

+ Hey there, @{$account.username} +

+ +
+ +
+

Account

+
+ + + + + + + + {#if !$account.admin} + + {/if} + +
+

Uploads

+
+ + + + + +
+

Customization

+
+ + + + + + + + {#if $refreshNeeded} + + {/if} + +
+

Sessions

+
+ + + + + + {#if $account.admin} + +
+

Admin

+
+ + + + + + + + + + + + {/if} +


{$account.id}

+
+
+ + {/if} +
\ No newline at end of file diff --git a/src/svelte/elem/pulldowns/Files.svelte b/src/svelte/elem/pulldowns/Files.svelte new file mode 100644 index 0000000..74b102f --- /dev/null +++ b/src/svelte/elem/pulldowns/Files.svelte @@ -0,0 +1,64 @@ + + + + + + + {#if !$account.username} +
+
+

Log in to view uploads

+ +
+
+ {:else} +
+ + +
+ + {#each $files.filter(f => f&&(f.filename.toLowerCase().includes(query.toLowerCase()) || f.id.toLowerCase().includes(query.toLowerCase()) || f.tag?.includes(query.toLowerCase()))) as file (file.id)} +
+ +
+
+

{file.filename}

+

+ {file.visibility||"public"}  + {file.id}  —  {file.mime.split(";")[0]} + {#if file.reserved} +
+ uploading  + Uploading... + {/if} + {#if file.tag} +
+ tag  + {file.tag} + {/if} +

+
+ +
+
+ {/each} +
+
+ {/if} + + \ No newline at end of file diff --git a/src/svelte/elem/pulldowns/Help.svelte b/src/svelte/elem/pulldowns/Help.svelte new file mode 100644 index 0000000..104af4a --- /dev/null +++ b/src/svelte/elem/pulldowns/Help.svelte @@ -0,0 +1,25 @@ + + + + + + {#each faq as question} +
+

{question.question}

+

{question.answer}

+
+ {/each} +
\ No newline at end of file diff --git a/src/svelte/elem/pulldowns/Pulldown.svelte b/src/svelte/elem/pulldowns/Pulldown.svelte new file mode 100644 index 0000000..f2efa94 --- /dev/null +++ b/src/svelte/elem/pulldowns/Pulldown.svelte @@ -0,0 +1,14 @@ + +
+ +
\ No newline at end of file diff --git a/src/svelte/elem/stores.mjs b/src/svelte/elem/stores.mjs new file mode 100644 index 0000000..d624dd7 --- /dev/null +++ b/src/svelte/elem/stores.mjs @@ -0,0 +1,35 @@ +import { writable } from "svelte/store" + +export let refreshNeeded = writable(false) +export let pulldownManager = writable(0) +export let account = writable({}) +export let serverStats = writable({}) +export let files = writable([]) + +export let fetchAccountData = function() { + fetch("/auth/me").then(async (response) => { + if (response.status == 200) { + account.set(await response.json()) + } else { + account.set({}) + } + }).catch((err) => { console.error(err) }) +} + +export let fetchFilePointers = function() { + fetch("/files/list", { cache: "no-cache" }).then(async (response) => { + if (response.status == 200) { + files.set(await response.json()) + } else { + files.set([]) + } + }).catch((err) => { console.error(err) }) +} + +export let refresh_stats = () => { + fetch("/server").then(async (data) => { + serverStats.set(await data.json()) + }).catch((err) => { console.error(err) }) +} + +fetchAccountData() \ No newline at end of file diff --git a/src/svelte/elem/transition/_void.js b/src/svelte/elem/transition/_void.js new file mode 100644 index 0000000..c9bfd0d --- /dev/null +++ b/src/svelte/elem/transition/_void.js @@ -0,0 +1,20 @@ +import { circIn, circOut } from "svelte/easing" + +export function _void(node, { duration, easingFunc, op, prop, rTarg }) { + let rect = node.getBoundingClientRect() + + return { + duration: duration||300, + css: t => { + let eased = (easingFunc || circIn)(t) + + return ` + white-space: nowrap; + ${prop||"height"}: ${(eased)*(rect[rTarg||prop||"height"])}px; + padding: 0px; + opacity:${eased}; + overflow: clip; + ` + } + } +} \ No newline at end of file diff --git a/src/svelte/elem/transition/padding_scaleY.js b/src/svelte/elem/transition/padding_scaleY.js new file mode 100644 index 0000000..c19a44b --- /dev/null +++ b/src/svelte/elem/transition/padding_scaleY.js @@ -0,0 +1,18 @@ +import { circIn, circOut } from "svelte/easing" + +export function padding_scaleY(node, { duration, easingFunc, padY, padX, op }) { + let rect = node.getBoundingClientRect() + + return { + duration: duration||300, + css: t => { + let eased = (easingFunc || circOut)(t) + + return ` + height: ${eased*(rect.height-(padY||0))}px; + ${padX&&padY ? `padding: ${(eased)*(padY)}px ${(padX)}px;` : ""} + ${op ? `opacity: ${eased};` : ""} + ` + } + } +} \ No newline at end of file diff --git a/src/svelte/elem/uploader/AttachmentZone.svelte b/src/svelte/elem/uploader/AttachmentZone.svelte new file mode 100644 index 0000000..7d70559 --- /dev/null +++ b/src/svelte/elem/uploader/AttachmentZone.svelte @@ -0,0 +1,93 @@ + + + + +
+

+ +add files +

+ {#if !uploadType} +
+ + +
+ {:else} + {#if uploadType == uploadTypes.files} +
+
+

click/tap to browse
or drag files into this box

+ +
+
+ {:else if uploadType == uploadTypes.clone} +
+ + +
+ {/if} + {/if} +
\ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 9715926..1867d13 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,104 +1,104 @@ -{ - "include":["src/**/*"], - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - // "rootDir": "./src/", /* Specify the root folder within your source files. */ - // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./out/", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} +{ + "include":["src/server/**/*"], + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./src/", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./out/server", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}