Merge branch 'staging' into ipv6_auto

This commit is contained in:
Cohee
2025-02-04 22:45:46 +02:00
146 changed files with 5467 additions and 2021 deletions

View File

@@ -14,6 +14,7 @@ import _ from 'lodash';
import yauzl from 'yauzl';
import mime from 'mime-types';
import { default as simpleGit } from 'simple-git';
import { LOG_LEVELS } from './constants.js';
/**
* Parsed config object.
@@ -150,6 +151,7 @@ export function getHexString(length) {
*/
export function formatBytes(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
@@ -164,14 +166,12 @@ export function formatBytes(bytes) {
*/
export async function extractFileFromZipBuffer(archiveBuffer, fileExtension) {
return await new Promise((resolve, reject) => yauzl.fromBuffer(Buffer.from(archiveBuffer), { lazyEntries: true }, (err, zipfile) => {
if (err) {
reject(err);
}
if (err) reject(err);
zipfile.readEntry();
zipfile.on('entry', (entry) => {
if (entry.fileName.endsWith(fileExtension) && !entry.fileName.startsWith('__MACOSX')) {
console.log(`Extracting ${entry.fileName}`);
console.info(`Extracting ${entry.fileName}`);
zipfile.openReadStream(entry, (err, readStream) => {
if (err) {
reject(err);
@@ -219,7 +219,7 @@ export async function getImageBuffers(zipFilePath) {
zipfile.on('entry', (entry) => {
const mimeType = mime.lookup(entry.fileName);
if (mimeType && mimeType.startsWith('image/') && !entry.fileName.startsWith('__MACOSX')) {
console.log(`Extracting ${entry.fileName}`);
console.info(`Extracting ${entry.fileName}`);
zipfile.openReadStream(entry, (err, readStream) => {
if (err) {
reject(err);
@@ -286,10 +286,11 @@ export function deepMerge(target, source) {
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach(key => {
if (isObject(source[key])) {
if (!(key in target))
if (!(key in target)) {
Object.assign(output, { [key]: source[key] });
else
} else {
output[key] = deepMerge(target[key], source[key]);
}
} else {
Object.assign(output, { [key]: source[key] });
}
@@ -390,10 +391,10 @@ export function generateTimestamp() {
* Remove old backups with the given prefix from a specified directory.
* @param {string} directory The root directory to remove backups from.
* @param {string} prefix File prefix to filter backups by.
* @param {number?} limit Maximum number of backups to keep. If null, the limit is determined by the `numberOfBackups` config value.
* @param {number?} limit Maximum number of backups to keep. If null, the limit is determined by the `backups.common.numberOfBackups` config value.
*/
export function removeOldBackups(directory, prefix, limit = null) {
const MAX_BACKUPS = limit ?? Number(getConfigValue('numberOfBackups', 50));
const MAX_BACKUPS = limit ?? Number(getConfigValue('backups.common.numberOfBackups', 50));
let files = fs.readdirSync(directory).filter(f => f.startsWith(prefix));
if (files.length > MAX_BACKUPS) {
@@ -448,7 +449,7 @@ export function forwardFetchResponse(from, to) {
let statusText = from.statusText;
if (!from.ok) {
console.log(`Streaming request failed with status ${statusCode} ${statusText}`);
console.warn(`Streaming request failed with status ${statusCode} ${statusText}`);
}
// Avoid sending 401 responses as they reset the client Basic auth.
@@ -468,11 +469,12 @@ export function forwardFetchResponse(from, to) {
to.socket.on('close', function () {
if (from.body instanceof Readable) from.body.destroy(); // Close the remote stream
to.end(); // End the Express response
});
from.body.on('end', function () {
console.log('Streaming request finished');
console.info('Streaming request finished');
to.end();
});
} else {
@@ -517,7 +519,7 @@ export function makeHttp2Request(endpoint, method, body, headers) {
});
req.on('end', () => {
console.log(data);
console.debug(data);
resolve(data);
});
});
@@ -757,6 +759,18 @@ export function stringToBool(str) {
return str;
}
/**
* Setup the minimum log level
*/
export function setupLogLevel() {
const logLevel = getConfigValue('minLogLevel', LOG_LEVELS.DEBUG);
globalThis.console.debug = logLevel <= LOG_LEVELS.DEBUG ? console.debug : () => {};
globalThis.console.info = logLevel <= LOG_LEVELS.INFO ? console.info : () => {};
globalThis.console.warn = logLevel <= LOG_LEVELS.WARN ? console.warn : () => {};
globalThis.console.error = logLevel <= LOG_LEVELS.ERROR ? console.error : () => {};
}
/**
* MemoryLimitedMap class that limits the memory usage of string values.
*/
@@ -936,3 +950,14 @@ export class MemoryLimitedMap {
return this.map[Symbol.iterator]();
}
}
/**
* A 'safe' version of `fs.readFileSync()`. Returns the contents of a file if it exists, falling back to a default value if not.
* @param {string} filePath Path of the file to be read.
* @param {Parameters<typeof fs.readFileSync>[1]} options Options object to pass through to `fs.readFileSync()` (default: `{ encoding: 'utf-8' }`).
* @returns The contents at `filePath` if it exists, or `null` if not.
*/
export function safeReadFileSync(filePath, options = { encoding: 'utf-8' }) {
if (fs.existsSync(filePath)) return fs.readFileSync(filePath, options);
return null;
}