81 lines
1.8 KiB
JavaScript
81 lines
1.8 KiB
JavaScript
import bhttp from 'bhttp';
|
|
import unprint from 'unprint';
|
|
import fs from 'fs';
|
|
import sharp from 'sharp';
|
|
|
|
import knex from './knex';
|
|
import initLogger from './logger';
|
|
|
|
const logger = initLogger();
|
|
|
|
async function createThumbnail(data, post) {
|
|
await fs.promises.mkdir('media/thumbnails', { recursive: true });
|
|
|
|
await sharp(data)
|
|
.resize(300, 300)
|
|
.jpeg({
|
|
quality: 80,
|
|
})
|
|
.toFile(`media/thumbnails/${post.id}.jpeg`);
|
|
|
|
await knex('posts')
|
|
.where('id', post.id)
|
|
.update('thumbnail', true);
|
|
|
|
logger.debug(`Saved thumbnail for ${post.id}`);
|
|
}
|
|
|
|
async function generateThumbnail(postId) {
|
|
const post = await knex('posts').where('id', postId).first();
|
|
|
|
if (!post) {
|
|
logger.warn(`Cannot generate thumbnail for non-existent post ${postId}`);
|
|
return;
|
|
}
|
|
|
|
if (!post.link) {
|
|
logger.debug(`Skipped thumbnail generation for text-only post ${postId}`);
|
|
return;
|
|
}
|
|
|
|
const res = await bhttp.get(post.link);
|
|
|
|
if (res.statusCode !== 200) {
|
|
logger.warn(`Failed thumbnail generation for ${post.link} from ${postId} (${res.statusCode})`);
|
|
return;
|
|
}
|
|
|
|
if (res.headers['content-type'].includes('image/')) {
|
|
await createThumbnail(res.body, post);
|
|
return;
|
|
}
|
|
|
|
const { query } = unprint.init(res.body.toString());
|
|
const ogHeader = query.attribute('meta[property="og:image"]', 'content');
|
|
|
|
if (ogHeader) {
|
|
const imgRes = await bhttp.get(ogHeader);
|
|
|
|
if (imgRes.statusCode === 200 && imgRes.headers['content-type'].includes('image/')) {
|
|
await createThumbnail(imgRes.body, post);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function generateMissingThumbnails(force = false) {
|
|
const postsWithoutThumbnail = await knex('posts')
|
|
.select('id')
|
|
.modify((builder) => {
|
|
if (!force) {
|
|
builder.where('thumbnail', false);
|
|
}
|
|
});
|
|
|
|
await Promise.all(postsWithoutThumbnail.map(async (post) => generateThumbnail(post.id)));
|
|
}
|
|
|
|
export {
|
|
generateThumbnail,
|
|
generateMissingThumbnails,
|
|
};
|