summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--README.md56
-rw-r--r--index.ts123
-rw-r--r--package-lock.json717
-rw-r--r--package.json51
-rw-r--r--prisma/schema.prisma36
-rw-r--r--router.ts120
-rw-r--r--src/CLI.ts31
-rw-r--r--src/Main.ts84
-rw-r--r--src/clients/Multer.ts68
-rw-r--r--src/clients/Prisma.ts19
-rw-r--r--src/routers/Auth.ts100
-rw-r--r--src/routers/Image.ts107
-rw-r--r--src/routers/Profile.ts58
-rw-r--r--static/css/style.css331
-rw-r--r--static/ejs/pages/home.ejs81
-rw-r--r--static/ejs/pages/me.ejs88
-rw-r--r--static/ejs/partials/bar.ejs7
-rw-r--r--static/ejs/partials/meta.ejs1
-rw-r--r--static/html/index.html62
-rw-r--r--static/img/favicon.png (renamed from static/webimg/favicon.png)bin70631 -> 70631 bytes
-rw-r--r--static/img/twitch.pngbin0 -> 6800 bytes
-rw-r--r--tsconfig.json6
23 files changed, 1621 insertions, 532 deletions
diff --git a/.gitignore b/.gitignore
index 55bcd35..eaccbf6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -129,5 +129,8 @@ dist
.yarn/install-state.gz
.pnp.*
-static/i
-options.json \ No newline at end of file
+# Picturebin
+*.ini
+static/images
+prisma/migrations
+*.db \ No newline at end of file
diff --git a/README.md b/README.md
index 622a05a..1546315 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
<div align="center">
<h1>
- <img src="./static/webimg/favicon.png" width=32> File Hoster!
+ <img src="./static/img/favicon.png" width=32> <b>Pic</b>ture<b>Bin</b> <i>(formerly Dank File Hoster)</i>
<br>
<a href="https://wakatime.com/badge/user/09f67b1c-0691-482a-a1d4-e4751e6962de/project/eda75115-4dad-4ada-995a-f1379687f257"><img src="https://wakatime.com/badge/user/09f67b1c-0691-482a-a1d4-e4751e6962de/project/eda75115-4dad-4ada-995a-f1379687f257.svg?style=plastic" alt="wakatime"></a>
</h1>
@@ -24,28 +24,48 @@
</div>
A small file hoster on ExpressJS.
+## Dependencies:
+1. Node.js
+2. NPM
+3. Typescript
+
## Installation:
-1. Use the script...
- 1. as a standalone app:
- ```bash
- $ git clone https://github.com/notdankenough/fh.git
- $ cd fh
- $ npm install
- $ npm run start
- ```
- 2. as a module for your project:
- ```bash
- $ git submodule add https://github.com/notdankenough/fh.git
- ```
- and you can import it as: `import SRouter from "./fh/router";`
+1. Install from Git repository:
+```bash
+$ git clone https://github.com/notdankenough/picbin
+$ cd picbin
+```
+2. Install the Node.js modules:
+```bash
+$ npm install
+```
+3. Run Prisma migrations. This will create the database:
+```bash
+$ npx prisma migrate dev
+```
+4. Build the app:
+```bash
+$ npm run build
+```
+5. Generate the configuration files. The program will create a `config.ini` file and you will need to insert the necessary values into their fields:
+```bash
+$ npm run init
+```
+6. Run the app:
+```bash
+$ npm run start
+```
+7. ???
+8. PROFIT! Now you have your own dank image hoster.
## Use in other tools:
-1. [ <img src="https://camo.githubusercontent.com/6ca305d42786c9dbd0b76f5ade013601b080d71a598e881b4349dff2eafae6c7/68747470733a2f2f666f757274662e636f6d2f696d672f63686174746572696e6f2d69636f6e2d36342e706e67" width=24> Chatterino 2 (by fourtf, pajlada, and more...)](https://github.com/chatterino/chatterino2):
+1. [ <img src="https://camo.githubusercontent.com/6ca305d42786c9dbd0b76f5ade013601b080d71a598e881b4349dff2eafae6c7/68747470733a2f2f666f757274662e636f6d2f696d672f63686174746572696e6f2d69636f6e2d36342e706e67" width=24> Chatterino (by fourtf, pajlada, and more...)](https://github.com/chatterino/chatterino2):
1. Go to `Settings -> External Tools -> Image Uploader` and paste the values in the relevant fields:
| Field | Value | Example |
| ---- | ------ | ------- |
- | Request URL: | `<YOUR_DOMAIN>`/dank_upload | https://hmmtodayiwill.ru/i/dank_upload
+ | Request URL: | `<YOUR_DOMAIN>`/upload | https://i.hmmtodayiwill.ru/upload
| Form field: | file |
- | Extra Headers: | no-redirect: true |
- | Image Link: | `<YOUR_DOMAIN>`/i/{name} | https://hmmtodayiwill.ru/i/{name}
+ | Extra Headers: | `Authorization: <some Base64 shit>` | Authorization: SUZZT1VTRUVUSElTVklWT05aVUxVTA==
+
+> * If you want to upload pictures under your account, you need to log in with your Twitch account [here](https://i.hmmtodayiwill.ru/). \ No newline at end of file
diff --git a/index.ts b/index.ts
index 89bb0d8..96e4a97 100644
--- a/index.ts
+++ b/index.ts
@@ -1,4 +1,4 @@
-// Copyright 2022 ilotterytea
+// Copyright 2022 NotDankEnough (ilotterytea)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,99 +12,38 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Command } from "commander";
-import chalk from "chalk";
-import express from "express";
-
-import pck from "./package.json";
-import SRouter from "./router";
-import { existsSync, mkdirSync, writeFileSync } from "fs";
-
-main();
-
-/**
- * The "web server" script.
- */
-function main() {
- // Obtaining the options that have been provided in the command line interface:
- const cli = CLI();
- const opts = cli.opts();
-
- try {
- // Create the necessary files if the script was started with the --init option:
- if (opts.init) {
- if (!(existsSync("./options.json"))) {
- writeFileSync("./options.json", JSON.stringify({
- allowedMIMETypes: [
- "image/jpeg",
- "image/png",
- "image/svg+xml",
- "image/tiff",
- "image/webp",
- "image/gif",
- "video/mp4"],
- maxFileSizeInBytes: 13107200
- }, null, 2), {encoding: "utf-8"});
- console.debug(chalk.green("The options file created!"));
- }
- return;
- }
-
- // Run the server if the script was started with the --standalone option:
- if (opts.standalone) {
- // ExpressJS instance:
- const App = express();
-
- // Using an image loader with custom route (--route <value>) on the server:
- App.use(opts.route, SRouter);
-
- // Using a static folder. Also, this will be used when viewing uploaded pictures.
- App.use(express.static(`${__dirname}/static`));
-
- // Starting the server on the specified port:
- App.listen(opts.port, () => {
- console.debug(chalk.bgGreen("Server (Image hoster) running on port ", opts.port));
- });
+import CLI from "./src/CLI";
+import Main from "./src/Main";
+import Ini from "ini";
+import { readFileSync, writeFileSync } from "fs";
+import { Logger } from "tslog";
+
+const log: Logger = new Logger({name: "init"});
+const cli: Record<string, string | boolean> = CLI();
+
+if (cli.init) {
+ const cfg_template = {
+ Auth: {
+ ClientID: "",
+ ClientSecret: "",
+ RedirectURI: ""
+ },
+ Certificate: {
+ Key: "",
+ Cert: "",
+ Ca: ""
+ },
+ Ports: {
+ HTTP: "80",
+ HTTPS: "443"
}
- } catch (err: any) {
- console.log(chalk.bgRed(err));
}
-}
-/**
- * Silly command-line interface.
- */
-function CLI() {
- // New Command instance:
- const Program = new Command();
+ writeFileSync("config.ini", Ini.stringify(cfg_template), {encoding: "utf-8"});
+ log.debug("Config file is generated! Exiting...");
+ process.exit(0);
+}
- // Setting the information about Program:
- Program
- .name(pck.displayName)
- .description(pck.description)
- .version(pck.version);
-
- // Create an option to run this script as a web app:
- Program
- .option("--standalone", "Run the script as a web app.", false)
- .alias("-s");
-
- // The option to be specified as the port in the web app:
- Program
- .option("--port <value>", "Set the port for standalone app.", "8080")
- .alias("-p");
-
- // The route for our image uploader:
- Program
- .option("--route <value>", "Set the route for standalone app.", "/")
- .alias("-r");
-
- // Initialize the first setup of image uploader:
- Program
- .option("--init", "Create the necessary files for image uploader.", false);
-
- // Parse the process arguments:
- Program.parse(process.argv);
+const config: {[key: string]: any} = Ini.parse(readFileSync("./config.ini", {encoding: "utf-8"}));
- return Program;
-} \ No newline at end of file
+Main(__dirname, config, cli); \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 8a1e040..2f5bb7e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,53 +1,110 @@
{
- "name": "imaimagehoster",
- "version": "1.0.0",
+ "name": "@notdankenough/picbin",
+ "version": "1.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "name": "imaimagehoster",
- "version": "1.0.0",
+ "name": "@notdankenough/picbin",
+ "version": "1.1.0",
"license": "Apache-2.0",
"dependencies": {
- "chalk": "^4.1.2",
- "commander": "^9.3.0",
+ "@prisma/client": "^4.2.1",
+ "@types/multer": "^1.4.7",
+ "axios": "^0.27.2",
+ "body-parser": "^1.20.0",
+ "commander": "^9.4.0",
+ "cookie-parser": "^1.4.6",
+ "ejs": "^3.1.8",
"express": "^4.18.1",
"fs": "^0.0.1-security",
- "mime": "^1.4.1",
+ "ini": "^3.0.0",
+ "jquery": "^3.6.0",
+ "mime": "^3.0.0",
"multer": "^1.4.5-lts.1",
- "serve-favicon": "^2.5.0"
+ "tslog": "^3.3.3"
},
"devDependencies": {
+ "@types/body-parser": "^1.19.2",
+ "@types/commander": "^2.12.2",
+ "@types/cookie-parser": "^1.4.3",
"@types/express": "^4.17.13",
- "@types/multer": "^1.4.7",
- "@types/node": "^18.0.1",
- "@types/serve-favicon": "^2.5.3"
+ "@types/ini": "^1.3.31",
+ "prisma": "^4.2.1"
}
},
+ "node_modules/@prisma/client": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.2.1.tgz",
+ "integrity": "sha512-PZBkY60+k5oix+e6IUfl3ub8TbRLNsPLdfWrdy2eh80WcHTaT+/UfvXf/B7gXedH7FRtbPFHZXk1hZenJiJZFQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@prisma/engines-version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826"
+ },
+ "engines": {
+ "node": ">=14.17"
+ },
+ "peerDependencies": {
+ "prisma": "*"
+ },
+ "peerDependenciesMeta": {
+ "prisma": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@prisma/engines": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.2.1.tgz",
+ "integrity": "sha512-0KqBwREUOjBiHwITsQzw2DWfLHjntvbqzGRawj4sBMnIiL5CXwyDUKeHOwXzKMtNr1rEjxEsypM14g0CzLRK3g==",
+ "devOptional": true,
+ "hasInstallScript": true
+ },
+ "node_modules/@prisma/engines-version": {
+ "version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826",
+ "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826.tgz",
+ "integrity": "sha512-tktkqdiwqE4QhmE088boPt+FwPj1Jub/zk+5F6sEfcRHzO5yz9jyMD5HFVtiwxZPLx/8Xg9ElnuTi8E5lWVQFQ=="
+ },
"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==",
- "dev": true,
"dependencies": {
"@types/connect": "*",
"@types/node": "*"
}
},
+ "node_modules/@types/commander": {
+ "version": "2.12.2",
+ "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz",
+ "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==",
+ "deprecated": "This is a stub types definition for commander (https://github.com/tj/commander.js). commander provides its own type definitions, so you don't need @types/commander installed!",
+ "dev": true,
+ "dependencies": {
+ "commander": "*"
+ }
+ },
"node_modules/@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
- "dev": true,
"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/express": {
"version": "4.17.13",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
"integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
- "dev": true,
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
@@ -56,65 +113,55 @@
}
},
"node_modules/@types/express-serve-static-core": {
- "version": "4.17.29",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz",
- "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==",
- "dev": true,
+ "version": "4.17.30",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz",
+ "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==",
"dependencies": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
- "node_modules/@types/mime": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
- "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
+ "node_modules/@types/ini": {
+ "version": "1.3.31",
+ "resolved": "https://registry.npmjs.org/@types/ini/-/ini-1.3.31.tgz",
+ "integrity": "sha512-8ecxxaG4AlVEM1k9+BsziMw8UsX0qy3jYI1ad/71RrDZ+rdL6aZB0wLfAuflQiDhkD5o4yJ0uPK3OSUic3fG0w==",
"dev": true
},
+ "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==",
- "dev": true,
"dependencies": {
"@types/express": "*"
}
},
"node_modules/@types/node": {
- "version": "18.0.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.1.tgz",
- "integrity": "sha512-CmR8+Tsy95hhwtZBKJBs0/FFq4XX7sDZHlGGf+0q+BRZfMbOTkzkj0AFAuTyXbObDIoanaBBW0+KEW+m3N16Wg==",
- "dev": true
+ "version": "18.7.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.4.tgz",
+ "integrity": "sha512-RzRcw8c0B8LzryWOR4Wj7YOTFXvdYKwvrb6xQQyuDfnlTxwYXGCV5RZ/TEbq5L5kn+w3rliHAUyRcG1RtbmTFg=="
},
"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==",
- "dev": true
+ "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==",
- "dev": true
- },
- "node_modules/@types/serve-favicon": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/@types/serve-favicon/-/serve-favicon-2.5.3.tgz",
- "integrity": "sha512-HirXLRJjLXzwiSnjhE1vMu55X7+qaY+noXsKqi/7eK1uByl3L6TwkcALZuJnQXqOalMdmBz3b662yXvaR+89Vw==",
- "dev": true,
- "dependencies": {
- "@types/express": "*"
- }
+ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
},
"node_modules/@types/serve-static": {
- "version": "1.13.10",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
- "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
- "dev": true,
+ "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": "^1",
+ "@types/mime": "*",
"@types/node": "*"
}
},
@@ -154,6 +201,30 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
+ "node_modules/async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
+ },
+ "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/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
"node_modules/body-parser": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
@@ -177,6 +248,15 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -244,14 +324,30 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "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/commander": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
- "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz",
+ "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==",
"engines": {
"node": "^12.20.0 || >=14"
}
},
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
"node_modules/concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
@@ -293,6 +389,26 @@
"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",
@@ -311,6 +427,14 @@
"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",
@@ -333,6 +457,20 @@
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
+ "node_modules/ejs": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
+ "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
+ "dependencies": {
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -395,6 +533,33 @@
"node": ">= 0.10.0"
}
},
+ "node_modules/filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "dependencies": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
@@ -412,6 +577,38 @@
"node": ">= 0.8"
}
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+ "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
+ "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",
@@ -512,6 +709,14 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "node_modules/ini": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.0.tgz",
+ "integrity": "sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw==",
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -525,6 +730,28 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
+ "node_modules/jake": {
+ "version": "10.8.5",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
+ "dependencies": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.1",
+ "minimatch": "^3.0.4"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jquery": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
+ "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -547,11 +774,14 @@
}
},
"node_modules/mime": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
- "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"bin": {
"mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
}
},
"node_modules/mime-db": {
@@ -573,6 +803,17 @@
"node": ">= 0.6"
}
},
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
@@ -659,6 +900,23 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
},
+ "node_modules/prisma": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.2.1.tgz",
+ "integrity": "sha512-HuYqnTDgH8atjPGtYmY0Ql9XrrJnfW7daG1PtAJRW0E6gJxc50lY3vrIDn0yjMR3TvRlypjTcspQX8DT+xD4Sg==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@prisma/engines": "4.2.1"
+ },
+ "bin": {
+ "prisma": "build/index.js",
+ "prisma2": "build/index.js"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -794,31 +1052,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
- "node_modules/serve-favicon": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz",
- "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==",
- "dependencies": {
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "ms": "2.1.1",
- "parseurl": "~1.3.2",
- "safe-buffer": "5.1.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/serve-favicon/node_modules/ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
- },
- "node_modules/serve-favicon/node_modules/safe-buffer": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
- "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
- },
"node_modules/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
@@ -851,6 +1084,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@@ -899,6 +1149,17 @@
"node": ">=0.6"
}
},
+ "node_modules/tslog": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.3.3.tgz",
+ "integrity": "sha512-lGrkndwpAohZ9ntQpT+xtUw5k9YFV1DjsksiWQlBSf82TTqsSAWBARPRD9juI730r8o3Awpkjp2aXy9k+6vr+g==",
+ "dependencies": {
+ "source-map-support": "^0.5.21"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -955,30 +1216,64 @@
}
},
"dependencies": {
+ "@prisma/client": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.2.1.tgz",
+ "integrity": "sha512-PZBkY60+k5oix+e6IUfl3ub8TbRLNsPLdfWrdy2eh80WcHTaT+/UfvXf/B7gXedH7FRtbPFHZXk1hZenJiJZFQ==",
+ "requires": {
+ "@prisma/engines-version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826"
+ }
+ },
+ "@prisma/engines": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.2.1.tgz",
+ "integrity": "sha512-0KqBwREUOjBiHwITsQzw2DWfLHjntvbqzGRawj4sBMnIiL5CXwyDUKeHOwXzKMtNr1rEjxEsypM14g0CzLRK3g==",
+ "devOptional": true
+ },
+ "@prisma/engines-version": {
+ "version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826",
+ "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826.tgz",
+ "integrity": "sha512-tktkqdiwqE4QhmE088boPt+FwPj1Jub/zk+5F6sEfcRHzO5yz9jyMD5HFVtiwxZPLx/8Xg9ElnuTi8E5lWVQFQ=="
+ },
"@types/body-parser": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
"integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
- "dev": true,
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
+ "@types/commander": {
+ "version": "2.12.2",
+ "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz",
+ "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==",
+ "dev": true,
+ "requires": {
+ "commander": "*"
+ }
+ },
"@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
- "dev": true,
"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/express": {
"version": "4.17.13",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
"integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
- "dev": true,
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
@@ -987,65 +1282,55 @@
}
},
"@types/express-serve-static-core": {
- "version": "4.17.29",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz",
- "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==",
- "dev": true,
+ "version": "4.17.30",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz",
+ "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==",
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
- "@types/mime": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
- "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
+ "@types/ini": {
+ "version": "1.3.31",
+ "resolved": "https://registry.npmjs.org/@types/ini/-/ini-1.3.31.tgz",
+ "integrity": "sha512-8ecxxaG4AlVEM1k9+BsziMw8UsX0qy3jYI1ad/71RrDZ+rdL6aZB0wLfAuflQiDhkD5o4yJ0uPK3OSUic3fG0w==",
"dev": true
},
+ "@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==",
- "dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/node": {
- "version": "18.0.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.1.tgz",
- "integrity": "sha512-CmR8+Tsy95hhwtZBKJBs0/FFq4XX7sDZHlGGf+0q+BRZfMbOTkzkj0AFAuTyXbObDIoanaBBW0+KEW+m3N16Wg==",
- "dev": true
+ "version": "18.7.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.4.tgz",
+ "integrity": "sha512-RzRcw8c0B8LzryWOR4Wj7YOTFXvdYKwvrb6xQQyuDfnlTxwYXGCV5RZ/TEbq5L5kn+w3rliHAUyRcG1RtbmTFg=="
},
"@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==",
- "dev": true
+ "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==",
- "dev": true
- },
- "@types/serve-favicon": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/@types/serve-favicon/-/serve-favicon-2.5.3.tgz",
- "integrity": "sha512-HirXLRJjLXzwiSnjhE1vMu55X7+qaY+noXsKqi/7eK1uByl3L6TwkcALZuJnQXqOalMdmBz3b662yXvaR+89Vw==",
- "dev": true,
- "requires": {
- "@types/express": "*"
- }
+ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
},
"@types/serve-static": {
- "version": "1.13.10",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
- "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
- "dev": true,
+ "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": "^1",
+ "@types/mime": "*",
"@types/node": "*"
}
},
@@ -1076,6 +1361,30 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
+ "async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
+ },
+ "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"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
"body-parser": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
@@ -1095,6 +1404,15 @@
"unpipe": "1.0.0"
}
},
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
"buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -1144,10 +1462,23 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "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"
+ }
+ },
"commander": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
- "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw=="
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz",
+ "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw=="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"concat-stream": {
"version": "1.6.2",
@@ -1178,6 +1509,22 @@
"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",
@@ -1196,6 +1543,11 @@
"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",
@@ -1211,6 +1563,14 @@
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
+ "ejs": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
+ "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
+ "requires": {
+ "jake": "^10.8.5"
+ }
+ },
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -1264,6 +1624,32 @@
"vary": "~1.1.2"
}
},
+ "filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "requires": {
+ "minimatch": "^5.0.1"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
"finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
@@ -1278,6 +1664,21 @@
"unpipe": "~1.0.0"
}
},
+ "follow-redirects": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+ "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
+ },
+ "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",
@@ -1351,6 +1752,11 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "ini": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.0.tgz",
+ "integrity": "sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw=="
+ },
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -1361,6 +1767,22 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
+ "jake": {
+ "version": "10.8.5",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
+ "requires": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.1",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "jquery": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
+ "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
+ },
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -1377,9 +1799,9 @@
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
},
"mime": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
- "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="
},
"mime-db": {
"version": "1.52.0",
@@ -1394,6 +1816,14 @@
"mime-db": "1.52.0"
}
},
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
"minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
@@ -1459,6 +1889,15 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
},
+ "prisma": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.2.1.tgz",
+ "integrity": "sha512-HuYqnTDgH8atjPGtYmY0Ql9XrrJnfW7daG1PtAJRW0E6gJxc50lY3vrIDn0yjMR3TvRlypjTcspQX8DT+xD4Sg==",
+ "devOptional": true,
+ "requires": {
+ "@prisma/engines": "4.2.1"
+ }
+ },
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -1560,30 +1999,6 @@
}
}
},
- "serve-favicon": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz",
- "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==",
- "requires": {
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "ms": "2.1.1",
- "parseurl": "~1.3.2",
- "safe-buffer": "5.1.1"
- },
- "dependencies": {
- "ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
- },
- "safe-buffer": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
- "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
- }
- }
- },
"serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
@@ -1610,6 +2025,20 @@
"object-inspect": "^1.9.0"
}
},
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
"statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@@ -1648,6 +2077,14 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
+ "tslog": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.3.3.tgz",
+ "integrity": "sha512-lGrkndwpAohZ9ntQpT+xtUw5k9YFV1DjsksiWQlBSf82TTqsSAWBARPRD9juI730r8o3Awpkjp2aXy9k+6vr+g==",
+ "requires": {
+ "source-map-support": "^0.5.21"
+ }
+ },
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
diff --git a/package.json b/package.json
index dc3e76c..347e9b9 100644
--- a/package.json
+++ b/package.json
@@ -1,35 +1,52 @@
{
- "name": "imafilehoster",
- "displayName": "I'm a File hoster.",
- "version": "1.0.0",
- "description": "iLotterytea's File hoster using ExpressJS.",
- "main": "index.ts",
+ "name": "@notdankenough/picbin",
+ "version": "1.1.0",
+ "description": "Simple web hoster for your pictures and other media files.",
+ "main": "index.js",
"scripts": {
- "start": "ts-node ./index.ts --standalone"
+ "test": "ts-node index.ts --debug",
+ "build": "tsc",
+ "init": "node dist/index.js --init",
+ "start": "node dist/index.js"
},
"repository": {
"type": "git",
- "url": "git+https://github.com/notdankenough/fh.git"
+ "url": "git+https://github.com/notdankenough/picbin.git"
},
- "author": "NotDankEnough <hatesociety@pm.me> (https://hmmtodayiwill.ru)",
+ "keywords": [
+ "hoster",
+ "web",
+ "expressjs",
+ "pictures"
+ ],
+ "author": "NotDankEnough <hatesociety@pm.me> (https://hmmtodayiwill.ru/)",
"license": "Apache-2.0",
"bugs": {
- "url": "https://github.com/notdankenough/fh/issues"
+ "url": "https://github.com/notdankenough/picbin/issues"
},
- "homepage": "https://github.com/notdankenough/fh#readme",
+ "homepage": "https://github.com/notdankenough/picbin#readme",
"dependencies": {
- "chalk": "^4.1.2",
- "commander": "^9.3.0",
+ "@prisma/client": "^4.2.1",
+ "@types/multer": "^1.4.7",
+ "axios": "^0.27.2",
+ "body-parser": "^1.20.0",
+ "commander": "^9.4.0",
+ "cookie-parser": "^1.4.6",
+ "ejs": "^3.1.8",
"express": "^4.18.1",
"fs": "^0.0.1-security",
- "mime": "^1.4.1",
+ "ini": "^3.0.0",
+ "jquery": "^3.6.0",
+ "mime": "^3.0.0",
"multer": "^1.4.5-lts.1",
- "serve-favicon": "^2.5.0"
+ "tslog": "^3.3.3"
},
"devDependencies": {
+ "@types/body-parser": "^1.19.2",
+ "@types/commander": "^2.12.2",
+ "@types/cookie-parser": "^1.4.3",
"@types/express": "^4.17.13",
- "@types/multer": "^1.4.7",
- "@types/node": "^18.0.1",
- "@types/serve-favicon": "^2.5.3"
+ "@types/ini": "^1.3.31",
+ "prisma": "^4.2.1"
}
}
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 0000000..c4d04d2
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,36 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "sqlite"
+ url = "file:data.db"
+}
+
+model Image {
+ id String @id @unique @default(cuid())
+ storage_id String
+ description String?
+ is_hidden Boolean?
+ burn_after_watched Boolean?
+ ext String
+ view_count Int? @default(0)
+ user User? @relation(fields: [userId], references: [id])
+ userId Int?
+ timestamp DateTime @default(now())
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ alias_id Int? @unique
+ key String
+ name String
+ desc String?
+ pic String @default("../img/default_avatar.png")
+ pswd String?
+ is_supauser Boolean?
+ Image Image[]
+}
diff --git a/router.ts b/router.ts
deleted file mode 100644
index 7e8b147..0000000
--- a/router.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2022 ilotterytea
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import express, {
- RequestHandler
-} from "express";
-import favicon from "serve-favicon";
-import pck from "./package.json";
-import i_opts from "./options.json";
-import multer from "multer";
-import crypto from "crypto";
-
-import { existsSync, readdirSync, readFileSync } from "fs";
-import mime from "mime";
-
-const router = express.Router();
-
-// To store files on local disk:
-const storage = multer.diskStorage({
- // File destination:
- destination: "./static/i",
- // Creation of file name:
- filename: (req, file, callback) => {
- // Compare file size and limit:
- if (file.size > i_opts.maxFileSizeInBytes) {
- callback(Error("The file size is larger than the maximum set value."), "");
- return;
- }
-
- // Name pattern:
- var pattern = "number/dir";
-
- switch (pattern) {
- // A name for the file based on where it will be positioned amongst the other files after uploading:
- case "number/dir":
- const img_id = readdirSync("./static/i").length + 1;
-
- var maxzero = 5;
- var zerostring = "";
-
- for (var i = 0; i < maxzero; i++) { zerostring = zerostring + "0"; }
-
- zerostring = zerostring.slice(img_id.toString().length, zerostring.length);
-
- callback(null, zerostring + img_id.toString() + "." + mime.extension(file.mimetype));
- break;
- // Random byte name:
- case "crypto/hex":
- crypto.randomBytes(5 /* <-- Character length */, (err, raw) => {
- if (err) return callback(err, "");
- callback(null, raw.toString("hex") + "." + mime.extension(file.mimetype));
- });
- break;
- default:
- break;
- }
- }
-});
-
-// Image uploader:
-const upload = multer({
- storage: storage,
- fileFilter(req, file, callback) {
- if (i_opts.allowedMIMETypes.includes(file.mimetype)) {
- callback(null, true);
- } else {
- callback(null, false);
- console.debug("The extension of this file isn't allowed.");
- }
- },
-})
-
-// Main page:
-router.get("/", async (req, res) => {
- var Page: string = readFileSync(`${__dirname}/static/html/index.html`, {encoding: "utf-8"});
-
- Page = Page.replace("{{AboutFileHoster}}", `Running on notdankenough/fh@${pck.version}!`);
-
- res.send(Page);
-});
-
-// Viewing files.
-router.get("/i/:id", async (req, res) => {
- if (!(existsSync("./static/i/" + req.params.id))) {
- return res.json({
- status: 404,
- reason: "The file " + req.params.id + " not found!",
- kitty: "https://http.cat/404"
- }).status(404);
- }
-
- return res.sendFile(`${__dirname}/static/i/${req.params.id}`);
-});
-
-// POST request to upload a file and then send its name:
-router.post("/dank_upload", upload.single("file"), (req, res) => {
- var name = req.file?.filename;
-
- // Required for some external tools:
- if (req.headers["no-redirect"]) {
- return res.json({
- name: name
- }).status(200);
- }
-
- res.redirect("/i/" + name);
-});
-
-export default router; \ No newline at end of file
diff --git a/src/CLI.ts b/src/CLI.ts
new file mode 100644
index 0000000..f1e4faf
--- /dev/null
+++ b/src/CLI.ts
@@ -0,0 +1,31 @@
+// Copyright 2022 NotDankEnough (ilotterytea)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Command } from "commander";
+
+/**
+ * Silly Command-Line Interface.
+ * @returns options.
+ */
+function CLI(): Record<string, string | boolean> {
+ const Program = new Command();
+
+ Program.option("--init", "Generate the neccessary files.", false);
+ Program.option("--no-ssl", "Run application in debug mode. Port for HTTP connection is \"8080\" instead of standard \"80\".", false);
+
+ Program.parse(process.argv);
+ return Program.opts();
+}
+
+export default CLI; \ No newline at end of file
diff --git a/src/Main.ts b/src/Main.ts
new file mode 100644
index 0000000..bf75f2a
--- /dev/null
+++ b/src/Main.ts
@@ -0,0 +1,84 @@
+// Copyright 2022 NotDankEnough (ilotterytea)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import express from "express";
+
+import cookieParser from "cookie-parser";
+import bodyParser from "body-parser";
+
+import http from "http";
+import https from "https";
+
+import { Logger } from "tslog";
+
+import ProfileRouter from "./routers/Profile";
+import AuthRouter from "./routers/Auth";
+import ImageRouter from "./routers/Image";
+import { PrismaClient } from "@prisma/client";
+
+const log: Logger = new Logger({name: "main"});
+
+function Main(dirPath: string, cfg: {[key: string]: any}, cli_options?: {[key: string]: any}): void {
+ const App: express.Express = express();
+ const prisma: PrismaClient = new PrismaClient();
+
+ var httpc: http.Server | null = null;
+ var httpsc: https.Server | null = null;
+
+ App.set("view engine", "ejs");
+ App.set("views", `${dirPath}/static/ejs`);
+
+ App.use(cookieParser());
+ App.use(bodyParser.urlencoded({extended: false}));
+
+ App.use("/me", ProfileRouter(dirPath, prisma));
+ App.use("/auth", AuthRouter(dirPath, cfg, prisma));
+ App.use("/", ImageRouter(dirPath, cfg, prisma));
+
+ App.use(express.static(`${dirPath}/static`));
+
+ if (cli_options) {
+ if (!cli_options.noSsl) {
+ httpc = http.createServer(App);
+ httpc.listen(parseInt(cfg.Ports.HTTP), () => {
+ log.info("Image hoster is running on port", cfg.Ports.HTTP);
+ });
+ } else {
+ if (
+ !cfg.Certificate.Key ||
+ !cfg.Certificate.Cert ||
+ !cfg.Certificate.Ca
+ ) {
+ log.error("No paths for certificate provided.");
+ process.exit(1);
+ }
+
+ const credentials = {
+ key: cfg.Certificate.Key,
+ cert: cfg.Certificate.Cert,
+ ca: cfg.Certificate.Ca
+ }
+
+ httpsc = https.createServer(credentials, App);
+ httpsc.listen(parseInt(cfg.Ports.HTTPS), () => {
+ log.info("Image hoster is running on port", cfg.Ports.HTTPS, "(SSL)");
+ });
+ }
+ } else {
+ log.error("NO CLI OPTIONS PROVIDED!!!")
+ process.exit(1);
+ }
+}
+
+export default Main; \ No newline at end of file
diff --git a/src/clients/Multer.ts b/src/clients/Multer.ts
new file mode 100644
index 0000000..81f2b0f
--- /dev/null
+++ b/src/clients/Multer.ts
@@ -0,0 +1,68 @@
+// Copyright 2022 NotDankEnough (ilotterytea)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import multer from "multer";
+import mime from "mime";
+import crypto from "crypto";
+import { readdirSync } from "fs";
+
+const fileFilter = (req: Express.Request, res: Express.Response, cb: multer.FileFilterCallback) => {
+ cb(null, true);
+}
+
+const storage = multer.diskStorage({
+ destination: "static/images",
+ filename(req, file, callback) {
+ if (!req.headers["pattern"]) req.headers["pattern"] = "random";
+
+ switch (req.headers["pattern"]) {
+ case "numeration": {
+ const img_id: number = readdirSync("images").length + 1;
+ const max_zero: number = 5;
+ var blank_string: string = "";
+
+ for (var i = 0; i < max_zero; i++) { blank_string = blank_string + "0"; }
+
+ blank_string = blank_string.slice(img_id.toString().length, blank_string.length);
+
+ callback(null, `${blank_string}${img_id.toString()}.${mime.getExtension(file.mimetype)}`);
+ break;
+ }
+ case "random": {
+ crypto.randomBytes(5, (err, raw) => {
+ if (err) return callback(err, "");
+ callback(null, `${raw.toString("hex")}.${mime.getExtension(file.mimetype)}`)
+ });
+ break;
+ }
+ default: {
+ crypto.randomBytes(5, (err, raw) => {
+ if (err) return callback(err, "");
+ callback(null, `${raw.toString("hex")}.${mime.getExtension(file.mimetype)}`)
+ });
+ break;
+ }
+ }
+ }
+});
+
+const Multer = multer({
+ fileFilter: fileFilter,
+ storage: storage,
+ limits: {
+ fieldSize: 1.6e+7
+ }
+});
+
+export default Multer; \ No newline at end of file
diff --git a/src/clients/Prisma.ts b/src/clients/Prisma.ts
new file mode 100644
index 0000000..1e17fc9
--- /dev/null
+++ b/src/clients/Prisma.ts
@@ -0,0 +1,19 @@
+// Copyright 2022 NotDankEnough (ilotterytea)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { PrismaClient } from "@prisma/client";
+
+const prisma = new PrismaClient();
+
+export default prisma; \ No newline at end of file
diff --git a/src/routers/Auth.ts b/src/routers/Auth.ts
new file mode 100644
index 0000000..146bafe
--- /dev/null
+++ b/src/routers/Auth.ts
@@ -0,0 +1,100 @@
+// Copyright 2022 NotDankEnough (ilotterytea)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Router, CookieOptions } from "express";
+import { PrismaClient, User } from "@prisma/client";
+import { randomBytes } from "crypto";
+import axios from "axios";
+import { Logger } from "tslog";
+
+const log: Logger = new Logger({name: "authlog"});
+
+function AuthRouter(dirPath: string, cfg: {[key: string]: any}, prisma: PrismaClient): Router {
+ const router: Router = Router();
+
+ router.get("/twitch", async (req, res) => {
+ if (!("code" in req.query)) {
+ return res.json({
+ status: 400,
+ reason: "\"code\" query not found."
+ }).status(400);
+ }
+
+ try {
+ const req_token = await axios.post("https://id.twitch.tv/oauth2/token", `client_id=${cfg.Auth.ClientID}&client_secret=${cfg.Auth.ClientSecret}&code=${req.query.code}&grant_type=authorization_code&redirect_uri=${cfg.Auth.RedirectURI}`, {headers: {"Content-Type": "application/x-www-form-urlencoded"}});
+
+ const ttv_user = await axios.get("https://api.twitch.tv/helix/users", {
+ responseType: "json",
+ headers: {
+ "Authorization": `Bearer ${req_token.data.access_token}`,
+ "Client-Id": cfg.Auth.ClientID
+ }
+ });
+
+ const user_data = ttv_user.data.data[0];
+
+ const user: User | null = await prisma.user.findFirst({
+ where: {
+ alias_id: parseInt(user_data.id)
+ }
+ });
+
+ const key: string = randomBytes(16).toString("hex");
+ const cookie_opts: CookieOptions = {
+ httpOnly: false,
+ secure: true,
+ sameSite: "lax"
+ };
+
+ if (!user) {
+ await prisma.user.create({
+ data: {
+ alias_id: parseInt(user_data.id),
+ name: user_data.login,
+ desc: user_data.description,
+ pic: user_data.profile_image_url,
+ key: key
+ }
+ });
+
+ res.cookie("key", key, cookie_opts);
+ res.cookie("id", user_data.id, cookie_opts);
+ } else {
+ await prisma.user.update({
+ where: {id: user.id},
+ data: {
+ name: user_data.login,
+ desc: user_data.description,
+ pic: user_data.profile_image_url,
+ key: key
+ }
+ });
+
+ res.cookie("key", key, cookie_opts);
+ res.cookie("id", user_data.id, cookie_opts);
+ }
+
+ res.redirect("/me");
+ } catch (err: any) {
+ res.json({
+ status: (err.response.data.status) ? err.response.data.status : 400,
+ message: (err.response.data.message) ? err.response.data.message : "Bad request."
+ }).status((err.response.data.status) ? err.response.data.status : 400);
+ }
+ });
+
+ return router;
+}
+
+export default AuthRouter; \ No newline at end of file
diff --git a/src/routers/Image.ts b/src/routers/Image.ts
new file mode 100644
index 0000000..dfd6a16
--- /dev/null
+++ b/src/routers/Image.ts
@@ -0,0 +1,107 @@
+// Copyright 2022 NotDankEnough (ilotterytea)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { PrismaClient, User, Image } from "@prisma/client";
+import express from "express";
+import mime from "mime";
+import multer from "../clients/Multer";
+
+function ImageRouter(dirPath: string, cfg: {[key: string]: any}, prisma: PrismaClient): express.Router {
+ const router: express.Router = express.Router();
+
+ router.get("/", async (req, res) => {
+ const user: User | null = await prisma.user.findFirst({
+ where: {
+ alias_id: (req.cookies.id) ? parseInt(req.cookies.id) : null,
+ key: (req.cookies.key) ? req.cookies.key : ""
+ }
+ });
+
+ return res.render("pages/home", {
+ user: user,
+ cid: cfg.Auth.ClientID,
+ uri: cfg.Auth.RedirectURI
+ });
+ });
+
+ router.post("/upload", multer.single("file"), async (req, res) => {
+ const auth: string[] | undefined = (req.headers["authorization"]) ? new Buffer(req.headers["authorization"], "base64").toString("utf-8").split(':') : undefined;
+
+ var user: User | null = await prisma.user.findFirst({
+ where: {
+ alias_id: (auth) ? parseInt(auth[1]) : (req.cookies.id) ? parseInt(req.cookies["id"]) : null,
+ key: (auth) ? auth[2] : (req.cookies.key) ? req.cookies["key"] : ""
+ }
+ });
+
+ const image: Image = await prisma.image.create({
+ data: {
+ storage_id: req.file!.filename!,
+ ext: mime.getExtension(req.file!.mimetype)!,
+ userId: (user) ? user.id : null
+ }
+ });
+
+ return res.send(`https://i.hmmtodayiwill.ru/${image.id}`).status(200);
+ });
+
+
+ router.get("/:imageId", async (req, res) => {
+ const auth: string[] | undefined = (req.headers["authorization"]) ? new Buffer(req.headers["authorization"], "base64").toString("utf-8").split(':') : undefined;
+
+ var user: User | null = await prisma.user.findFirst({
+ where: {
+ alias_id: (auth) ? parseInt(auth[0]) : (req.cookies.id) ? parseInt(req.cookies["id"]) : null,
+ key: (auth) ? auth[1] : (req.cookies.key) ? req.cookies["key"] : ""
+ }
+ });
+
+ const image: Image | null = await prisma.image.findFirst({
+ where: {
+ id: req.params.imageId
+ }
+ });
+
+ if (!image) {
+ return res.json({
+ status: 404,
+ reason: "Image ID " + req.params.imageId + " not found in database!"
+ }).status(404);
+ }
+
+ if (image.is_hidden) {
+ if (user) {
+ if (image.userId !== user.id) {
+ return res.json({
+ status: 401,
+ reason: "Image ID " + req.params.imageId + " have a hide flag."
+ }).status(401);
+ } else {
+ return res.sendFile(`${__dirname}/static/images/${image.storage_id}`);
+ }
+ } else {
+ return res.json({
+ status: 401,
+ reason: "Image ID " + req.params.imageId + " have a hide flag."
+ }).status(401);
+ }
+ }
+
+ return res.sendFile(`${dirPath}/static/images/${image.storage_id}`);
+ });
+
+ return router;
+}
+
+export default ImageRouter; \ No newline at end of file
diff --git a/src/routers/Profile.ts b/src/routers/Profile.ts
new file mode 100644
index 0000000..afc5e5d
--- /dev/null
+++ b/src/routers/Profile.ts
@@ -0,0 +1,58 @@
+// Copyright 2022 NotDankEnough (ilotterytea)
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { PrismaClient, User, Image } from "@prisma/client";
+import { Router } from "express";
+
+function ProfileRouter(dirPath: string, prisma: PrismaClient): Router {
+ const router: Router = Router();
+
+ router.get("/", async (req, res) => {
+ if (!req.cookies.id || !req.cookies.key) {
+ return res.redirect("/");
+ }
+
+ const user: User | null = await prisma.user.findFirst({
+ where: {
+ alias_id: parseInt(req.cookies.id),
+ key: req.cookies.key
+ }
+ });
+
+ if (!user) {
+ return res.redirect("/");
+ }
+
+ var images: Image[] = await prisma.image.findMany({
+ where: {
+ userId: user.id
+ },
+ orderBy: {
+ timestamp: "desc"
+ }
+ });
+
+ const keyNotEncoded: string = `${user.id}:${user.alias_id}:${user.key}`;
+
+ return res.render("pages/me", {
+ user: user,
+ images: images,
+ authKey: Buffer.alloc(keyNotEncoded.length, keyNotEncoded).toString("base64")
+ });
+ });
+
+ return router;
+}
+
+export default ProfileRouter; \ No newline at end of file
diff --git a/static/css/style.css b/static/css/style.css
index bbdd598..ee92164 100644
--- a/static/css/style.css
+++ b/static/css/style.css
@@ -13,114 +13,289 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Manrope:wght@500;600;700&display=swap');
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Manrope:wght@500;600;700&family=SourceCodePro:wght@500,600,700&display=swap');
+ @import url('https://use.fontawesome.com/releases/v6.1.2/css/all.css');
+
:root {
- --bg-color-main: #0f0f0f;
- --text-color: #ddd;
-
- --bg-color-submit-button: #649b44;
- --bg-color-sec-submit-button: #75b450;
- --bg-color-submit-button-na: #555;
- --bg-color-submit-button-na-2: #333;
- --border-color-submit-button: #a5df84;
- --border-color-submit-button-highlight: #d3f3c0;
- --border-color-submit-button-na: #888;
- --text-color-submit-button: #ddd;
- --text-color-submit-button-na: #aaa;
- --text-color-submit-button-highlight: #fff;
-}
-html, body {
+ --text-black: #151515;
+ --text-white: #fff;
+ --button-0: #7aa751;
+ --button-1: #84b458;
+ --button-border: #63a62f;
+ --button-text-shadow: #4c9021;
+ }
+
+ html, body, h1, h2, h3, p {
margin: 0;
padding: 0;
- min-height: 100vh;
-}
-body {
- background: var(--bg-color-main);
- color: var(--text-color);
+ }
+
+ body {
font-family: "Inter", sans-serif;
+ font-size: 14px;
+ background: var(--text-black);
+ color: var(--text-white);
+ }
+
+ h1,h2,h3 {
+ font-family: "Manrope", sans-serif;
+ }
+
+ .container {
+ width: 100%;
+ min-height: 100vh;
display: flex;
- flex-direction: column;
justify-content: center;
align-items: center;
-}
+ }
-.container {
- margin: 0 30px;
+ .wrapper {
display: flex;
- flex-grow: 1;
flex-direction: column;
justify-content: center;
- padding: 40px 0;
-}
+ align-items: center;
+ }
-.content {
- display: flex;
- flex-direction: column;
- justify-content: center;
+ .wrapper section {
+ margin: 8px 0;
+ padding: 8px;
+ min-width: 384px;
+ }
+/* NAVIGATION */
+nav {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ flex-direction: row;
}
-.content section {
- padding: 14px;
-}
-h1,h2,h3 {
- font-family: "Manrope", sans-serif;
+nav a.button img {
+ width: 16px;
+ height: auto;
+ border-radius: 4px;
+ margin-right: 8px;
}
-input[type=submit] {
- background: linear-gradient(0deg, var(--bg-color-sec-submit-button), var(--bg-color-submit-button));
- padding: 2px 12px;
- border-radius: 5px;
- border: 1px solid var(--border-color-submit-button);
- color: var(--text-color-submit-button);
+/* MAIN PAGE */
+section#brand {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
}
-
-input[type=submit]:hover {
- background: linear-gradient(0deg, var(--bg-color-submit-button), var(--bg-color-sec-submit-button));
- border: 1px solid var(--border-color-submit-button-highlight);
- color: var(--text-color-submit-button-highlight);
- cursor: pointer;
+section#brand #logo img {
+ width: 64px;
+ height: 64px;
+ transform: rotate(-45deg);
}
-input[type=submit]:disabled {
- background: linear-gradient(0deg, var(--bg-color-submit-button-na-2), var(--bg-color-submit-button-na));
- color: var(--text-color-submit-button-na);
- border: 1px solid var(--border-color-submit-button-na);
+section#brand #summary {
+ margin: 0 16px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
}
-
-input[type=submit]:disabled:hover {
- cursor: not-allowed;
+section#brand #summary p#name {
+ font-size: 32px;
+ line-height: 0px;
+ margin: 0;
}
-input[type=file]::file-selector-button {
- background: linear-gradient(0deg, var(--bg-color-sec-submit-button), var(--bg-color-submit-button));
- padding: 2px 12px;
- border-radius: 5px;
- border: 1px solid var(--border-color-submit-button);
- color: var(--text-color-submit-button);
+form#uploadform {
+
}
-input[type=file]::file-selector-button:hover {
- background: linear-gradient(0deg, var(--bg-color-submit-button), var(--bg-color-sec-submit-button));
- border: 1px solid var(--border-color-submit-button-highlight);
- color: var(--text-color-submit-button-highlight);
- cursor: pointer;
+form#uploadform button#submit {
+ float:right;
+}
+form#uploadform input[type="file"]::file-selector-button {
+ background: linear-gradient(0deg, var(--button-0), var(--button-1));
+ border: var(--button-border) solid 1px;
+ font-family: "Source Code Pro", monospace;
+ color: var(--text-white);
+ text-shadow: 0 -1px 0 var(--button-text-shadow);
+ text-align: center;
+ text-decoration: none;
+ border-radius: 5px;
+ padding: 2px 6px;
}
-a img:hover {
- opacity: 0.75;
+form#uploadform input[type="file"]::file-selector-button:hover {
+ background: linear-gradient(180deg, var(--button-0), var(--button-1));
+ cursor: pointer;
}
-#i_preview {
- padding: 16px 0;
+/* LINK SECTION */
+.link {
+ display: flex;
+ flex-direction: row;
}
-#preview {
- display: block;
- margin-left: auto;
- margin-right: auto;
+.link #link {
+ background: #ddd;
+ overflow-x: scroll;
+ text-overflow: ellipsis;
+ display: table;
+ margin: 0 auto;
+ max-width: 50%;
}
+ /* ME SECTION */
+ .infoblock {
+ background: linear-gradient(0deg, #000, #222);
+ border: #222 solid 1px;
+ display: flex;
+ flex-direction: column;
+ vertical-align: middle;
+ border-radius: 5px;
+ width: 512px;
+ }
-#footer {
- align-items: center;
+ .infoblock .user_summary {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .summary p#desc {
+ text-align: justify;
+ }
+
+ .summary #name {
+ margin: 12px 0;
+ }
+
+ .infoblock .user_summary div {
+ margin: 5px;
+ }
+
+ .infoblock .user_summary .pfp {
+ display: flex;
justify-content: center;
- justify-items: center;
+ }
+
+ .pfp img {
+ width: auto;
+ height: 64px;
+ border-radius: 5px;
+ }
+
+ .infoblock .action_buttons {
+ display: flex;
+ flex-direction: row-reverse;
+ }
+
+ .infoblock .action_buttons a.button {
+ margin: 0 4px;
+ }
+
+ /* ME/IMAGES SECTION! */
+
+ #images h2#name {
+ padding: 6px;
+ }
+
+ .items {
+ display: flex;
+ flex-direction: column;
+ overflow-y: scroll;
+ max-height: 512px;
+ background: #222;
+ border: #444 solid 1px;
+ border-radius: 4px;
+ }
+
+ .item {
+ background: #525252;
+ border-radius: 4px;
+ padding: 5px;
+ margin: 5px;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .item #info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .item #info div {
+ margin: 5px;
+ }
+
+ .item #info #numeration {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-family: "Manrope", sans-serif;
+ font-weight: 800;
+ font-size: 18px;
+ }
+
+ .item #info #summary {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+
+ .item #info #summary #timestamp {
+ color: #d7ccff;
+ }
+
+ .item #info #thumbnail img {
+ width: 64px;
+ height: auto;
+ }
+
+ .item #info #actions {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-content: center;
+ }
+
+ /* AUTHENTICATION SECTION */
+ .infoblock#authk .action_buttons {
+ display: flex;
+ flex-direction: row;
+ }
+ .infoblock#authk .action_buttons button {
+ flex-grow: 1;
+ margin: 2px;
+ }
+ /* BUTTONS */
+ .button {
+ background: linear-gradient(0deg, var(--button-0), var(--button-1));
+ border: var(--button-border) solid 1px;
+ font-family: "Source Code Pro", monospace;
+ color: var(--text-white);
+ text-shadow: 0 -1px 0 var(--button-text-shadow);
+ text-align: center;
+ text-decoration: none;
+ border-radius: 5px;
+ padding: 2px 6px;
+ }
+
+ .button:hover {
+ background: linear-gradient(180deg, var(--button-0), var(--button-1));
+ cursor: pointer;
+ }
+ .button.twitch {
+ font-family: "Inter", sans-serif;
+ padding: 6px;
+ margin: 8px;
+ vertical-align: middle;
+ display: flex;
+ flex-direction: row;
+ background: linear-gradient(0deg, #5f1481, #821ab3);
+ border: #66158b solid 1px;
+ text-shadow: 0 -1px 0 #691591;
+}
+.button.twitch:hover {
+ background: linear-gradient(180deg, #5f1481, #821ab3);
+}
+
+/* SOON (tm) */
+soontm {
+ color: #444;
+ text-decoration: wavy;
+ font-style: italic;
} \ No newline at end of file
diff --git a/static/ejs/pages/home.ejs b/static/ejs/pages/home.ejs
new file mode 100644
index 0000000..340c563
--- /dev/null
+++ b/static/ejs/pages/home.ejs
@@ -0,0 +1,81 @@
+<!--
+ Copyright 2022 NotDankEnough (ilotterytea)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Picbin</title>
+ <%- include("../partials/meta") %>
+
+ </head>
+ <body>
+ <nav>
+ <% if (!user) {%>
+ <a href="https://id.twitch.tv/oauth2/authorize?response_type=code&redirect_uri=<%= uri %>&client_id=<%= cid %>" class="button twitch">
+ <span class="fa-brands fa-twitch" style="margin-right:8px;"></span>
+ <p>Log in with Twitch</p>
+ </a>
+ <% } else { %>
+ <a href="/me" class="button twitch">
+ <img src="<%= user.pic %>">
+ <p><%= user.name %></p>
+ </a>
+ <button onclick="logout()" class="button twitch">
+ <span class="fa-solid fa-arrow-right-from-bracket"></span>
+ </button>
+ <% } %>
+
+ <a href="https://github.com/notdankenough/picbin" class="button twitch">
+ <span class="fa-brands fa-github"></span>
+ </a>
+ </nav>
+ <div class="container">
+ <div class="wrapper">
+ <section id="brand">
+ <div id="logo">
+ <img src="../img/favicon.png">
+ </div>
+ <div id="summary">
+ <p id="name"><span style="font-weight:800;font-family:'Manrope', sans-serif;">Pic</span>ture<span style="font-weight:800;font-family:'Manrope',sans-serif;">Bin</span></p>
+ </div>
+ </section>
+ <section id="form">
+ <form action="/upload" method="post" id="uploadform">
+ <label>Select file to upload:</label><br>
+ <input accept="image/*" type="file" name="file" id="file">
+ <button type="submit" id="submit" class="button">Upload!</button>
+ </form>
+ </section>
+ </div>
+ </div>
+ </body>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
+ <script src="https://malsup.github.io/jquery.form.js"></script>
+ <script type="text/javascript">
+ function logout() {
+ document.cookie = "id=;Max-Age=-999999";
+ document.cookie = "key=;Max-Age=-999999";
+ window.location.reload();
+ }
+
+ $("#uploadform").ajaxForm({
+ dataType: "text",
+ success: (response) => {
+ window.location.replace(response.split('/')[response.split('/').length - 1]);
+ }
+ });
+ </script>
+</html> \ No newline at end of file
diff --git a/static/ejs/pages/me.ejs b/static/ejs/pages/me.ejs
new file mode 100644
index 0000000..0c69ef5
--- /dev/null
+++ b/static/ejs/pages/me.ejs
@@ -0,0 +1,88 @@
+<!--
+ Copyright 2022 NotDankEnough (ilotterytea)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <title><%= user.name %> - Image Hoster</title>
+ <%- include("../partials/meta") %>
+ </head>
+ <body>
+ <div class="container">
+ <div class="wrapper">
+ <section class="infoblock">
+ <a href="/" class="button">Go back...</a>
+ </section>
+ <section class="infoblock">
+ <div class="user_summary">
+ <div class="pfp">
+ <img src="<%= user.pic %>">
+ </div>
+ <div class="summary">
+ <h2 id="name"><%= user.name%> (<%= user.alias_id %>)</h2>
+ <p id="desc"><%= user.desc %></p>
+ </div>
+ </div>
+ <div class="action_buttons">
+
+ </div>
+ </section>
+ <section class="infoblock" id="authk">
+ <h2 id="name">
+ <span class="fa-solid fa-key"></span> Authentication Key
+ </h2>
+ <p>An authentication key is required if you want to upload images under your account <soontm>and be able to delete them.</soontm></p>
+ <div class="action_buttons">
+ <button value="<%= authKey %>" id="authkey" class="button" onclick="copyAuthkey()">Copy to Clipboard</button>
+ </div>
+ </section>
+ <section class="infoblock">
+ <h2 id="name">
+ Files (<%= images.length %>)
+ </h2>
+ <div class="items">
+ <% images.forEach((image, index) => { %>
+ <div class="item">
+ <div id="info">
+ <div id="numeration">
+ <p><%= index + 1 %></p>
+ </div>
+ <div id="thumbnail">
+ <img src="../images/<%= image.storage_id %>">
+ </div>
+ <div id="summary">
+ <!--<p id="desc"><% if (!image.description) {%> No description provided. <% } else { %> <%= image.description %> <%}%></p>-->
+ <p id="timestamp" title="Timestamp"><span class="fa-solid fa-stamp"></span> <%= image.timestamp %></p>
+ </div>
+ <div id="actions">
+ <a href="/<%= image.id %>" class="button">View</a>
+ </div>
+ </div>
+ </div>
+ <%})%>
+ </div>
+ </section>
+ </div>
+ </div>
+ </body>
+ <script>
+ function copyAuthkey() {
+ var text = document.getElementById("authkey");
+ navigator.clipboard.writeText(text.value);
+ alert("Copied the authentication key!");
+ }
+ </script>
+</html> \ No newline at end of file
diff --git a/static/ejs/partials/bar.ejs b/static/ejs/partials/bar.ejs
new file mode 100644
index 0000000..550d9e2
--- /dev/null
+++ b/static/ejs/partials/bar.ejs
@@ -0,0 +1,7 @@
+<nav>
+ <div class="content">
+ <a href="#">
+ API
+ </a>
+ </div>
+</nav> \ No newline at end of file
diff --git a/static/ejs/partials/meta.ejs b/static/ejs/partials/meta.ejs
new file mode 100644
index 0000000..38aa1df
--- /dev/null
+++ b/static/ejs/partials/meta.ejs
@@ -0,0 +1 @@
+<link rel="stylesheet" href="../css/style.css"> \ No newline at end of file
diff --git a/static/html/index.html b/static/html/index.html
deleted file mode 100644
index 212b1aa..0000000
--- a/static/html/index.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!--
- Copyright 2022 ilotterytea
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!DOCTYPE html>
-<html>
- <head>
- <title>file hoster</title>
- <link rel="stylesheet" href="css/style.css">
- <meta property="og:title" content="iLotterytea's file hoster">
- <meta property="og:description" content="iLotterytea's file hoster. Powered by notdankenough/fh. ">
- <meta property="og:image" content="webimg/favicon.png">
- </head>
- <body>
- <div class="container">
- <div class="content">
- <section id="brand">
- <a href="/">
- <img src="webimg/favicon.png" width="64" title="{{AboutFileHoster}}">
- </a>
- </section>
-
- <section id="uploadform">
- <form action="dank_upload" method="post" enctype="multipart/form-data">
- <p>Select file to upload: </p>
- <input accept="image/*" name="file" id="fileu" type="file" onchange="loadFile(event)">
- <input value="Upload" name="submit" type="submit" id="submitbtn" disabled="true">
- </form>
- </section>
-
- </div>
-
- </div>
- <section id="i_preview">
- <img id="preview" src="#" alt="">
- </section>
-
- </body>
- <script>
- var loadFile = function(event) {
- var out = document.getElementById("preview");
- var btn = document.getElementById("submitbtn");
- out.src = URL.createObjectURL(event.target.files[0]);
- btn.disabled = false;
- out.onload = function() {
- URL.revokeObjectURL(out.src);
- }
- }
- </script>
-</html> \ No newline at end of file
diff --git a/static/webimg/favicon.png b/static/img/favicon.png
index 4b165b8..4b165b8 100644
--- a/static/webimg/favicon.png
+++ b/static/img/favicon.png
Binary files differ
diff --git a/static/img/twitch.png b/static/img/twitch.png
new file mode 100644
index 0000000..d7b64a1
--- /dev/null
+++ b/static/img/twitch.png
Binary files differ
diff --git a/tsconfig.json b/tsconfig.json
index 1b7a608..03dfc11 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -27,7 +27,7 @@
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
- "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
+ "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. */
@@ -35,7 +35,7 @@
// "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. */
+ // "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
@@ -49,7 +49,7 @@
// "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": "./dist", /* Specify an output folder for all emitted files. */
+ "outDir": "./dist", /* 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. */