initialize redoc
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "legica-dana",
|
"name": "legica-dana",
|
||||||
"version": "0.7.0",
|
"version": "0.7.5",
|
||||||
"main": "src/app.ts",
|
"main": "src/app.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "bun src/app.ts"
|
"start": "bun src/app.ts"
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-basic-auth": "^1.2.1",
|
"express-basic-auth": "^1.2.1",
|
||||||
|
"redoc-express": "^2.1.0",
|
||||||
"typescript": "^4.1.5"
|
"typescript": "^4.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
48
src/app.ts
48
src/app.ts
@@ -3,9 +3,10 @@ import { Chat } from "@common";
|
|||||||
import { Controller } from "@core";
|
import { Controller } from "@core";
|
||||||
import { ClientController } from "@controllers";
|
import { ClientController } from "@controllers";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { config } from "@constants";
|
import { APP_VERSION, config } from "@constants";
|
||||||
import basicAuth from "express-basic-auth";
|
|
||||||
import bodyParser from "body-parser";
|
import bodyParser from "body-parser";
|
||||||
|
import redoc from "redoc-express";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
const client: Client = new Client();
|
const client: Client = new Client();
|
||||||
const chat: Chat = new Chat(client);
|
const chat: Chat = new Chat(client);
|
||||||
@@ -13,16 +14,47 @@ const app = express();
|
|||||||
|
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
app.use(
|
app.get("/docs/swagger.json", (req, res) => {
|
||||||
basicAuth({
|
res.sendFile("swagger.json", { root: path.join(__dirname, "..") });
|
||||||
users: {
|
});
|
||||||
admin: config.PASSWORD,
|
app.get(
|
||||||
|
"/docs",
|
||||||
|
redoc({
|
||||||
|
title: "API Docs",
|
||||||
|
specUrl: "/docs/swagger.json",
|
||||||
|
nonce: "",
|
||||||
|
redocOptions: {
|
||||||
|
theme: {
|
||||||
|
colors: {
|
||||||
|
primary: {
|
||||||
|
main: "#6EC5AB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
fontFamily: `"museo-sans", 'Helvetica Neue', Helvetica, Arial, sans-serif`,
|
||||||
|
fontSize: "15px",
|
||||||
|
lineHeight: "1.5",
|
||||||
|
code: {
|
||||||
|
code: "#87E8C7",
|
||||||
|
backgroundColor: "#4D4D4E",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
backgroundColor: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const controllers = new Controller([new ClientController(client, app)]);
|
app.get("version", (_, res) => {
|
||||||
|
res.send(APP_VERSION);
|
||||||
|
});
|
||||||
|
|
||||||
|
const controllers = new Controller(app, [new ClientController(client)]);
|
||||||
|
|
||||||
controllers.register();
|
controllers.register();
|
||||||
chat.register(config.TOKEN || "");
|
chat.register(config.TOKEN || "");
|
||||||
app.listen(config.PORT);
|
app.listen(config.PORT, () =>
|
||||||
|
console.log(`Legica bot API listening on port ${config.PORT}!`)
|
||||||
|
);
|
||||||
|
|||||||
@@ -2,13 +2,15 @@ import { Client, MessageEmbed, TextChannel } from "discord.js";
|
|||||||
import * as cron from "cron";
|
import * as cron from "cron";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import cheerio from "cheerio";
|
import cheerio from "cheerio";
|
||||||
import { Express } from "express";
|
import { Router } from "express";
|
||||||
import { IController, Legica } from "@models";
|
import { IController, Legica } from "@models";
|
||||||
import { APP_VERSION, config } from "@constants";
|
import { config } from "@constants";
|
||||||
|
import basicAuth from "express-basic-auth";
|
||||||
|
|
||||||
class ClientController implements IController {
|
class ClientController implements IController {
|
||||||
private legicaTask: cron.CronJob | null = null;
|
private legicaTask: cron.CronJob | null = null;
|
||||||
constructor(private client: Client, private app: Express) {}
|
public path: string = "task";
|
||||||
|
constructor(private client: Client) {}
|
||||||
|
|
||||||
public register = (): void => {
|
public register = (): void => {
|
||||||
this.client.on("ready", (): void => {
|
this.client.on("ready", (): void => {
|
||||||
@@ -20,24 +22,30 @@ class ClientController implements IController {
|
|||||||
"utc"
|
"utc"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.app.get("", (_, res) => {
|
public registerRouter = (): Router => {
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.use(
|
||||||
|
basicAuth({
|
||||||
|
users: {
|
||||||
|
admin: config.PASSWORD,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
router.get("", (_, res) => {
|
||||||
res.send(this.legicaTask?.running);
|
res.send(this.legicaTask?.running);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.app.get("/next", (_, res) => {
|
router.get("next", (_, res) => {
|
||||||
if (!this.legicaTask?.running) {
|
if (!this.legicaTask?.running) {
|
||||||
res.status(400).send("Task is not running.");
|
res.status(400).send("Task is not running.");
|
||||||
} else {
|
} else {
|
||||||
res.send(this.legicaTask.nextDate().toISO());
|
res.send(this.legicaTask.nextDate().toISO());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
router.post("", (_, res) => {
|
||||||
this.app.get("/version", (_, res) => {
|
|
||||||
res.send(APP_VERSION);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.app.post("/start", (_, res) => {
|
|
||||||
if (this.legicaTask?.running) {
|
if (this.legicaTask?.running) {
|
||||||
res.status(400).send("Task already running.");
|
res.status(400).send("Task already running.");
|
||||||
} else {
|
} else {
|
||||||
@@ -45,8 +53,7 @@ class ClientController implements IController {
|
|||||||
res.send("Task started.");
|
res.send("Task started.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
router.delete("", (_, res) => {
|
||||||
this.app.post("/stop", (_, res) => {
|
|
||||||
if (!this.legicaTask?.running) {
|
if (!this.legicaTask?.running) {
|
||||||
res.status(400).send("Task already stopped.");
|
res.status(400).send("Task already stopped.");
|
||||||
} else {
|
} else {
|
||||||
@@ -55,7 +62,7 @@ class ClientController implements IController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.app.post("/post-next", async (_, res) => {
|
router.post("send-latest", async (_, res) => {
|
||||||
try {
|
try {
|
||||||
await this.sendNextMessage();
|
await this.sendNextMessage();
|
||||||
res.send(true);
|
res.send(true);
|
||||||
@@ -64,7 +71,7 @@ class ClientController implements IController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.app.post("/post", async (req, res) => {
|
router.post("send", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const url = req.body.url;
|
const url = req.body.url;
|
||||||
await this.sendMessage(url);
|
await this.sendMessage(url);
|
||||||
@@ -73,6 +80,7 @@ class ClientController implements IController {
|
|||||||
res.status(400).send(err);
|
res.status(400).send(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return router;
|
||||||
};
|
};
|
||||||
|
|
||||||
private sendNextMessage = async (): Promise<void> => {
|
private sendNextMessage = async (): Promise<void> => {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { IController } from "models";
|
import { IController } from "models";
|
||||||
|
import { Express } from "express";
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor(private controllers: IController[]) {}
|
constructor(private app: Express, private controllers: IController[]) {}
|
||||||
|
|
||||||
public register = (): void => {
|
public register = (): void => {
|
||||||
this.controllers?.forEach((controller) => {
|
this.controllers?.forEach((controller) => {
|
||||||
controller.register();
|
controller.register();
|
||||||
|
this.app.use(controller.path || "", controller.registerRouter());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import { Router } from "express";
|
||||||
|
|
||||||
export interface IController {
|
export interface IController {
|
||||||
register(): void;
|
register(): void;
|
||||||
|
registerRouter(): Router;
|
||||||
|
path: string;
|
||||||
}
|
}
|
||||||
|
|||||||
154
swagger.json
Normal file
154
swagger.json
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.3",
|
||||||
|
"info": {
|
||||||
|
"title": "Legica Bot API",
|
||||||
|
"license": {
|
||||||
|
"name": "Apache 2.0",
|
||||||
|
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||||
|
},
|
||||||
|
"version": "0.7.0"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"name": "api",
|
||||||
|
"description": "API information"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "task",
|
||||||
|
"description": "Everything about the task"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/version": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"api"
|
||||||
|
],
|
||||||
|
"summary": "Display current API version.",
|
||||||
|
"description": "Displays the current API version defined in package.json.",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful operation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/task": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Check if task is running.",
|
||||||
|
"description": "Retrieve the current state of scheduled task.",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful operation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Start task if it is not running.",
|
||||||
|
"description": "Starts the task if it is not currently running.",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Task started."
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Task already running."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Stop task if it is running.",
|
||||||
|
"description": "Stops the task if it is currently running.",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Task stopped."
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Task already stopped."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/task/next": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Check when the task is scheduled due next.",
|
||||||
|
"description": "Retrieve the datetime when task is scheduled to execute.",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Next datetime"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Task is not running."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/task/send-latest": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Send latest post of legica dana.",
|
||||||
|
"description": "Sends latest post of legica dana to all discord channels.",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Confirmation."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/task/send": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Send post of legica dana.",
|
||||||
|
"description": "Sends provided post of legica dana to all discord channels.",
|
||||||
|
"requestBody": {
|
||||||
|
"description": "URL",
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Legica"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Confirmation."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Legica": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "string",
|
||||||
|
"example": "https://sib.net.hr/legica-dana/4390659/legica-dana-2992023/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xml": {
|
||||||
|
"name": "order"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user