Added fancy image/video viewer

pull/20/head
tycrek 3 years ago
parent b882866863
commit 180383ffc5
No known key found for this signature in database
GPG Key ID: 25D74F3943625263

@ -25,7 +25,7 @@ const Thumbnail = require('./thumbnails');
const Vibrant = require('./vibrant');
const Hash = require('./hash');
const { uploadLocal, uploadS3, deleteS3 } = require('./storage');
const { path, saveData, log, verify, getTrueHttp, getTrueDomain, renameFile, generateToken, generateId, formatBytes, arrayEquals, getS3url, downloadTempS3, sanitize } = require('./utils');
const { path, saveData, log, verify, getTrueHttp, getTrueDomain, renameFile, generateToken, generateId, formatBytes, formatTimestamp, arrayEquals, getS3url, getDirectUrl, getResourceColor, downloadTempS3, sanitize } = require('./utils');
const { CODE_NO_CONTENT, CODE_BAD_REQUEST, CODE_UNAUTHORIZED, CODE_NOT_FOUND } = require('./MagicNumbers.json');
//#endregion
@ -252,8 +252,16 @@ function startup() {
};
// If the client is a social bot (such as Discord or Instagram), send an Open Graph embed
if (req.useragent.isBot) return res.type('html').send(new OpenGraph(getTrueHttp(), getTrueDomain(), resourceId, requiredItems).build());
else res.redirect(`${req.url}/direct`);
if (req.useragent.isBot) res.type('html').send(new OpenGraph(getTrueHttp(), getTrueDomain(), resourceId, requiredItems).build());
else res.render('view', {
title: requiredItems.originalname,
uploader: users[fileData.token].username,
timestamp: formatTimestamp(fileData.timestamp),
size: formatBytes(fileData.size),
color: getResourceColor(fileData.opengraph.color || null, fileData.vibrant),
isVideo: fileData.mimetype.includes('video'),
resourceAttr: { src: getDirectUrl(resourceId) },
});
});
// Direct resource

@ -1,8 +1,6 @@
const Mustache = require('mustache');
const DateTime = require('luxon').DateTime;
const { homepage, version } = require('./package.json');
const { s3enabled } = require('./config.json');
const { formatBytes, randomHexColour, getS3url, getSafeExt } = require('./utils');
const { formatBytes, getDirectUrl, getResourceColor, formatTimestamp, getSafeExt } = require('./utils');
// https://ogp.me/
class OpenGraph {
@ -41,7 +39,7 @@ class OpenGraph {
}
build() {
let resourceUrl = !s3enabled ? (this.http + this.domain + '/' + this.resourceId + '/direct' + getSafeExt(this.type)) : getS3url(this.randomId, this.type);
let resourceUrl = getDirectUrl(this.resourceId) + getSafeExt(this.type);
return Mustache.render(html, {
homepage,
version,
@ -57,16 +55,12 @@ class OpenGraph {
title: (this.title.length != 0) ? `<meta property="og:title" content="${this.title}">` : '',
description: (this.description.length != 0) ? `<meta property="og:description" content="${this.description}">` : '',
site: (this.author.length != 0) ? `<meta property="og:site_name" content="${this.author}">` : '',
color: (this.color.length != 0) ? `<meta name="theme-color" content="${this.getBuildColor()}">` : '',
color: (this.color.length != 0) ? `<meta name="theme-color" content="${getResourceColor(this.color, this.vibrant)}">` : '',
card: !this.type.includes('video') ? `<meta name="twitter:card" content="summary_large_image">` : '',
})
.replace(new RegExp('&size', 'g'), formatBytes(this.size))
.replace(new RegExp('&filename', 'g'), this.filename)
.replace(new RegExp('&timestamp', 'g'), DateTime.fromMillis(this.timestamp).toLocaleString(DateTime.DATETIME_MED));
}
getBuildColor() {
return this.color === '&random' ? randomHexColour() : this.color === '&vibrant' ? this.vibrant : this.color;
.replace(new RegExp('&timestamp', 'g'), formatTimestamp(this.timestamp));
}
}

@ -1,7 +1,8 @@
const fs = require('fs-extra');
const Path = require('path');
const fetch = require('node-fetch');
const sanitize = require("sanitize-filename");
const sanitize = require('sanitize-filename');
const { DateTime } = require('luxon');
const token = require('./generators/token');
const zwsGen = require('./generators/zws');
const randomGen = require('./generators/random');
@ -27,6 +28,10 @@ function getS3url(s3key, type) {
return `https://${s3bucket}.${s3endpoint}/${s3key}${getSafeExt(type)}`;
}
function getDirectUrl(resourceId) {
return getTrueHttp() + getTrueDomain() + `/${resourceId}/direct`;
}
function randomHexColour() { // From: https://www.geeksforgeeks.org/javascript-generate-random-hex-codes-color/
const letters = "0123456789ABCDEF";
let colour = '#';
@ -35,6 +40,14 @@ function randomHexColour() { // From: https://www.geeksforgeeks.org/javascript-g
return colour;
}
function getResourceColor(colorValue, vibrantValue) {
return colorValue === '&random' ? randomHexColour() : colorValue === '&vibrant' ? vibrantValue : colorValue;
}
function formatTimestamp(timestamp) {
return DateTime.fromMillis(timestamp).toLocaleString(DateTime.DATETIME_MED);
}
const idModes = {
zws: 'zws', // Zero-width spaces (see: https://zws.im/)
og: 'original', // Use original uploaded filename
@ -51,7 +64,13 @@ module.exports = {
path,
getTrueHttp,
getTrueDomain,
getS3url,
getDirectUrl,
getResourceColor,
formatTimestamp,
getSafeExt,
randomHexColour,
sanitize,
log: console.log,
saveData: (data) => fs.writeJsonSync(Path.join(__dirname, 'data.json'), data, { spaces: 4 }),
verify: (req, users) => req.headers.authorization && Object.prototype.hasOwnProperty.call(users, req.headers.authorization),
@ -78,7 +97,4 @@ module.exports = {
fetch(getS3url(file.randomId, file.mimetype))
.then((f2) => f2.body.pipe(fs.createWriteStream(Path.join(__dirname, diskFilePath, sanitize(file.originalname))).on('close', () => resolve())))
.catch(reject)),
getS3url,
getSafeExt,
sanitize
}

@ -0,0 +1,5 @@
img, video {
border-left-width: 4px;
border-left-style: solid;
border-radius: 4px;
}

@ -0,0 +1,29 @@
#container {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
width: 100%;
height: 100%;
}
#content {
background-color: #151515;
border-radius: 24px;
}
#footer {
font-size-adjust: 0.3;
margin-left: 16px;
margin-right: 16px;
}
img, video {
max-height: 50vh;
}
figcaption strong {
font-weight: bold;
}

@ -1,18 +1,16 @@
meta(name='viewport' content='width=device-width, initial-scale=1.0, viewport-fit=cover')
//- Markdown stylesheet & Highlight.js theme
style: include css/modest.css
style: include css/dracula.highlight.js.css
//- DarkReader for easy dark modes & Highlight.js for codeblocks
script(src='https://cdn.jsdelivr.net/npm/darkreader@4/darkreader.min.js')
script(src='https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.7.1/build/highlight.min.js')
script.
// Dark mode with Dark Reader
DarkReader.setFetchMethod(window.fetch);
DarkReader.enable({
brightness: 100,
contrast: 100,
sepia: 0
});
DarkReader.enable({}, { css: '#content { background-color: #121212 !important; }' }); // Fix the card colour
// Highlight code blocks
hljs.highlightAll();

@ -0,0 +1,25 @@
html
head
title!=title
include head
style: include css/font.css
style: include css/view.css
if color !== null
style: include css/img.css
style.
img, video { border-color: #{color}; }
body
#container
#content
h4!=title
figure
if isVideo
video#media(controls loop muted playsinline preload='metadata')&attributes(resourceAttr)
else
img#media(decoding='async')&attributes(resourceAttr)
figcaption
br
span Uploaded by #[strong!=uploader]
br
small #{timestamp} (#{size})
#footer: p Image hosted by #[a(href='https://github.com/tycrek/ass' target='_blank'): strong ass], the superior self-hosted ShareX server
Loading…
Cancel
Save