feat: new variables parser
This commit is contained in:
parent
6349503b00
commit
91341e2d21
6 changed files with 193 additions and 63 deletions
|
@ -2,53 +2,21 @@ import { Image, Url, User } from '@prisma/client';
|
|||
import config from 'lib/config';
|
||||
import { ConfigDiscordContent } from 'lib/config/Config';
|
||||
import Logger from './logger';
|
||||
|
||||
// [user, image, url, route (ex. https://example.com/r/something.png)]
|
||||
export type Args = [User, Image?, Url?, string?];
|
||||
import { parseString, ParseValue } from './utils/parser';
|
||||
|
||||
const logger = Logger.get('discord');
|
||||
|
||||
function parse(str: string, args: Args) {
|
||||
if (!str) return null;
|
||||
|
||||
str = str
|
||||
.replace(/{user\.admin}/gi, args[0].administrator ? 'yes' : 'no')
|
||||
.replace(/{user\.id}/gi, args[0].id.toString())
|
||||
.replace(/{user\.name}/gi, args[0].username)
|
||||
.replace(/{link}/gi, args[3]);
|
||||
|
||||
if (args[1])
|
||||
str = str
|
||||
.replace(/{file\.id}/gi, args[1].id.toString())
|
||||
.replace(/{file\.mime}/gi, args[1].mimetype)
|
||||
.replace(/{file\.file}/gi, args[1].file)
|
||||
.replace(/{file\.created_at.full_string}/gi, args[1].created_at.toLocaleString())
|
||||
.replace(/{file\.created_at.time_string}/gi, args[1].created_at.toLocaleTimeString())
|
||||
.replace(/{file\.created_at.date_string}/gi, args[1].created_at.toLocaleDateString());
|
||||
|
||||
if (args[2])
|
||||
str = str
|
||||
.replace(/{url\.id}/gi, args[2].id.toString())
|
||||
.replace(/{url\.vanity}/gi, args[2].vanity ? args[2].vanity : 'none')
|
||||
.replace(/{url\.destination}/gi, args[2].destination)
|
||||
.replace(/{url\.created_at.full_string}/gi, args[2].created_at.toLocaleString())
|
||||
.replace(/{url\.created_at.time_string}/gi, args[2].created_at.toLocaleTimeString())
|
||||
.replace(/{url\.created_at.date_string}/gi, args[2].created_at.toLocaleDateString());
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
export function parseContent(
|
||||
content: ConfigDiscordContent,
|
||||
args: Args
|
||||
args: ParseValue
|
||||
): ConfigDiscordContent & { url: string } {
|
||||
return {
|
||||
content: parse(content.content, args),
|
||||
content: parseString(content.content, args),
|
||||
embed: content.embed
|
||||
? {
|
||||
title: parse(content.embed.title, args),
|
||||
description: parse(content.embed.description, args),
|
||||
footer: parse(content.embed.footer, args),
|
||||
title: parseString(content.embed.title, args),
|
||||
description: parseString(content.embed.description, args),
|
||||
footer: parseString(content.embed.footer, args),
|
||||
color: content.embed.color,
|
||||
thumbnail: content.embed.thumbnail,
|
||||
timestamp: content.embed.timestamp,
|
||||
|
@ -59,10 +27,16 @@ export function parseContent(
|
|||
};
|
||||
}
|
||||
|
||||
export async function sendUpload(user: User, image: Image, host: string) {
|
||||
export async function sendUpload(user: User, image: Image, raw_link: string, link: string) {
|
||||
if (!config.discord.upload) return;
|
||||
|
||||
const parsed = parseContent(config.discord.upload, [user, image, null, host]);
|
||||
const parsed = parseContent(config.discord.upload, {
|
||||
file: image,
|
||||
user,
|
||||
link,
|
||||
raw_link,
|
||||
});
|
||||
|
||||
const isImage = image.mimetype.startsWith('image/');
|
||||
|
||||
const body = JSON.stringify({
|
||||
|
@ -118,10 +92,14 @@ export async function sendUpload(user: User, image: Image, host: string) {
|
|||
return;
|
||||
}
|
||||
|
||||
export async function sendShorten(user: User, url: Url, host: string) {
|
||||
export async function sendShorten(user: User, url: Url, link: string) {
|
||||
if (!config.discord.shorten) return;
|
||||
|
||||
const parsed = parseContent(config.discord.shorten, [user, null, url, host]);
|
||||
const parsed = parseContent(config.discord.shorten, {
|
||||
url,
|
||||
user,
|
||||
link,
|
||||
});
|
||||
|
||||
const body = JSON.stringify({
|
||||
username: config.discord.username,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import type { Image, User } from '@prisma/client';
|
||||
import dayjs from 'dayjs';
|
||||
import duration from 'dayjs/plugin/duration';
|
||||
import dayjsRelativeTime from 'dayjs/plugin/relativeTime';
|
||||
|
@ -6,21 +5,6 @@ import ms, { StringValue } from 'ms';
|
|||
dayjs.extend(duration);
|
||||
dayjs.extend(dayjsRelativeTime);
|
||||
|
||||
export function parse(str: string, image: Image, user: User) {
|
||||
if (!str) return null;
|
||||
|
||||
return str
|
||||
.replace(/{user\.admin}/gi, user.administrator ? 'yes' : 'no')
|
||||
.replace(/{user\.id}/gi, user.id.toString())
|
||||
.replace(/{user\.name}/gi, user.username)
|
||||
.replace(/{image\.id}/gi, image.id.toString())
|
||||
.replace(/{image\.mime}/gi, image.mimetype)
|
||||
.replace(/{image\.file}/gi, image.file)
|
||||
.replace(/{image\.created_at.full_string}/gi, image.created_at.toLocaleString())
|
||||
.replace(/{image\.created_at.time_string}/gi, image.created_at.toLocaleTimeString())
|
||||
.replace(/{image\.created_at.date_string}/gi, image.created_at.toLocaleDateString());
|
||||
}
|
||||
|
||||
export function randomChars(length: number) {
|
||||
const charset = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890';
|
||||
|
||||
|
|
143
src/lib/utils/parser.ts
Normal file
143
src/lib/utils/parser.ts
Normal file
|
@ -0,0 +1,143 @@
|
|||
import type { Image, User, Url } from '@prisma/client';
|
||||
|
||||
export type ParseValue = {
|
||||
file?: Image;
|
||||
url?: Url;
|
||||
user?: User;
|
||||
|
||||
link?: string;
|
||||
raw_link?: string;
|
||||
};
|
||||
|
||||
export function parseString(str: string, value: ParseValue) {
|
||||
str = str.replace(/\{link\}/gi, value.link).replace(/\{raw_link\}/gi, value.raw_link);
|
||||
|
||||
const re = /\{(?<type>file|url|user)\.(?<prop>\w+)(::(?<mod>\w+))?\}/gi;
|
||||
let matches: RegExpMatchArray;
|
||||
|
||||
while ((matches = re.exec(str))) {
|
||||
const getV = value[matches.groups.type];
|
||||
if (!getV) {
|
||||
str = replaceCharsFromString(str, '{unknown_type}', matches.index, re.lastIndex);
|
||||
re.lastIndex = matches.index;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matches.groups.prop in ['password', 'avatar']) {
|
||||
str = replaceCharsFromString(str, '{unknown_property}', matches.index, re.lastIndex);
|
||||
re.lastIndex = matches.index;
|
||||
continue;
|
||||
}
|
||||
|
||||
const v = getV[matches.groups.prop];
|
||||
|
||||
if (v === undefined) {
|
||||
str = replaceCharsFromString(str, '{unknown_property}', matches.index, re.lastIndex);
|
||||
re.lastIndex = matches.index;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matches.groups.mod) {
|
||||
str = replaceCharsFromString(str, modifier(matches.groups.mod, v), matches.index, re.lastIndex);
|
||||
re.lastIndex = matches.index;
|
||||
continue;
|
||||
}
|
||||
|
||||
str = replaceCharsFromString(str, v, matches.index, re.lastIndex);
|
||||
re.lastIndex = matches.index;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function modifier(mod: string, value: any): string {
|
||||
mod = mod.toLowerCase();
|
||||
|
||||
if (value instanceof Date) {
|
||||
switch (mod) {
|
||||
case 'locale':
|
||||
return value.toLocaleString();
|
||||
case 'time':
|
||||
return value.toLocaleTimeString();
|
||||
case 'date':
|
||||
return value.toLocaleDateString();
|
||||
case 'unix':
|
||||
return Math.floor(value.getTime() / 1000).toString();
|
||||
case 'iso':
|
||||
return value.toISOString();
|
||||
case 'utc':
|
||||
return value.toUTCString();
|
||||
case 'year':
|
||||
return value.getFullYear().toString();
|
||||
case 'month':
|
||||
return (value.getMonth() + 1).toString();
|
||||
case 'day':
|
||||
return value.getDate().toString();
|
||||
case 'hour':
|
||||
return value.getHours().toString();
|
||||
case 'minute':
|
||||
return value.getMinutes().toString();
|
||||
case 'second':
|
||||
return value.getSeconds().toString();
|
||||
default:
|
||||
return '{unknown_date_modifier}';
|
||||
}
|
||||
} else if (typeof value === 'string') {
|
||||
switch (mod) {
|
||||
case 'upper':
|
||||
return value.toUpperCase();
|
||||
case 'lower':
|
||||
return value.toLowerCase();
|
||||
case 'title':
|
||||
return value.charAt(0).toUpperCase() + value.slice(1);
|
||||
case 'length':
|
||||
return value.length.toString();
|
||||
case 'reverse':
|
||||
return value.split('').reverse().join('');
|
||||
case 'base64':
|
||||
return btoa(value);
|
||||
case 'hex':
|
||||
return toHex(value);
|
||||
default:
|
||||
return '{unknown_str_modifier}';
|
||||
}
|
||||
} else if (typeof value === 'number') {
|
||||
switch (mod) {
|
||||
case 'comma':
|
||||
return value.toLocaleString();
|
||||
case 'hex':
|
||||
return value.toString(16);
|
||||
case 'octal':
|
||||
return value.toString(8);
|
||||
case 'binary':
|
||||
return value.toString(2);
|
||||
default:
|
||||
return '{unknown_int_modifier}';
|
||||
}
|
||||
} else if (typeof value === 'boolean') {
|
||||
switch (mod) {
|
||||
case 'yesno':
|
||||
return value ? 'Yes' : 'No';
|
||||
case 'onoff':
|
||||
return value ? 'On' : 'Off';
|
||||
case 'truefalse':
|
||||
return value ? 'True' : 'False';
|
||||
default:
|
||||
return '{unknown_bool_modifier}';
|
||||
}
|
||||
}
|
||||
|
||||
return '{unknown_modifier}';
|
||||
}
|
||||
|
||||
function replaceCharsFromString(str: string, replace: string, start: number, end: number): string {
|
||||
return str.slice(0, start) + replace + str.slice(end);
|
||||
}
|
||||
|
||||
function toHex(str: string): string {
|
||||
let hex = '';
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hex += '' + str.charCodeAt(i).toString(16);
|
||||
}
|
||||
return hex;
|
||||
}
|
|
@ -191,7 +191,10 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
file,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}/r/${
|
||||
invis ? invis.invis : file.file
|
||||
}`
|
||||
}`,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.uploader.route === '/' ? '' : zconfig.uploader.route
|
||||
}/${invis ? invis.invis : file.file}`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -325,7 +328,10 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
image,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}/r/${
|
||||
invis ? invis.invis : image.file
|
||||
}`
|
||||
}`,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.uploader.route === '/' ? '' : zconfig.uploader.route
|
||||
}/${invis ? invis.invis : image.file}`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Box, Button, Modal, PasswordInput } from '@mantine/core';
|
||||
import exts from 'lib/exts';
|
||||
import prisma from 'lib/prisma';
|
||||
import { parse } from 'lib/utils/client';
|
||||
import { parseString } from 'lib/utils/parser';
|
||||
import { GetServerSideProps } from 'next';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
|
@ -63,9 +63,14 @@ export default function EmbeddedFile({ image, user, pass, prismRender }) {
|
|||
{image.embed && (
|
||||
<>
|
||||
{user.embedSiteName && (
|
||||
<meta property='og:site_name' content={parse(user.embedSiteName, image, user)} />
|
||||
<meta
|
||||
property='og:site_name'
|
||||
content={parseString(user.embedSiteName, { file: image, user })}
|
||||
/>
|
||||
)}
|
||||
{user.embedTitle && (
|
||||
<meta property='og:title' content={parseString(user.embedTitle, { file: image, user })} />
|
||||
)}
|
||||
{user.embedTitle && <meta property='og:title' content={parse(user.embedTitle, image, user)} />}
|
||||
<meta property='theme-color' content={user.embedColor} />
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -21,6 +21,7 @@ import rawRoute from './routes/raw';
|
|||
import uploadsRoute, { uploadsRouteOnResponse } from './routes/uploads';
|
||||
import urlsRoute, { urlsRouteOnResponse } from './routes/urls';
|
||||
import { IncomingMessage } from 'http';
|
||||
import { parseString } from '../lib/utils/parser';
|
||||
|
||||
const dev = process.env.NODE_ENV === 'development';
|
||||
const logger = Logger.get('server');
|
||||
|
@ -38,6 +39,19 @@ start();
|
|||
async function start() {
|
||||
logger.debug('Starting server');
|
||||
|
||||
// const a = parseString(
|
||||
// '{file.name::upper} {file.mimetype} {file.test} {file.created_at::unix} {file.v::yesno} {file.int::hex}',
|
||||
// // @ts-ignore
|
||||
// {
|
||||
// name: 'test',
|
||||
// mimetype: 'image/png',
|
||||
// created_at: new Date(),
|
||||
// int: 123123123123123,
|
||||
// v: false,
|
||||
// }
|
||||
// );
|
||||
// console.log(a);
|
||||
|
||||
// plugins
|
||||
server
|
||||
.register(loggerPlugin)
|
||||
|
|
Loading…
Add table
Reference in a new issue