diff --git a/backend/embed.ts b/backend/embed.ts index 7078e56..9f5aa5c 100644 --- a/backend/embed.ts +++ b/backend/embed.ts @@ -1,26 +1,55 @@ -import { EmbedTemplate, EmbedTemplateOperation, PreparedEmbed } from "ass" +import { AssFile, AssUser, EmbedTemplate, EmbedTemplateOperation, PreparedEmbed } from "ass" export const DEFAULT_EMBED: EmbedTemplate = { title: "ass - The simple self-hosted ShareX server", description: "ass is a self-hosted ShareX upload server written in Node.js" } -const executeEmbedOperation = (op: EmbedTemplateOperation): string => { +class EmbedContext { + public uploader: AssUser; + public file: AssFile; + + constructor(uploader: AssUser, file: AssFile) { + this.uploader = uploader; + this.file = file; + } +} + +const executeEmbedOperation = (op: EmbedTemplateOperation, ctx: EmbedContext): string | number => { if (typeof op == 'string') { return op; + } else if (typeof op == 'number') { + return op; } else if (typeof op == 'object') { switch (op.op) { case 'random': - if (op.options.length > 0) { - return executeEmbedOperation(op.options[Math.round(Math.random() * (op.options.length - 1))]); - } else throw new Error("Random without child operations"); + if (op.values.length > 0) { + return executeEmbedOperation(op.values[Math.round(Math.random() * (op.values.length - 1))], ctx); + } else throw new Error('Random without child operations'); + case 'fileSize': + return ctx.file.size; + case 'uploader': + return ctx.uploader.username; + case 'formatBytes': + // calculate the value + let value = executeEmbedOperation(op.value, ctx); + + // calculate the exponent + let exponent = (op.unit != null && { 'b': 0, 'kb': 1, 'mb': 2, 'gb': 3, 'tb': 4 }[executeEmbedOperation(op.unit, ctx)]) + || Math.max(Math.min(Math.floor(Math.log10(Number(value))/3), 4), 0); + + return `${(Number(value) / 1000 ** exponent).toFixed(2)}${['b', 'kb', 'mb', 'gb', 'tb'][exponent]}`; + case 'concat': + return op.values.reduce((prev, op) => prev.concat(executeEmbedOperation(op, ctx).toString()), ""); } } else throw new Error("Invalid embed template operation"); }; -export const prepareEmbed = (template: EmbedTemplate): PreparedEmbed => { +export const prepareEmbed = (template: EmbedTemplate, user: AssUser, file: AssFile): PreparedEmbed => { + let ctx = new EmbedContext(user, file); + return { - title: executeEmbedOperation(template.title), - description: executeEmbedOperation(template.description) + title: executeEmbedOperation(template.title, ctx).toString(), + description: executeEmbedOperation(template.description, ctx).toString() }; }; \ No newline at end of file diff --git a/backend/routers/index.ts b/backend/routers/index.ts index 39b815f..b5288f0 100644 --- a/backend/routers/index.ts +++ b/backend/routers/index.ts @@ -126,7 +126,15 @@ router.get('/:fakeId', async (req, res) => { embed: prepareEmbed({ title: UserConfig.config.embed?.title ?? DEFAULT_EMBED.title, description: UserConfig.config.embed?.description ?? DEFAULT_EMBED.description - }) + }, user ?? { + admin: false, + files: [], + id: "", + meta: {}, + password: "", + tokens: [], + username: "unknown" + }, meta) }); } }); diff --git a/common/types.d.ts b/common/types.d.ts index 8881557..b5c68b7 100644 --- a/common/types.d.ts +++ b/common/types.d.ts @@ -276,16 +276,52 @@ declare module 'ass' { } // Generic embed template operation - type EmbedTemplateOperation = EmbedTemplateRandomOperation | string; + type EmbedTemplateOperation = + EmbedTemplateRandomOperation | + EmbedTemplateFileSizeOperation | + EmbedTemplateFormatBytesOperation | + EmbedTemplateUploaderOperation | + EmbedTemplateConcatOperation | + string | number; /** * Selects one operation and executes it */ type EmbedTemplateRandomOperation = { - op: "random"; - options: EmbedTemplateOperation[]; + op: 'random'; + values: EmbedTemplateOperation[]; }; + /** + * Returns the file size in bytes + * @returns number + */ + type EmbedTemplateFileSizeOperation = { op: 'fileSize' }; + + /** + * Formats the file size in in {value} + */ + type EmbedTemplateFormatBytesOperation = { + op: 'formatBytes'; + unit?: EmbedTemplateOperation; // ready for ios! + value: EmbedTemplateOperation; + }; + + /** + * Returns the user who uploaded this file + */ + type EmbedTemplateUploaderOperation = { + op: 'uploader' + }; + + /** + * Joins strings + */ + type EmbedTemplateConcatOperation = { + op: 'concat', + values: EmbedTemplateOperation[] + } + /** * This is so beyond cursed */ diff --git a/views/viewer.pug b/views/viewer.pug index ee535bb..e517dd4 100644 --- a/views/viewer.pug +++ b/views/viewer.pug @@ -13,6 +13,7 @@ html.dark.sl-theme-dark(lang='en', prefix='og: https://ogp.me/ns') //- embed data meta(property='og:title', content=embed.title) meta(property='og:description', content=embed.description) + meta(property='og:author', content='ass') meta(property='og:type', content='image') meta(property='og:image', content=url) meta(property='og:url', content='.')