feat: refactoring and download route

This commit is contained in:
2023-01-28 09:46:36 +01:00
parent f38d8dff22
commit 7dc60fc25e
12 changed files with 416 additions and 87 deletions

View File

@@ -3,5 +3,6 @@
"useTabs": true,
"semi": false,
"singleQuote": false,
"quoteProps": "preserve"
"quoteProps": "preserve",
"tabWidth": 4
}

View File

@@ -1,13 +1,17 @@
FROM node:alpine
COPY . /server
COPY package.json /server
WORKDIR /server
RUN apk add python make gcc g++
RUN npm i
RUN npm i -g typescript
EXPOSE 7272
COPY . /server
CMD tsc --build;node dist/index.js

44
docs/swagger.json Normal file
View File

@@ -0,0 +1,44 @@
{
"swagger": "2.0",
"info": {
"title": "Sr Izan API",
"description": "Image recognition stuff for now lol",
"version": "1.0.0"
},
"host": "api.srizan.ml",
"basePath": "/",
"schemes": [
"https"
],
"paths": {
"/misc/download": {
"get": {
"summary": "Download images from a URL",
"parameters": [
{
"in": "query",
"name": "url",
"type": "string",
"required": true,
"description": "The URL (https and stuff)"
},
{
"in": "query",
"name": "type",
"type": "string",
"required": true,
"description": "The file type (png, jpg, jpeg or gif)"
}
],
"responses": {
"200": {
"description": "Success"
},
"400": {
"description": "Bad Request"
}
}
}
}
}
}

118
index.ts
View File

@@ -1,100 +1,56 @@
import mongoose from "mongoose"
import express from "express"
const app = express()
import * as dotenv from "dotenv"
dotenv.config()
import sernTime from "./schemas/sern-time.js"
import 'dotenv/config'
import bodyParser from "body-parser"
import rateLimit from "express-rate-limit"
import { consolelogTime } from "./util/consolelogTime.js"
app.use(bodyParser.json())
app.disable("x-powered-by")
const limiter = rateLimit({
windowMs: 1 * 60 * 1000,
max: 30,
message: { error: "You just got ratelimited." },
standardHeaders: true,
legacyHeaders: false,
})
app.use(limiter)
import swagger from './docs/swagger.json' assert { type: 'json' }
import swaggerUI from 'swagger-ui-express'
/* Mongoose */
await mongoose.connect(`${process.env.MONGODB}`).then(() => {
consolelogTime(`Connected to MongoDB!`)
})
app.post("/sern/newTime", async (req, res, next) => {
if (
req.body.timezone &&
req.body.key === process.env.SERN_TIME &&
req.body.userid
) {
sernTime.exists({ userid: req.body.userid }, function (err, doc) {
if (err) throw err
if (doc) {
res.status(400).json({ "error": "You already created a timezone!" })
} else {
if (doc) {
res
.status(400)
.json({ "error": "User already exists in the database." })
} else {
const saveToDB = new sernTime({
timezone: req.body.timezone,
userid: req.body.userid,
})
saveToDB.save()
res.json({ "ok": "you were added successfully!" })
}
}
})
} else {
res.status(400).json({
"error": "make sure you have the right params.",
})
}
/* Express configuration */
const app = express()
const limiter = rateLimit({
windowMs: 1 * 60 * 1000,
max: 10,
message: { error: "You just got ratelimited." },
standardHeaders: true,
})
app.use(bodyParser.json())
app.use('/docs', swaggerUI.serve, swaggerUI.setup(swagger));
app.use(express.static('public'))
app.disable("x-powered-by")
/* All route imports */
import newTime from "./routes/sern/newTime.js"
import getTime from "./routes/sern/getTime.js"
import deleteTime from "./routes/sern/deleteTime.js"
import download from "./routes/misc/download.js"
app.use("/sern/newTime", limiter)
app.post("/sern/newTime", async (req, res) => {
newTime(req, res)
})
app.get("/sern/getTime", async (req, res, next) => {
if (req.query.userid) {
sernTime.exists({ userid: req.query.userid }, async function (err, doc) {
if (err) throw err
if (doc) {
const timezone = (await sernTime.findOne({ userid: req.query.userid }))?.timezone
res.json({"timezone": timezone})
} else {
res.status(400).json({
"error": "you don't exist in the database",
})
}
})
} else {
res.status(400).json({
"error": "make sure you have the userid param",
})
}
app.use("/sern/getTime", limiter)
app.get("/sern/getTime", async (req, res) => {
getTime(req, res)
})
app.use("/sern/newTime", limiter)
app.delete("/sern/deleteTime", async (req, res) => {
if (req.query.userid && req.query.key === process.env.SERN_TIME) {
sernTime.exists({ userid: req.query.userid }, async function (err, doc) {
if (err) throw err
if (doc) {
const timezone = await sernTime.findOne({ userid: req.query.userid })
await timezone!.delete()
res.json({"ok": "done"})
} else {
res.status(400).json({
"error": "the user doesn't exist",
})
}
})
} else {
res.status(400).json({
"error": "make sure you have the userid param and the right key",
})
}
deleteTime(req, res)
})
app.use("/misc/download", limiter)
app.get("/misc/download", async (req, res) => {
download(req, res)
})
app.listen(7272, () => {
consolelogTime(`listening`)
consolelogTime(`Listening`)
})

178
package-lock.json generated
View File

@@ -9,13 +9,16 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"axios": "^1.2.3",
"dotenv": "^16.0.3",
"express": "^4.18.1",
"express-rate-limit": "^6.6.0",
"mongoose": "^6.6.5"
"mongoose": "^6.6.5",
"swagger-ui-express": "^4.6.0"
},
"devDependencies": {
"@types/express": "^4.17.14",
"@types/swagger-ui-express": "^4.1.3",
"typescript": "^4.8.4"
}
},
@@ -94,6 +97,16 @@
"@types/node": "*"
}
},
"node_modules/@types/swagger-ui-express": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz",
"integrity": "sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==",
"dev": true,
"dependencies": {
"@types/express": "*",
"@types/serve-static": "*"
}
},
"node_modules/@types/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@@ -125,6 +138,34 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.3.tgz",
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/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/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -221,6 +262,17 @@
"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/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -261,6 +313,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/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
@@ -389,6 +449,25 @@
"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/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -719,6 +798,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -903,6 +987,25 @@
"node": ">= 0.8"
}
},
"node_modules/swagger-ui-dist": {
"version": "4.15.5",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.5.tgz",
"integrity": "sha512-V3eIa28lwB6gg7/wfNvAbjwJYmDXy1Jo1POjyTzlB6wPcHiGlRxq39TSjYGVjQrUSAzpv+a7nzp7mDxgNy57xA=="
},
"node_modules/swagger-ui-express": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.0.tgz",
"integrity": "sha512-ZxpQFp1JR2RF8Ar++CyJzEDdvufa08ujNUJgMVTMWPi86CuQeVdBtvaeO/ysrz6dJAYXf9kbVNhWD7JWocwqsA==",
"dependencies": {
"swagger-ui-dist": ">=4.11.0"
},
"engines": {
"node": ">= v0.10.32"
},
"peerDependencies": {
"express": ">=4.0.0"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -1068,6 +1171,16 @@
"@types/node": "*"
}
},
"@types/swagger-ui-express": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz",
"integrity": "sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==",
"dev": true,
"requires": {
"@types/express": "*",
"@types/serve-static": "*"
}
},
"@types/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@@ -1096,6 +1209,33 @@
"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": "1.2.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.3.tgz",
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
},
"dependencies": {
"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"
}
}
}
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -1151,6 +1291,14 @@
"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"
}
},
"content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -1182,6 +1330,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=="
},
"denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
@@ -1280,6 +1433,11 @@
"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=="
},
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -1514,6 +1672,11 @@
"ipaddr.js": "1.9.1"
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -1648,6 +1811,19 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
},
"swagger-ui-dist": {
"version": "4.15.5",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.5.tgz",
"integrity": "sha512-V3eIa28lwB6gg7/wfNvAbjwJYmDXy1Jo1POjyTzlB6wPcHiGlRxq39TSjYGVjQrUSAzpv+a7nzp7mDxgNy57xA=="
},
"swagger-ui-express": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.0.tgz",
"integrity": "sha512-ZxpQFp1JR2RF8Ar++CyJzEDdvufa08ujNUJgMVTMWPi86CuQeVdBtvaeO/ysrz6dJAYXf9kbVNhWD7JWocwqsA==",
"requires": {
"swagger-ui-dist": ">=4.11.0"
}
},
"toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",

View File

@@ -5,7 +5,8 @@
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "tsc-watch --onSuccess \"node dist/index.js\""
},
"repository": {
"type": "git",
@@ -18,13 +19,16 @@
},
"homepage": "https://github.com/SrIzan10/api#readme",
"dependencies": {
"axios": "^1.2.3",
"dotenv": "^16.0.3",
"express": "^4.18.1",
"express-rate-limit": "^6.6.0",
"mongoose": "^6.6.5"
"mongoose": "^6.6.5",
"swagger-ui-express": "^4.6.0"
},
"devDependencies": {
"@types/express": "^4.17.14",
"@types/swagger-ui-express": "^4.1.3",
"typescript": "^4.8.4"
}
}

13
public/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sr Izan's API</title>
</head>
<body>
<h1>hi this is my shitty api tbh</h1>
<a href="docs/">really bad docs</a>
</body>
</html>

52
routes/misc/download.ts Normal file
View File

@@ -0,0 +1,52 @@
import axios from "axios"
import { Request, Response } from "express"
export default async function download(req: Request, res: Response) {
const url = req.query.url as string
const filetype = req.query.type as string
function typeResolver(filetype: string) {
switch (filetype) {
case "png":
return {
success: true,
extension: "png",
contentType: "image/png",
}
case "jpg" || "jpeg":
return {
success: true,
extension: "jpg",
contentType: "image/jpeg",
}
case "gif":
return {
success: true,
extension: "gif",
contentType: "image/gif",
}
default:
return {
success: false,
extension: "idk",
contentType: "idk/idk",
}
}
}
try {
const fileTypeResolved = typeResolver(filetype)
if (!fileTypeResolved.success)
return res.status(400).send({ error: 'Image needs to be either png, jpg or gif' })
const response = await axios.get(url, { responseType: "stream" })
res.set({
"Content-Disposition": `attachment; filename=download.${fileTypeResolved.extension}`,
"Content-Type": fileTypeResolved.contentType,
})
response.data.pipe(res)
} catch (error) {
console.error(error)
res.status(400).send({ error: 'File not found' })
}
}

23
routes/sern/deleteTime.ts Normal file
View File

@@ -0,0 +1,23 @@
import sernTime from "../../schemas/sern-time.js"
import { Request, Response } from "express"
export default async function deleteTime(req: Request, res: Response) {
if (req.query.userid && req.query.key === process.env.SERN_TIME) {
sernTime.exists({ userid: req.query.userid }, async function (err, doc) {
if (err) throw err
if (doc) {
const timezone = await sernTime.findOne({ userid: req.query.userid })
await timezone!.delete()
res.json({"ok": "done"})
} else {
res.status(400).json({
"error": "the user doesn't exist",
})
}
})
} else {
res.status(400).json({
"error": "make sure you have the userid param and the right key",
})
}
}

22
routes/sern/getTime.ts Normal file
View File

@@ -0,0 +1,22 @@
import sernTime from "../../schemas/sern-time.js"
import { Request, Response } from "express"
export default async function getTime(req: Request, res: Response) {
if (req.query.userid) {
sernTime.exists({ userid: req.query.userid }, async function (err, doc) {
if (err) throw err
if (doc) {
const timezone = (await sernTime.findOne({ userid: req.query.userid }))?.timezone
res.json({"timezone": timezone})
} else {
res.status(400).json({
"error": "you don't exist in the database",
})
}
})
} else {
res.status(400).json({
"error": "make sure you have the userid param",
})
}
}

34
routes/sern/newTime.ts Normal file
View File

@@ -0,0 +1,34 @@
import sernTime from "../../schemas/sern-time.js"
import { Request, Response } from "express"
export default async function newTime(req: Request, res: Response) {
if (
req.body.timezone &&
req.body.key === process.env.SERN_TIME &&
req.body.userid
) {
sernTime.exists({ userid: req.body.userid }, function (err, doc) {
if (err) throw err
if (doc) {
res.status(400).json({ "error": "You already created a timezone!" })
} else {
if (doc) {
res
.status(400)
.json({ "error": "User already exists in the database." })
} else {
const saveToDB = new sernTime({
timezone: req.body.timezone,
userid: req.body.userid,
})
saveToDB.save()
res.json({ "ok": "you were added successfully!" })
}
}
})
} else {
res.status(400).json({
"error": "make sure you have the right params.",
})
}
}

View File

@@ -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 */