diff --git a/ass.js b/ass.js index 0a0567f..0b10cba 100755 --- a/ass.js +++ b/ass.js @@ -14,6 +14,8 @@ const fs = require('fs-extra'); const express = require('express'); const useragent = require('express-useragent'); const multer = require('multer'); +const DateTime = require('luxon').DateTime; +const OpenGraph = require('./ogp'); const { path, saveData, log, verify, generateToken, generateId } = require('./utils'); //#endregion @@ -82,6 +84,17 @@ function startup() { let trueDomain = getTrueDomain(req.headers["x-ass-domain"]); let generator = req.headers["x-ass-access"] || resourceIdType; + // Get the uploaded time in milliseconds + req.file.timestamp = DateTime.now().toMillis(); + + // Attach any embed overrides, if necessary + req.file.opengraph = { + title: req.headers['x-ass-og-title'], + description: req.headers['x-ass-og-description'], + author: req.headers['x-ass-og-author'], + color: req.headers['x-ass-og-color'] + }; + // Save the file information let resourceId = generateId(generator, resourceIdSize, req.file.originalname); data[resourceId.split('.')[0]] = req.file; @@ -107,8 +120,8 @@ function startup() { // If the ID is invalid, return 404 if (!resourceId || !data[resourceId]) return res.sendStatus(404); - // If a Discord client wants to load an mp4, send the data needed for a proper inline embed - if (req.useragent.isBot && data[resourceId].mimetype == 'video/mp4') return res.type('html').send(genHtml(resourceId)); + // If the client is Discord, send an Open Graph embed + if (req.useragent.isBot) return res.type('html').send(new OpenGraph(getTrueHttp(), getTrueDomain(), resourceId, data[resourceId]).build()); // Read the file and send it to the client fs.readFile(path(data[resourceId].path)) @@ -147,16 +160,3 @@ function getTrueHttp() { function getTrueDomain(d = domain) { return d.concat((port == 80 || port == 443 || isProxied) ? '' : `:${port}`); } - -function genHtml(resourceId) { - return ` - - - ass - - - - ass - -`; -} diff --git a/ogp.js b/ogp.js new file mode 100644 index 0000000..29703f2 --- /dev/null +++ b/ogp.js @@ -0,0 +1,80 @@ +const Mustache = require('mustache'); +const DateTime = require('luxon').DateTime; +const github = require('./package.json').homepage; +const { formatBytes } = require('./utils'); + +// +class OpenGraph { + http; + domain; + resourceId; + + filename; + type; + size; + timestamp; + + title; + description; + author; + color; + + constructor(http, domain, resourceId, { originalname, mimetype, size, timestamp, opengraph }) { + this.http = http; + this.domain = domain; + this.resourceId = resourceId; + + this.type = mimetype; + this.filename = originalname; + this.size = size; + this.timestamp = timestamp; + + this.title = opengraph.title || ''; + this.description = opengraph.description || ''; + this.author = opengraph.author || ''; + this.color = opengraph.color || ''; + } + + build() { + return Mustache.render(html, { + github, + + http: this.http, + domain: this.domain, + resourceId: this.resourceId, + + ogtype: this.type.includes('video') ? 'video.other' : 'image', + type: this.type.includes('video') ? 'video' : 'image', + ext: this.type.includes('video') ? '.mp4' : '', + + title: (this.title.length != 0) ? `` : '', + description: (this.description.length != 0) ? `` : '', + site: (this.author.length != 0) ? `` : '', + color: (this.color.length != 0) ? `` : '', + card: !this.type.includes('video') ? `` : '', + }) + .replace(new RegExp('&size', 'g'), formatBytes(this.size)) + .replace(new RegExp('&filename', 'g'), this.filename) + .replace(new RegExp('×tamp', 'g'), DateTime.fromMillis(this.timestamp).toLocaleString(DateTime.DATETIME_MED)); + } +} + +const html = ` + + + ass + + + {{{title}}} + {{{description}}} + {{{site}}} + {{{color}}} + {{{card}}} + + + Open Graph response for ass. + + +`; + +module.exports = OpenGraph; diff --git a/package-lock.json b/package-lock.json index 8d1f917..7639471 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,21 @@ { "name": "ass", - "version": "1.0.0", + "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ass", - "version": "1.0.0", + "version": "0.1.0", "license": "ISC", "dependencies": { "crypto-random-string": "3.3.1", "express": "^4.17.1", "express-useragent": "^1.0.15", "fs-extra": "^9.1.0", + "luxon": "^1.26.0", "multer": "^1.4.2", + "mustache": "^4.2.0", "prompt": "^1.1.0", "uuid": "^8.3.2" } @@ -493,6 +495,14 @@ "universalify": "^2.0.0" } }, + "node_modules/luxon": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.26.0.tgz", + "integrity": "sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A==", + "engines": { + "node": "*" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -594,6 +604,14 @@ "node": ">= 0.10.0" } }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -1380,6 +1398,11 @@ "universalify": "^2.0.0" } }, + "luxon": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.26.0.tgz", + "integrity": "sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1454,6 +1477,11 @@ "xtend": "^4.0.0" } }, + "mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", diff --git a/package.json b/package.json index 0fa2b4e..10f44c3 100755 --- a/package.json +++ b/package.json @@ -28,8 +28,10 @@ "express": "^4.17.1", "express-useragent": "^1.0.15", "fs-extra": "^9.1.0", + "luxon": "^1.26.0", "multer": "^1.4.2", + "mustache": "^4.2.0", "prompt": "^1.1.0", "uuid": "^8.3.2" } -} \ No newline at end of file +} diff --git a/utils.js b/utils.js index e4d81ce..d441e72 100755 --- a/utils.js +++ b/utils.js @@ -20,5 +20,11 @@ module.exports = { generateId: (mode, lenth, originalName) => (mode == idModes.zws) ? zwsGen(lenth) : (mode == idModes.r) ? randomGen(lenth) - : originalName -} \ No newline at end of file + : originalName, + formatBytes: (bytes, decimals = 2) => { + if (bytes === 0) return '0 Bytes'; + let sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + let i = Math.floor(Math.log(bytes) / Math.log(1024)); + return parseFloat((bytes / Math.pow(1024, i)).toFixed(decimals < 0 ? 0 : decimals)) + ' ' + sizes[i]; + } +}