From fa3069280586a097a03b6344bb57c2104c3abf8d Mon Sep 17 00:00:00 2001 From: Kath <55346310+Kathund@users.noreply.github.com> Date: Thu, 15 Feb 2024 09:02:47 +0800 Subject: [PATCH] Add Discord Embed functionality --- config.example.json | 3 +- index.ts | 25 +++-- src/data/embed.json | 11 ++ src/endpoints/discord.ts | 28 +++++ src/endpoints/embed.ts | 58 +++++++++++ src/endpoints/generate.ts | 2 +- src/public/css/discord.css | 199 ++++++++++++++++++++++++++++++++++++ src/public/js/discord.js | 92 +++++++++++++++++ src/types/global.d.ts | 1 + src/views/pages/discord.ejs | 84 +++++++++++++++ src/views/pages/file.ejs | 4 +- 11 files changed, 494 insertions(+), 13 deletions(-) create mode 100644 src/data/embed.json create mode 100644 src/endpoints/discord.ts create mode 100644 src/endpoints/embed.ts create mode 100644 src/public/css/discord.css create mode 100644 src/public/js/discord.js create mode 100644 src/views/pages/discord.ejs diff --git a/config.example.json b/config.example.json index 2810cdf..2344f49 100644 --- a/config.example.json +++ b/config.example.json @@ -4,5 +4,6 @@ "nameHide": true, "key": "API_KEY", "maxFileSize": 104857600, - "allowConfigGen": true + "allowConfigGen": true, + "discordEmbed": false } diff --git a/index.ts b/index.ts index 1339b98..00ddd88 100644 --- a/index.ts +++ b/index.ts @@ -1,6 +1,6 @@ +import { PORT, url, key, allowConfigGen, discordEmbed } from './config.json'; import { errorMessage, otherMessage, warnMessage } from './src/logger'; -import { PORT, url, key, allowConfigGen } from './config.json'; -import express, { Request, Response } from 'express'; +import express, { json, Request, Response } from 'express'; import { loadEndpoints } from './src/functions'; import { existsSync, mkdirSync } from 'fs'; import fileUpload from 'express-fileupload'; @@ -16,7 +16,9 @@ try { app.set('views', './src/views'); app.set('view engine', 'ejs'); app.use(fileUpload()); + app.use(json()); global.generateKey = allowConfigGen ? crypto.randomUUID() : null; + global.discordEmbedKey = discordEmbed ? crypto.randomUUID() : null; const result = await loadEndpoints(app); if (result !== undefined) { otherMessage(`Loaded ${result} endpoints`); @@ -38,13 +40,18 @@ try { if (key === 'API_KEY') { warnMessage('The API Key is still the default key! It is recommended to change this in the config.json file.'); } - if (global.generateKey === null) return; - otherMessage(`Config is available to be generated @ ${url}/generate?key=${global.generateKey}`); - setTimeout(() => { - if (global.generateKey === null) return; - global.generateKey = null; - otherMessage(`Config is no longer available to be generated. Please restart to generate a new key.`); - }, 300000); + if (global.discordEmbedKey !== null) { + otherMessage(`Discord Embed is available to be customized @ ${url}/discord?key=${global.discordEmbedKey}`); + } + + if (global.generateKey !== null) { + otherMessage(`Config is available to be generated @ ${url}/generate?key=${global.generateKey}`); + setTimeout(() => { + if (global.generateKey === null) return; + global.generateKey = null; + otherMessage(`Config is no longer available to be generated. Please restart to generate a new key.`); + }, 300000); + } }); })(); } catch (error) { diff --git a/src/data/embed.json b/src/data/embed.json new file mode 100644 index 0000000..fc1c35f --- /dev/null +++ b/src/data/embed.json @@ -0,0 +1,11 @@ +{ + "author": "Kathund", + "siteName": "Source Code", + "description": "ShareX-API Made by Kathund", + "authorURL": "https://github.com/kathund", + "siteNameURL": "https://github.com/kathund/ShareX-API", + "title": "ShareX-API", + "color": "#52a396", + "timestampState": true, + "randomColorState": false +} diff --git a/src/endpoints/discord.ts b/src/endpoints/discord.ts new file mode 100644 index 0000000..033ff4f --- /dev/null +++ b/src/endpoints/discord.ts @@ -0,0 +1,28 @@ +import { Application, Request, Response } from 'express'; +import { discordEmbed } from '../../config.json'; +import { errorMessage } from '../logger'; +import { readFileSync } from 'fs'; + +export default (app: Application) => { + app.get('/discord', async (req: Request, res: Response) => { + try { + if (!discordEmbed || global.discordEmbedKey === null) { + return res.status(400).send({ success: false, message: 'Discord Embeds are disabled' }); + } + const discordKey = req.query.key; + if (discordKey !== global.discordEmbedKey) { + errorMessage('Invalid Embed Key provided'); + return res.status(400).send({ success: false, message: 'Invalid Embed Key provided' }); + } + + const data = JSON.parse(readFileSync('src/data/embed.json', 'utf-8')); + return res.status(200).render('pages/discord', { + data: data, + embedKey: discordKey, + }); + } catch (err) { + errorMessage(err as string); + return res.status(500).send({ success: false, message: 'Internal server error' }); + } + }); +}; diff --git a/src/endpoints/embed.ts b/src/endpoints/embed.ts new file mode 100644 index 0000000..8542068 --- /dev/null +++ b/src/endpoints/embed.ts @@ -0,0 +1,58 @@ +import { Application, Request, Response } from 'express'; +import { apiMessage, errorMessage } from '../logger'; +import { discordEmbed } from '../../config.json'; +import { writeFileSync } from 'fs'; + +export default (app: Application) => { + app.post('/embed', async (req: Request, res: Response) => { + try { + apiMessage(req.path, 'User is trying to save embed'); + if (!discordEmbed || global.discordEmbedKey === null) { + return res.status(400).send({ success: false, message: 'Discord Embeds are disabled' }); + } + const discordKey = req.query.key; + if (discordKey !== global.discordEmbedKey) { + errorMessage('Invalid Embed Key provided'); + return res.status(400).send({ success: false, message: 'Invalid Embed Key provided' }); + } + const data = req.body; + if (typeof data !== 'object') { + errorMessage('User provided invalid data'); + return res.status(400).send({ success: false, message: 'Invalid data provided' }); + } + if ( + !data.author || + !data.siteName || + !data.description || + !data.authorURL || + !data.siteNameURL || + !data.title || + !data.color + ) { + errorMessage('User provided invalid data'); + return res.status(400).send({ success: false, message: 'Invalid data provided' }); + } + if ( + typeof data.author !== 'string' || + typeof data.siteName !== 'string' || + typeof data.description !== 'string' || + typeof data.authorURL !== 'string' || + typeof data.siteNameURL !== 'string' || + typeof data.title !== 'string' || + typeof data.color !== 'string' || + typeof data.timestampState !== 'boolean' || + typeof data.randomColorState !== 'boolean' + ) { + errorMessage('User provided invalid data'); + return res.status(400).send({ success: false, message: 'Invalid data provided' }); + } + + writeFileSync('src/data/embed.json', JSON.stringify(data)); + apiMessage(req.path, 'User updated embed data'); + return res.status(200).send({ success: true, message: 'Embed data saved' }); + } catch (err) { + errorMessage(err as string); + return res.status(500).send({ success: false, message: 'Internal server error' }); + } + }); +}; diff --git a/src/endpoints/generate.ts b/src/endpoints/generate.ts index ef54ef9..0cdfe93 100644 --- a/src/endpoints/generate.ts +++ b/src/endpoints/generate.ts @@ -1,6 +1,6 @@ +import { url, key, allowConfigGen } from '../../config.json'; import { Application, Request, Response } from 'express'; import { apiMessage, errorMessage } from '../logger'; -import { url, key, allowConfigGen } from '../../config.json'; export default (app: Application) => { app.get('/generate', async (req: Request, res: Response) => { diff --git a/src/public/css/discord.css b/src/public/css/discord.css new file mode 100644 index 0000000..a6feebd --- /dev/null +++ b/src/public/css/discord.css @@ -0,0 +1,199 @@ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('fonts/Inter.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, + U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +*, +*::before, +*::after { + box-sizing: border-box; + padding: 0px; + margin: 0px; +} + +body { + font-family: 'Inter', sans-serif; + background-color: #dcdcdc; + justify-content: center; + align-items: center; + font-size: 1.5rem; + color: #343434; + height: 100vh; + display: flex; + width: 100vw; +} + +main { + filter: drop-shadow(#000000bf 20px 20px 30px); + background-color: #bfb9b9; + border-radius: 16px; + width: 900px; + height: 900px; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; +} + +label { + font-size: 20px; +} + +input { + font-size: 16px; + border-radius: 8px; + background: none; + color: white; + border: none; + width: 100%; +} + +input:focus { + outline: none; +} + +.options { + width: 836px; + height: 376px; + background-color: #03395a; +} + +.inputs { + border: 2px solid #000000; + background-color: #4b4646; + width: 836px; + height: 192px; + display: flex; +} + +.inputs > * > * { + border: 2px solid #000000; + width: 418px; + height: 64px; +} + +.inputs > * { + width: 418px; + height: 192px; +} + +.buttons { + margin-top: 32px; + width: 836px; + height: 152px; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.buttons > * { + width: 836px; + height: 64px; + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.randomColor, +.color, +.timestamp { + background-color: #dcdcdc; + display: flex; + align-items: center; + justify-content: space-evenly; + font-size: 24px; + border-radius: 24px; + color: black; +} + +.randomColorToggle, +.timestampToggle { + background-color: #fff; + width: 64px; + height: 32px; + border-radius: 32px; + display: flex; + align-items: center; +} + +.randomColorSwitch, +.timestampSwitch { + position: absolute; + height: 23px; + width: 23px; + display: block; + border-radius: 30px; + border: 1px solid black; + background-color: #00000080; + transition: all 0.3s ease; + transform: translateX(4px); +} + +.randomColorActive, +.timestampActive { + transform: translateX(calc(64px - 27px)); + border: 1px solid #52a396; + background-color: #52a39680; +} + +.randomColor { + width: 300px; + height: 64px; +} + +.color { + width: 176px; + height: 64px; +} + +.timestamp { + width: 300px; + height: 64px; +} + +.save, +.reset, +.clear { + font-size: 24px; + width: 200px; + height: 64px; + border-radius: 24px; + border: none; + padding: 0px; + cursor: pointer; +} + +.save { + background-color: #27d26b; +} + +.reset { + background-color: #c94040; + width: 350px; + color: white; +} + +.clear { + background-color: #c7abcf; +} + +@media (prefers-color-scheme: dark) { + body { + background-color: #464646; + color: #dcdcdc; + } + + a { + color: #dcdcdc; + } + + main { + filter: drop-shadow(#ffffff1a 20px 20px 30px); + background-color: #363636; + } +} diff --git a/src/public/js/discord.js b/src/public/js/discord.js new file mode 100644 index 0000000..128a8b9 --- /dev/null +++ b/src/public/js/discord.js @@ -0,0 +1,92 @@ +/* eslint-disable */ + +const timestampToggle = document.getElementsByClassName('timestampToggle')[0]; +const timestampSwitch = document.getElementsByClassName('timestampSwitch')[0]; + +const randomColorToggle = document.getElementsByClassName('randomColorToggle')[0]; +const randomColorSwitch = document.getElementsByClassName('randomColorSwitch')[0]; + +let randomColorState = false; +let timestampState = false; + +timestampToggle.addEventListener('click', () => { + timestampState = !timestampState; + timestampSwitch.classList.toggle('timestampActive'); +}); + +randomColorToggle.addEventListener('click', () => { + randomColorState = !randomColorState; + randomColorSwitch.classList.toggle('randomColorActive'); +}); + +function resetToDefault() { + document.getElementById('authorInput').value = 'Kathund'; + document.getElementById('siteNameInput').value = 'Source Code'; + document.getElementById('descriptionInput').value = 'ShareX-API Made by Kathund'; + document.getElementById('authorURLInput').value = 'https://github.com/kathund'; + document.getElementById('siteNameURLInput').value = 'https://github.com/kathund/ShareX-API'; + document.getElementById('titleInput').value = 'ShareX-API'; + document.getElementById('colorInput').value = '#52A396'; + + if (!timestampState) { + timestampToggle.click(); + } + + if (randomColorState) { + randomColorToggle.click(); + } +} + +function clearBoxes() { + document.getElementById('authorInput').value = ''; + document.getElementById('siteNameInput').value = ''; + document.getElementById('descriptionInput').value = ''; + document.getElementById('authorURLInput').value = ''; + document.getElementById('siteNameURLInput').value = ''; + document.getElementById('titleInput').value = ''; + document.getElementById('colorInput').value = '#000000'; + + if (timestampState) { + timestampToggle.click(); + } + + if (randomColorState) { + randomColorToggle.click(); + } +} + +function saveData() { + const author = document.getElementById('authorInput').value; + const siteName = document.getElementById('siteNameInput').value; + const description = document.getElementById('descriptionInput').value; + const authorURL = document.getElementById('authorURLInput').value; + const siteNameURL = document.getElementById('siteNameURLInput').value; + const title = document.getElementById('titleInput').value; + const color = document.getElementById('colorInput').value; + + const urlParams = new URLSearchParams(window.location.search); + const key = urlParams.get('key'); + + fetch(`/embed?key=${key}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + author: author, + siteName: siteName, + description: description, + authorURL: authorURL, + siteNameURL: siteNameURL, + title: title, + color: color, + timestampState: timestampState, + randomColorState: randomColorState, + }), + }) + .then((res) => res.json()) + .then((data) => { + // Log the response from the server + console.log(data); + }); +} diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 5223e02..98f2619 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -1,2 +1,3 @@ /* eslint-disable no-var */ declare var generateKey: string | null; +declare var discordEmbedKey: string | null; diff --git a/src/views/pages/discord.ejs b/src/views/pages/discord.ejs new file mode 100644 index 0000000..d2b9d28 --- /dev/null +++ b/src/views/pages/discord.ejs @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + ShareX-API | Home + + + + +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+

Random Color

+
+ +
+
+
+

Color

+ +
+
+

Timestamp

+
+ +
+
+
+
+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/src/views/pages/file.ejs b/src/views/pages/file.ejs index 8887a91..19a18fe 100644 --- a/src/views/pages/file.ejs +++ b/src/views/pages/file.ejs @@ -12,7 +12,7 @@ - <% if (img.endsWith('.mp4')) { %> + <% if (img.endsWith(".mp4")) { %> @@ -24,7 +24,7 @@
- <% if (img.endsWith('.mp4')) { %> + <% if (img.endsWith(".mp4")) { %>