mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add thumbnail dimensions to config (#3262)
* Add thumbnail dimensions to config * Fix default value for thumbnails.enabled * Update comment for thumbnail recreation instructions in config.yaml * Lint config values * Verify config size > 0 * More config lint
This commit is contained in:
@@ -83,13 +83,21 @@ autorun: true
|
|||||||
# Avoids using 'localhost' for autorun in auto mode.
|
# Avoids using 'localhost' for autorun in auto mode.
|
||||||
# use if you don't have 'localhost' in your hosts file
|
# use if you don't have 'localhost' in your hosts file
|
||||||
avoidLocalhost: false
|
avoidLocalhost: false
|
||||||
# Disable thumbnail generation
|
|
||||||
disableThumbnails: false
|
# THUMBNAILING CONFIGURATION
|
||||||
# Thumbnail quality (0-100)
|
thumbnails:
|
||||||
thumbnailsQuality: 95
|
# Enable thumbnail generation
|
||||||
# Generate avatar thumbnails as PNG instead of JPG (preserves transparency but increases filesize by about 100%)
|
enabled: true
|
||||||
# Changing this only affects new thumbnails. To recreate the old ones, clear out your ST/thumbnails/ folder.
|
# Image format of avatar thumbnails:
|
||||||
avatarThumbnailsPng: false
|
# * "jpg": best compression with adjustable quality, no transparency
|
||||||
|
# * "png": preserves transparency but increases filesize by about 100%
|
||||||
|
# Changing this only affects new thumbnails. To recreate the old ones, clear out /thumbnails folder in your user data.
|
||||||
|
format: "jpg"
|
||||||
|
# JPG thumbnail quality (0-100)
|
||||||
|
quality: 95
|
||||||
|
# Maximum thumbnail dimensions per type [width, height]
|
||||||
|
dimensions: { 'bg': [160, 90], 'avatar': [96, 144] }
|
||||||
|
|
||||||
# Allow secret keys exposure via API
|
# Allow secret keys exposure via API
|
||||||
allowKeysExposure: false
|
allowKeysExposure: false
|
||||||
# Skip new default content checks
|
# Skip new default content checks
|
||||||
|
@@ -28,6 +28,24 @@ const color = {
|
|||||||
white: (mess) => color.byNum(mess, 37),
|
white: (mess) => color.byNum(mess, 37),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const keyMigrationMap = [
|
||||||
|
{
|
||||||
|
oldKey: 'disableThumbnails',
|
||||||
|
newKey: 'thumbnails.enabled',
|
||||||
|
migrate: (value) => !value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'thumbnailsQuality',
|
||||||
|
newKey: 'thumbnails.quality',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'avatarThumbnailsPng',
|
||||||
|
newKey: 'thumbnails.format',
|
||||||
|
migrate: (value) => (value ? 'png' : 'jpg'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all keys from an object recursively.
|
* Gets all keys from an object recursively.
|
||||||
* @param {object} obj Object to get all keys from
|
* @param {object} obj Object to get all keys from
|
||||||
@@ -83,6 +101,24 @@ function addMissingConfigValues() {
|
|||||||
const defaultConfig = yaml.parse(fs.readFileSync(path.join(process.cwd(), './default/config.yaml'), 'utf8'));
|
const defaultConfig = yaml.parse(fs.readFileSync(path.join(process.cwd(), './default/config.yaml'), 'utf8'));
|
||||||
let config = yaml.parse(fs.readFileSync(path.join(process.cwd(), './config.yaml'), 'utf8'));
|
let config = yaml.parse(fs.readFileSync(path.join(process.cwd(), './config.yaml'), 'utf8'));
|
||||||
|
|
||||||
|
// Migrate old keys to new keys
|
||||||
|
const migratedKeys = [];
|
||||||
|
for (const { oldKey, newKey, migrate } of keyMigrationMap) {
|
||||||
|
if (_.has(config, oldKey)) {
|
||||||
|
const oldValue = _.get(config, oldKey);
|
||||||
|
const newValue = migrate(oldValue);
|
||||||
|
_.set(config, newKey, newValue);
|
||||||
|
_.unset(config, oldKey);
|
||||||
|
|
||||||
|
migratedKeys.push({
|
||||||
|
oldKey,
|
||||||
|
newKey,
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get all keys from the original config
|
// Get all keys from the original config
|
||||||
const originalKeys = getAllKeys(config);
|
const originalKeys = getAllKeys(config);
|
||||||
|
|
||||||
@@ -95,11 +131,18 @@ function addMissingConfigValues() {
|
|||||||
// Find the keys that were added
|
// Find the keys that were added
|
||||||
const addedKeys = _.difference(updatedKeys, originalKeys);
|
const addedKeys = _.difference(updatedKeys, originalKeys);
|
||||||
|
|
||||||
if (addedKeys.length === 0) {
|
if (addedKeys.length === 0 && migratedKeys.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Adding missing config values to config.yaml:', addedKeys);
|
if (addedKeys.length > 0) {
|
||||||
|
console.log('Adding missing config values to config.yaml:', addedKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (migratedKeys.length > 0) {
|
||||||
|
console.log('Migrating config values in config.yaml:', migratedKeys);
|
||||||
|
}
|
||||||
|
|
||||||
fs.writeFileSync('./config.yaml', yaml.stringify(config));
|
fs.writeFileSync('./config.yaml', yaml.stringify(config));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(color.red('FATAL: Could not add missing config values to config.yaml'), error);
|
console.error(color.red('FATAL: Could not add missing config values to config.yaml'), error);
|
||||||
|
@@ -12,9 +12,12 @@ import { getAllUserHandles, getUserDirectories } from '../users.js';
|
|||||||
import { getConfigValue } from '../util.js';
|
import { getConfigValue } from '../util.js';
|
||||||
import { jsonParser } from '../express-common.js';
|
import { jsonParser } from '../express-common.js';
|
||||||
|
|
||||||
const thumbnailsDisabled = getConfigValue('disableThumbnails', false);
|
const thumbnailsEnabled = !!getConfigValue('thumbnails.enabled', true);
|
||||||
const quality = getConfigValue('thumbnailsQuality', 95);
|
const quality = Math.min(100, Math.max(1, parseInt(getConfigValue('thumbnails.quality', 95))));
|
||||||
const pngFormat = getConfigValue('avatarThumbnailsPng', false);
|
const pngFormat = String(getConfigValue('thumbnails.format', 'jpg')).toLowerCase().trim() === 'png';
|
||||||
|
|
||||||
|
/** @type {Record<string, number[]>} */
|
||||||
|
const dimensions = getConfigValue('thumbnails.dimensions', { 'bg': [160, 90], 'avatar': [96, 144] });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a path to thumbnail folder based on the type.
|
* Gets a path to thumbnail folder based on the type.
|
||||||
@@ -114,16 +117,16 @@ async function generateThumbnail(directories, type, file) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageSizes = { 'bg': [160, 90], 'avatar': [96, 144] };
|
|
||||||
const mySize = imageSizes[type];
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let buffer;
|
let buffer;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const size = dimensions[type];
|
||||||
const image = await jimp.read(pathToOriginalFile);
|
const image = await jimp.read(pathToOriginalFile);
|
||||||
const imgType = type == 'avatar' && pngFormat ? 'image/png' : 'image/jpeg';
|
const imgType = type == 'avatar' && pngFormat ? 'image/png' : 'image/jpeg';
|
||||||
buffer = await image.cover(mySize[0], mySize[1]).quality(quality).getBufferAsync(imgType);
|
const width = !isNaN(size?.[0]) && size?.[0] > 0 ? size[0] : image.bitmap.width;
|
||||||
|
const height = !isNaN(size?.[1]) && size?.[1] > 0 ? size[1] : image.bitmap.height;
|
||||||
|
buffer = await image.cover(width, height).quality(quality).getBufferAsync(imgType);
|
||||||
}
|
}
|
||||||
catch (inner) {
|
catch (inner) {
|
||||||
console.warn(`Thumbnailer can not process the image: ${pathToOriginalFile}. Using original size`);
|
console.warn(`Thumbnailer can not process the image: ${pathToOriginalFile}. Using original size`);
|
||||||
@@ -193,7 +196,7 @@ router.get('/', jsonParser, async function (request, response) {
|
|||||||
return response.sendStatus(403);
|
return response.sendStatus(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thumbnailsDisabled) {
|
if (!thumbnailsEnabled) {
|
||||||
const folder = getOriginalFolder(request.user.directories, type);
|
const folder = getOriginalFolder(request.user.directories, type);
|
||||||
|
|
||||||
if (folder === undefined) {
|
if (folder === undefined) {
|
||||||
|
Reference in New Issue
Block a user