From 1fe59f26e4131b6fd97ad9f90aaf510afb094bf0 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Thu, 9 Oct 2025 13:26:57 +0200 Subject: [PATCH] chore: clean up avatar and gravatar files by removing extra blank lines for improved readability --- src/lib/avatars.ts | 94 +++++++++++++++++++++++---------------------- src/lib/gravatar.ts | 60 +++++++++++++++++------------ 2 files changed, 84 insertions(+), 70 deletions(-) diff --git a/src/lib/avatars.ts b/src/lib/avatars.ts index ac9dd7a..c68e6f0 100644 --- a/src/lib/avatars.ts +++ b/src/lib/avatars.ts @@ -1,12 +1,12 @@ -import { getGravatarUrl, isGravatarUrl } from './gravatar' +import { getGravatarUrl, isGravatarUrl } from './gravatar'; -export type AvatarType = 'custom' | 'gravatar' | 'default' +export type AvatarType = 'custom' | 'gravatar' | 'default'; export interface AvatarConfig { - type: AvatarType - url?: string - email?: string - size?: number + type: AvatarType; + url?: string; + email?: string; + size?: number; } /** @@ -15,20 +15,20 @@ export interface AvatarConfig { * @returns URL finale de l'avatar ou null */ export function getAvatarUrl(config: AvatarConfig): string | null { - const { type, url, email, size = 200 } = config + const { type, url, email, size = 200 } = config; switch (type) { case 'custom': - if (!url) return null - return url + if (!url) return null; + return url; case 'gravatar': - if (!email) return null - return getGravatarUrl(email, { size }) + if (!email) return null; + return getGravatarUrl(email, { size }); case 'default': default: - return null + return null; } } @@ -38,22 +38,25 @@ export function getAvatarUrl(config: AvatarConfig): string | null { * @param email Email de l'utilisateur (pour vérifier si c'est déjà un Gravatar) * @returns Type d'avatar détecté */ -export function detectAvatarType(url: string | null | undefined, email?: string): AvatarType { - if (!url) return 'default' - +export function detectAvatarType( + url: string | null | undefined, + email?: string +): AvatarType { + if (!url) return 'default'; + if (isGravatarUrl(url)) { - return 'gravatar' + return 'gravatar'; } - + // Si on a un email et que l'URL correspond à un Gravatar généré pour cet email if (email && typeof url === 'string') { - const expectedGravatarUrl = getGravatarUrl(email) + const expectedGravatarUrl = getGravatarUrl(email); if (url.includes(expectedGravatarUrl.split('?')[0].split('avatar/')[1])) { - return 'gravatar' + return 'gravatar'; } } - - return 'custom' + + return 'custom'; } /** @@ -64,33 +67,33 @@ export function detectAvatarType(url: string | null | undefined, email?: string) * @returns Configuration optimisée pour l'avatar */ export function optimizeAvatarConfig( - url: string | null | undefined, - email: string | undefined, + url: string | null | undefined, + email: string | undefined, size: number = 200 ): AvatarConfig { - const type = detectAvatarType(url, email) - + const type = detectAvatarType(url, email); + switch (type) { case 'gravatar': return { type: 'gravatar', email, - size - } - + size, + }; + case 'custom': return { type: 'custom', url: url!, - size - } - + size, + }; + case 'default': default: return { type: 'default', - size - } + size, + }; } } @@ -101,26 +104,25 @@ export function optimizeAvatarConfig( */ export function validateCustomAvatarUrl(url: string): boolean { try { - const parsedUrl = new URL(url) - + const parsedUrl = new URL(url); + // Vérifier le protocole (seulement HTTPS pour la sécurité) if (parsedUrl.protocol !== 'https:') { - return false + return false; } - + // Vérifier que c'est bien une URL d'image - const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg'] - const hasImageExtension = imageExtensions.some(ext => + const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg']; + const hasImageExtension = imageExtensions.some((ext) => parsedUrl.pathname.toLowerCase().endsWith(ext) - ) - + ); + if (!hasImageExtension && parsedUrl.pathname.includes('.')) { - return false + return false; } - - return true + + return true; } catch { - return false + return false; } } - diff --git a/src/lib/gravatar.ts b/src/lib/gravatar.ts index 6253b15..4d14955 100644 --- a/src/lib/gravatar.ts +++ b/src/lib/gravatar.ts @@ -1,10 +1,18 @@ -import crypto from 'crypto' +import crypto from 'crypto'; export interface GravatarOptions { - size?: number - defaultImage?: '404' | 'mp' | 'identicon' | 'monsterid' | 'wavatar' | 'retro' | 'robohash' | 'blank' - rating?: 'g' | 'pg' | 'r' | 'x' - forcedefault?: 'y' | 'n' + size?: number; + defaultImage?: + | '404' + | 'mp' + | 'identicon' + | 'monsterid' + | 'wavatar' + | 'retro' + | 'robohash' + | 'blank'; + rating?: 'g' | 'pg' | 'r' | 'x'; + forcedefault?: 'y' | 'n'; } /** @@ -14,37 +22,39 @@ export interface GravatarOptions { * @returns URL de l'avatar Gravatar */ export function getGravatarUrl( - email: string, + email: string, options: GravatarOptions = {} ): string { const { size = 200, defaultImage = 'identicon', rating = 'g', - forcedefault = 'n' - } = options + forcedefault = 'n', + } = options; // Hacher l'email en MD5 (en minuscules et trimé) - const normalizedEmail = email.toLowerCase().trim() - const hash = crypto.createHash('md5').update(normalizedEmail).digest('hex') + const normalizedEmail = email.toLowerCase().trim(); + const hash = crypto.createHash('md5').update(normalizedEmail).digest('hex'); // Construire l'URL const params = new URLSearchParams({ size: size.toString(), default: defaultImage, rating, - forcedefault - }) + forcedefault, + }); - return `https://www.gravatar.com/avatar/${hash}?${params.toString()}` + return `https://www.gravatar.com/avatar/${hash}?${params.toString()}`; } /** * Valide si une URL est une URL Gravatar valide */ export function isGravatarUrl(url: string): boolean { - return url.startsWith('https://www.gravatar.com/avatar/') || - url.startsWith('https://gravatar.com/avatar/') + return ( + url.startsWith('https://www.gravatar.com/avatar/') || + url.startsWith('https://gravatar.com/avatar/') + ); } /** @@ -54,16 +64,18 @@ export function isGravatarUrl(url: string): boolean { */ export async function checkGravatarExists(email: string): Promise { try { - const gravatarUrl = getGravatarUrl(email, { defaultImage: '404', forcedefault: 'y' }) - - const response = await fetch(gravatarUrl, { + const gravatarUrl = getGravatarUrl(email, { + defaultImage: '404', + forcedefault: 'y', + }); + + const response = await fetch(gravatarUrl, { method: 'HEAD', - signal: AbortSignal.timeout(5000) // 5s timeout - }) - - return response.ok + signal: AbortSignal.timeout(5000), // 5s timeout + }); + + return response.ok; } catch { - return false + return false; } } -