Spaces:
Sleeping
Sleeping
elsamueldev
commited on
Commit
•
e1dafe2
1
Parent(s):
aae7b59
Upload 6 files
Browse files- Dockerfile +11 -0
- app.js +37 -0
- discord-webhook.js +74 -0
- package.json +23 -0
- schemas.js +22 -0
- server.js +15 -0
Dockerfile
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM node:20
|
2 |
+
|
3 |
+
WORKDIR /app
|
4 |
+
|
5 |
+
COPY package.json ./
|
6 |
+
|
7 |
+
RUN npm install
|
8 |
+
|
9 |
+
COPY . .
|
10 |
+
|
11 |
+
CMD ["node", "index.js"]
|
app.js
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import express from 'express';
|
2 |
+
import cors from 'cors';
|
3 |
+
|
4 |
+
import { DiscordWebhook } from './discord-webhook.js';
|
5 |
+
import { messageSchema } from './schemas.js';
|
6 |
+
|
7 |
+
|
8 |
+
/**
|
9 |
+
*
|
10 |
+
* @param {DiscordWebhook} discordWebhook
|
11 |
+
* @returns {express.Express}
|
12 |
+
*/
|
13 |
+
export function createApp(discordWebhook) {
|
14 |
+
const app = express();
|
15 |
+
app.disable('x-powered-by');
|
16 |
+
app.use(express.json());
|
17 |
+
app.use(cors());
|
18 |
+
|
19 |
+
app.post('/submit', async (req, res) => {
|
20 |
+
const result = messageSchema.safeParse(req.body);
|
21 |
+
if (!result.success) {
|
22 |
+
res.status(400).send(result.error.message);
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
const sent = await discordWebhook.sendEmbed(result.data);
|
27 |
+
|
28 |
+
if (!sent) {
|
29 |
+
res.status(500).send('Tu mensaje no se ha podido guardar');
|
30 |
+
return;
|
31 |
+
}
|
32 |
+
|
33 |
+
res.status(201).send('va');
|
34 |
+
});
|
35 |
+
|
36 |
+
return app;
|
37 |
+
}
|
discord-webhook.js
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { urlSchema } from "./schemas.js";
|
2 |
+
|
3 |
+
|
4 |
+
export class DiscordWebhook {
|
5 |
+
#url;
|
6 |
+
|
7 |
+
constructor(url) {
|
8 |
+
this.#url = urlSchema.parse(url);
|
9 |
+
}
|
10 |
+
|
11 |
+
|
12 |
+
/**
|
13 |
+
*
|
14 |
+
* @param {object} payload
|
15 |
+
* @returns {boolean}
|
16 |
+
*/
|
17 |
+
#sendPayload = async (payload) => {
|
18 |
+
const response = await fetch(this.#url, {
|
19 |
+
method: 'POST',
|
20 |
+
body: JSON.stringify(payload),
|
21 |
+
headers: {
|
22 |
+
'Content-Type': 'application/json'
|
23 |
+
}
|
24 |
+
});
|
25 |
+
|
26 |
+
const sent = response.status === 204;
|
27 |
+
|
28 |
+
if (!sent) {
|
29 |
+
console.error(await response.text());
|
30 |
+
}
|
31 |
+
|
32 |
+
return sent;
|
33 |
+
};
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @param {string} content
|
37 |
+
* @returns {Promise<boolean>}
|
38 |
+
*/
|
39 |
+
async sendPlainText(content) {
|
40 |
+
const payload = {
|
41 |
+
content
|
42 |
+
};
|
43 |
+
|
44 |
+
return this.#sendPayload(payload);
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
*
|
49 |
+
* @param {object} content
|
50 |
+
* @returns {Promise<boolean>}
|
51 |
+
*/
|
52 |
+
async sendEmbed(content) {
|
53 |
+
const fields = [];
|
54 |
+
|
55 |
+
for (const [label, value] of Object.entries(content)) {
|
56 |
+
const field = {
|
57 |
+
name: label,
|
58 |
+
value: value
|
59 |
+
};
|
60 |
+
fields.push(field);
|
61 |
+
}
|
62 |
+
|
63 |
+
const embed = {
|
64 |
+
title: "Nuevo mensaje",
|
65 |
+
fields
|
66 |
+
};
|
67 |
+
|
68 |
+
const payload = {
|
69 |
+
embeds: [embed]
|
70 |
+
};
|
71 |
+
|
72 |
+
return this.#sendPayload(payload);
|
73 |
+
}
|
74 |
+
}
|
package.json
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "confia-form-backend",
|
3 |
+
"version": "1.0.0",
|
4 |
+
"main": "server.js",
|
5 |
+
"type": "module",
|
6 |
+
"scripts": {
|
7 |
+
"start": "node server.js",
|
8 |
+
"test": "echo \"Error: no test specified\" && exit 1"
|
9 |
+
},
|
10 |
+
"keywords": [],
|
11 |
+
"author": "",
|
12 |
+
"license": "ISC",
|
13 |
+
"description": "",
|
14 |
+
"devDependencies": {
|
15 |
+
"@types/express": "5.0.0",
|
16 |
+
"@types/node": "22.7.5"
|
17 |
+
},
|
18 |
+
"dependencies": {
|
19 |
+
"cors": "2.8.5",
|
20 |
+
"express": "4.21.1",
|
21 |
+
"zod": "3.23.8"
|
22 |
+
}
|
23 |
+
}
|
schemas.js
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import z from 'zod';
|
2 |
+
|
3 |
+
export const messageSchema = z.object({
|
4 |
+
name: z.string({
|
5 |
+
required_error: "El nombre es obligatorio",
|
6 |
+
invalid_type_error: "El nombre debe ser texto"
|
7 |
+
})
|
8 |
+
.min(3, "El nombre debe tener por lo menos 3 caracteres")
|
9 |
+
.max(20, "El nombre no puede superar los 20 caracteres"),
|
10 |
+
email: z.string({
|
11 |
+
required_error: "El correo es obligatorio",
|
12 |
+
invalid_type_error: "El correo debe ser texto"
|
13 |
+
}).email("El correo debe ser válido"),
|
14 |
+
message: z.string({
|
15 |
+
required_error: "El mensaje es obligatorio",
|
16 |
+
invalid_type_error: "El mensaje debe ser un texto"
|
17 |
+
})
|
18 |
+
.min(1, "El mensaje no puede estar vacío")
|
19 |
+
.max(500, "El mensaje no puede superar los 500 caracteres")
|
20 |
+
});
|
21 |
+
|
22 |
+
export const urlSchema = z.string().url();
|
server.js
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { createApp } from "./app.js";
|
2 |
+
import { DiscordWebhook } from "./discord-webhook.js";
|
3 |
+
|
4 |
+
const webhookUrl = process.env.WEBHOOK_URL;
|
5 |
+
if (!webhookUrl) {
|
6 |
+
console.error("WEBHOOK_URL environment variable is not set.");
|
7 |
+
process.exit(1);
|
8 |
+
}
|
9 |
+
|
10 |
+
const PORT = process.env.PORT ?? 80;
|
11 |
+
const app = createApp(new DiscordWebhook(webhookUrl));
|
12 |
+
|
13 |
+
app.listen(PORT, () => {
|
14 |
+
console.log(`Server is listening on port ${PORT}`);
|
15 |
+
});
|