WIP blurash & sync card ?
This commit is contained in:
114
server/utils/blurHash.ts
Normal file
114
server/utils/blurHash.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
// server/utils/blurHash.ts
|
||||
import sharp from 'sharp'
|
||||
import { encode } from 'blurhash'
|
||||
import { $fetch } from 'ofetch'
|
||||
import { mkdir, writeFile, unlink } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
// Dossier temporaire pour les images téléchargées
|
||||
const TMP_DIR = join(tmpdir(), 'evilspins-images')
|
||||
|
||||
async function ensureTmpDir() {
|
||||
try {
|
||||
await mkdir(TMP_DIR, { recursive: true })
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadImage(url: string): Promise<string> {
|
||||
await ensureTmpDir()
|
||||
const tmpPath = join(TMP_DIR, `${randomUUID()}.jpg`)
|
||||
|
||||
try {
|
||||
const response = await $fetch(url, {
|
||||
responseType: 'arrayBuffer',
|
||||
headers: {
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
|
||||
Accept: 'image/*,*/*;q=0.8'
|
||||
},
|
||||
// Timeout plus long
|
||||
timeout: 60000, // 60 secondes
|
||||
// Désactiver la compression pour les images
|
||||
headers: {
|
||||
'Accept-Encoding': 'identity'
|
||||
}
|
||||
})
|
||||
|
||||
await writeFile(tmpPath, Buffer.from(response))
|
||||
return tmpPath
|
||||
} catch (error) {
|
||||
// Nettoyer en cas d'erreur
|
||||
try {
|
||||
await unlink(tmpPath).catch(() => {})
|
||||
} catch {
|
||||
/* Ignorer les erreurs de suppression */
|
||||
}
|
||||
console.error(`Failed to download image from ${url}:`, error.message)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
function createDefaultBlurhash() {
|
||||
// Un blurhash plus discret
|
||||
return 'L5H2EC=H00~q^-=wD6xuxvV@%KxZ'
|
||||
}
|
||||
|
||||
export async function generateBlurhash(
|
||||
input: Buffer | string,
|
||||
componentX: number = 4,
|
||||
componentY: number = 3
|
||||
): Promise<string> {
|
||||
let tmpPath: string | null = null
|
||||
|
||||
try {
|
||||
if (typeof input === 'string') {
|
||||
if (input.startsWith('http')) {
|
||||
try {
|
||||
tmpPath = await downloadImage(input)
|
||||
input = tmpPath
|
||||
} catch (error) {
|
||||
console.warn(`Using default blurhash for ${input} due to download error`)
|
||||
return createDefaultBlurhash()
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier si le fichier existe
|
||||
try {
|
||||
const image = sharp(input).resize(32, 32, { fit: 'inside' }).ensureAlpha()
|
||||
|
||||
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true })
|
||||
return encode(new Uint8ClampedArray(data), info.width, info.height, componentX, componentY)
|
||||
} catch (error) {
|
||||
console.warn(`Error processing image ${input}:`, error.message)
|
||||
return createDefaultBlurhash()
|
||||
}
|
||||
} else {
|
||||
// Si c'est déjà un Buffer
|
||||
try {
|
||||
const image = sharp(input).resize(32, 32, { fit: 'inside' }).ensureAlpha()
|
||||
|
||||
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true })
|
||||
return encode(new Uint8ClampedArray(data), info.width, info.height, componentX, componentY)
|
||||
} catch (error) {
|
||||
console.warn('Error processing image buffer:', error.message)
|
||||
return createDefaultBlurhash()
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Unexpected error in generateBlurhash:', error.message)
|
||||
return createDefaultBlurhash()
|
||||
} finally {
|
||||
// Nettoyer le fichier temporaire s'il existe
|
||||
if (tmpPath) {
|
||||
try {
|
||||
await unlink(tmpPath).catch(() => {})
|
||||
} catch {
|
||||
/* Ignorer les erreurs de suppression */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user