Skip to content

Commit

Permalink
feat: add proper error handling, fix the logger
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDogHusky committed Oct 2, 2024
1 parent 00994da commit 03914d9
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 188 deletions.
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nekonya-storage",
"version": "2.0.5",
"version": "2.1.5",
"description": "The API of NekoNya.",
"main": "src/index.ts",
"scripts": {
Expand All @@ -16,12 +16,17 @@
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"express-validator": "^7.1.0",
"on-finished": "^2.4.1",
"on-headers": "^1.0.2",
"tsx": "^4.16.2"
},
"devDependencies": {
"@types/cors": "^2.8.13",
"@types/express": "^4.17.17",
"@types/on-finished": "^2.3.4",
"@types/on-headers": "^1.0.3",
"typescript": "^4.9.5"
}
}
3 changes: 2 additions & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'fs';
import {Router} from 'express';
import {Logger} from "@classycrafter/super-logger";
import { basename } from 'path';

export default (logger: Logger) => {
const router = Router();
Expand All @@ -14,7 +15,7 @@ export default (logger: Logger) => {
});

fs.readdirSync(__dirname).forEach(dir => {
if(dir === 'index.ts') return;
if(dir === basename(__filename)) return;
const route = require('./' + dir).default(logger);
router.use(`/${dir}/`, route);
logger.info(`Loaded API version ${dir}`, "API");
Expand Down
31 changes: 22 additions & 9 deletions src/api/v1/8ball.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Router, Request, Response } from 'express';
import {Router, Request, Response, NextFunction} from 'express';
const router = Router();
import { eightballValidator } from "../../utils";
import { APIRouteInfos, eightballValidator } from "../../utils";
import { matchedData, validationResult } from "express-validator";
import { ValidationError } from "../../structures/errors";

const eightballAnswers = [
"It is certain",
Expand Down Expand Up @@ -55,15 +56,11 @@ const cuteEightballAnswers = [
"Very doubtfwul!"
];

router.get('/', eightballValidator, (req: Request, res: Response) => {
router.get('/', eightballValidator, async (req: Request, res: Response, next: NextFunction) => {
const results = validationResult(req);
if(!results.isEmpty()) return res.status(400).json({
message: 'Validation failed',
errors: results.array()
});
if(!results.isEmpty()) throw new ValidationError(results.array());

const data = matchedData(req);

const cute = data.cute || false;
const answers = cute ? cuteEightballAnswers : eightballAnswers;
const answer = answers[Math.floor(Math.random() * answers.length)];
Expand All @@ -73,4 +70,20 @@ router.get('/', eightballValidator, (req: Request, res: Response) => {
});
});

export default router;
export default router;
export const infos: APIRouteInfos = {
name: "8ball",
description: "Get a random 8ball response",
path: "/8ball",
methods: ["GET"],
parameters: [],
queries: [
{
name: "cute",
description: "If you want the response to be cute",
required: false,
type: "boolean"
}
],
body: []
};
82 changes: 21 additions & 61 deletions src/api/v1/endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,27 @@
import { Router } from 'express';
const router = Router();
import { APIRouteInfos } from "../../utils";
import fs from "fs";
import path from "path";

const routeInfos: APIRouteInfos[] = [];
const files = fs.readdirSync(__dirname).filter(file => file !== path.basename(__filename) && file !== "index.ts" && file !== "index.js");
for (const file of files) {
const infos = require('./' + file).infos;
routeInfos.push(infos);
}

router.get("/", (req, res) => {
res.status(200).json([
{
"name": "random",
"description": "Get random images",
"path": "/random",
"methods": ["GET"],
"parameters": [
{
"name": "type",
"description": "Type of image",
"required": true,
"type": "string",
"values": ["neko", "kitsune", "pat", "kisse", "hug", "lewd", "slap"]
}
],
"queries": [],
"body": []
},
{
"name": "8ball",
"description": "Get a random 8ball response",
"path": "/8ball",
"methods": ["GET"],
"parameters": [],
"queries": [
{
"name": "cute",
"description": "If you want the response to be cute",
"required": false,
"type": "boolean"
}
],
"body": []
},
{
"name": "owoify",
"description": "Owoify text (make it cute)",
"path": "/owoify",
"methods": ["GET", "POST"],
"parameters": [],
"queries": [
{
"name": "text",
"description": "Text to owoify",
"required": true,
"type": "string"
}
],
"body": [
{
"name": "text",
"description": "Text to owoify",
"required": true,
"type": "string",
"max_length": 2000,
"min_length": 1
}
]
}
]);
res.status(200).json(routeInfos);
});

export default router;
export default router;
export const infos: APIRouteInfos = {
name: "endpoints",
description: "Get all available endpoints",
path: "/endpoints",
methods: ["GET"],
parameters: [],
queries: [],
body: []
};
12 changes: 6 additions & 6 deletions src/api/v1/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs';
import path from 'path';
import {Router} from 'express';
import {Logger} from "@classycrafter/super-logger";
import { Router } from 'express';
import { Logger } from "@classycrafter/super-logger";

const router = Router();
router.get('/', (req, res) => {
Expand All @@ -14,12 +14,12 @@ router.get('/', (req, res) => {
});

export default (logger: Logger) => {
const files = fs.readdirSync(__dirname).filter(file => file !== path.basename(__filename));
const files = fs.readdirSync(__dirname).filter(file => file !== path.basename(path.basename(__filename)));
for (const file of files) {
const route = require('./' + file).default;
const fileName = file.replace('.ts', '');
router.use(`/${fileName}`, route);
logger.info(`Loaded route /api/v1/${fileName}`, "API");
const infos = require('./' + file).infos;
router.use(`/${infos.name}`, route);
logger.info(`Loaded route /api/v1/${infos.name}`, "API");
}

return router;
Expand Down
79 changes: 35 additions & 44 deletions src/api/v1/owoify.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { Router } from 'express';
import { NextFunction, Router } from 'express';
const router = Router();
import { owoifyGetValidator, owoifyPostValidator } from "../../utils";
import { APIRouteInfos, owoifyGetValidator, owoifyPostValidator } from "../../utils";
import { Request, Response } from 'express';
import { matchedData, validationResult } from "express-validator";
import { BadRequestError, ValidationError } from "../../structures/errors";

router.get('/', owoifyGetValidator, (req: Request, res: Response) => {
async function middleware(req: Request, res: Response, next: NextFunction) {
const results = validationResult(req);
if(!results.isEmpty()) return res.status(400).json({
message: 'Validation failed',
errors: results.array()
});
if(!results.isEmpty()) throw new ValidationError(results.array());

const text: string | undefined = matchedData(req).text as string | undefined;
if(!text) return res.status(400).json({
error: {
status: 400,
message: 'Missing text'
}
});
if(!text) throw new BadRequestError("Missing text");

const owoified = text.replace(/(?:r|l)/g, "w")
.replace(/(?:R|L)/g, "W")
Expand All @@ -28,36 +21,34 @@ router.get('/', owoifyGetValidator, (req: Request, res: Response) => {
.replace(/!+/g, " " + "owo");

res.status(200).json({
"result": owoified
});
});

router.post('/', owoifyPostValidator, (req: Request, res: Response) => {
const results = validationResult(req);
if(!results.isEmpty()) return res.status(400).json({
message: 'Validation failed',
errors: results.array()
result: owoified
});

const text: string | undefined = matchedData(req).text as string | undefined;
if(!text) return res.status(400).json({
error: {
status: 400,
message: 'Missing text'
}

router.get('/', owoifyGetValidator, middleware);
router.post('/', owoifyPostValidator, middleware);

export default router;
export const infos: APIRouteInfos = {
name: "owoify",
description: "Make your text cute",
path: "/owoify",
methods: ["GET"],
parameters: [],
queries: [
{
name: "text",
description: "The text you want to make cute",
required: false,
type: "string"
}
});

const owoified = text.replace(/(?:r|l)/g, "w")
.replace(/(?:R|L)/g, "W")
.replace(/n([aeiou])/g, 'ny$1')
.replace(/N([aeiou])/g, 'Ny$1')
.replace(/N([AEIOU])/g, 'Ny$1')
.replace(/ove/g, "uv")
.replace(/!+/g, " " + "owo");

res.status(200).json({
"result": owoified
});
});

export default router;
],
body: [
{
name: "text",
description: "The text you want to make cute",
required: false,
type: "string"
}
]
};
53 changes: 28 additions & 25 deletions src/api/v1/random.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
import { Router } from 'express';
const router = Router();
import fs from 'fs';
import { getBaseURL } from "../../utils";
import fs from 'fs/promises';
import { APIRouteInfos, formatType, getBaseURL } from "../../utils";
import { BadRequestError } from "../../structures/errors";

router.get("/", (req, res) => {
res.redirect("/api/v1/random/neko");
});

router.get('/:type', (req, res) => {
router.get('/:type', async (req, res, next) => {
const type = req.params.type;
const types = ['neko', 'kitsune', 'pat', 'kiss', 'hug', 'lewd', 'slap'];
if (!types.includes(type)) throw new BadRequestError("Invalid Type");

const types = ['all', 'neko', 'kitsune', 'pat', 'kiss', 'hug', 'lewd', 'slap'];
if(!types.includes(type)) return res.status(400).json({
status: 400,
error: 'Bad Request',
message: 'Invalid type'
});

let files: string[] = [];
const scanType = type === 'kiss' ? 'kisses' : type + 's';

if(type === 'all') {
for (const type of types) {
if(type === 'all') continue;
const scanType = type === 'kiss' ? 'kisses' : type + 's';
const dirFiles = fs.readdirSync(`./images/${scanType}`);
files.push(...dirFiles);
}
}
else files = fs.readdirSync(`./images/${scanType}`);

const scanType = formatType(type);
let files: string[] = await fs.readdir(`./images/${scanType}`);
const image = files[Math.floor(Math.random() * files.length)];

return res.status(200).json({
"url": getBaseURL(req) + "/images/" + scanType + "/" + image
url: getBaseURL(req) + "/images/" + scanType + "/" + image
});
});

export default router;
export default router;
export const infos: APIRouteInfos = {
name: "random",
description: "Get a random image",
path: "/random",
methods: ["GET"],
parameters: [
{
name: "type",
description: "The type of image",
required: true,
type: "string",
values: ["neko", "kitsune", "pat", "kiss", "hug", "lewd", "slap"]
}
],
queries: [],
body: []
};
Loading

0 comments on commit 03914d9

Please sign in to comment.