You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ass/src/utils.ts

144 lines
5.1 KiB

import { AssRequest, FileData } from './definitions';
import fs from 'fs-extra';
import Path from 'path';
import fetch from 'node-fetch';
import sanitize from 'sanitize-filename';
import { DateTime } from 'luxon';
import token from './generators/token';
import zwsGen from './generators/zws';
import randomGen from './generators/random';
import gfyGen from './generators/gfycat';
import logger from './logger';
const { HTTP, HTTPS, KILOBYTES } = require('../MagicNumbers.json');
// Catch config.json not existing when running setup script
try {
var { useSsl, port, domain, isProxied, diskFilePath, saveWithDate, s3bucket, s3endpoint, s3usePathStyle } = require('../config.json'); // skipcq: JS-0239, JS-0102
} catch (ex) {
// @ts-ignore
if (ex.code !== 'MODULE_NOT_FOUND') console.error(ex);
}
export function getTrueHttp() {
return ('http').concat(useSsl ? 's' : '').concat('://');
}
export function getTrueDomain(d = domain) {
return d.concat((port === HTTP || port === HTTPS || isProxied) ? '' : `:${port}`);
}
export function getS3url(s3key: string, ext: string) {
return `https://${s3usePathStyle ? `${s3endpoint}/${s3bucket}` : `${s3bucket}.${s3endpoint}`}/${s3key}${ext}`;
}
export function getDirectUrl(resourceId: string) {
3 years ago
return `${getTrueHttp()}${getTrueDomain()}/${resourceId}/direct`;
}
export function randomHexColour() { // From: https://www.geeksforgeeks.org/javascript-generate-random-hex-codes-color/
const letters = '0123456789ABCDEF';
let colour = '#';
for (let i = 0; i < 6; i++) // skipcq: JS-0074
colour += letters[(Math.floor(Math.random() * letters.length))];
return colour;
}
export function getResourceColor(colorValue: string, vibrantValue: string) {
return colorValue === '&random' ? randomHexColour() : colorValue === '&vibrant' ? vibrantValue : colorValue;
}
export function formatTimestamp(timestamp: number, timeoffset: string) {
return DateTime.fromMillis(timestamp).setZone(timeoffset).toLocaleString(DateTime.DATETIME_MED);
}
export function formatBytes(bytes: number, decimals = 2) { // skipcq: JS-0074
if (bytes === 0) return '0 Bytes';
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(KILOBYTES));
return parseFloat((bytes / Math.pow(KILOBYTES, i)).toFixed(decimals < 0 ? 0 : decimals)).toString().concat(` ${sizes[i]}`);
}
export function replaceholder(data: string, size: number, timestamp: number, timeoffset: string, originalname: string) {
return data
.replace(/&size/g, formatBytes(size))
.replace(/&filename/g, originalname)
.replace(/&timestamp/g, formatTimestamp(timestamp, timeoffset));
}
export function getDatedDirname() {
if (!saveWithDate) return diskFilePath;
// Get current month and year
const [month, , year] = new Date().toLocaleDateString('en-US').split('/');
// Add 0 before single digit months (6 turns into 06)
return `${diskFilePath}${diskFilePath.endsWith('/') ? '' : '/'}${year}-${`0${month}`.slice(-2)}`; // skipcq: JS-0074
}
export function arrayEquals(arr1: any[], arr2: any[]) {
return arr1.length === arr2.length && arr1.slice().sort().every((value: string, index: number) => value === arr2.slice().sort()[index])
};
export function verify(req: AssRequest, users: JSON) {
return req.headers.authorization && Object.prototype.hasOwnProperty.call(users, req.headers.authorization);
}
export function generateId(mode: string, length: number, gfyLength: number, originalName: string) {
return (GENERATORS.has(mode) ? GENERATORS.get(mode)({ length, gfyLength }) : originalName);
}
// Set up pathing
export const path = (...paths: string[]) => Path.join(process.cwd(), ...paths); // '..' was added to make it easier to run files after moving the project to src/
const idModes = {
zws: 'zws', // Zero-width spaces (see: https://zws.im/)
og: 'original', // Use original uploaded filename
r: 'random', // Use a randomly generated ID with a mixed-case alphanumeric character set
gfy: 'gfycat' // Gfycat-style ID's (https://gfycat.com/unsungdiscretegrub)
};
4 years ago
const GENERATORS = new Map();
GENERATORS.set(idModes.zws, zwsGen);
GENERATORS.set(idModes.r, randomGen);
GENERATORS.set(idModes.gfy, gfyGen);
export const isProd = require('@tycrek/isprod')();
4 years ago
module.exports = {
path,
getTrueHttp,
getTrueDomain,
getS3url,
getDirectUrl,
getResourceColor,
formatTimestamp,
formatBytes,
replaceholder,
getDatedDirname,
randomHexColour,
sanitize,
verify,
renameFile: (req: AssRequest, newName: string) => new Promise((resolve: Function, reject) => {
try {
const paths = [req.file!.destination, newName];
fs.rename(path(req.file!.path), path(...paths));
req.file!.path = Path.join(...paths);
resolve();
} catch (err) {
reject(err);
}
}),
generateToken: () => token(),
generateId,
arrayEquals,
downloadTempS3: (file: FileData) => new Promise((resolve: Function, reject) =>
fetch(getS3url(file.randomId, file.ext))
.then((f2) => f2.body.pipe(fs.createWriteStream(Path.join(__dirname, diskFilePath, sanitize(file.originalname))).on('close', () => resolve())))
.catch(reject)),
}
export const log = logger;
/**
* @type {TLog}
*/
module.exports.log = logger;