fix(头像生成): 当邮箱为空时使用昵称生成头像哈希
修复 getCravatar 函数在邮箱为空时无法生成有效头像的问题。现在当邮箱为空或不存在时,函数会尝试使用昵称作为替代标识符生成 MD5 哈希。如果两者都不可用,则返回默认占位符头像,确保始终返回有效的头像 URL。
This commit is contained in:
@@ -65,7 +65,7 @@ export const listComments = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
? row.likes
|
? row.likes
|
||||||
: 0,
|
: 0,
|
||||||
ua: row.ua,
|
ua: row.ua,
|
||||||
avatar: await getCravatar(row.email, avatarPrefix || undefined),
|
avatar: await getCravatar(row.email, row.name, avatarPrefix || undefined),
|
||||||
isAdmin: adminEmail && row.email === adminEmail
|
isAdmin: adminEmail && row.email === adminEmail
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export const getComments = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
// 2. 批量处理头像并格式化
|
// 2. 批量处理头像并格式化
|
||||||
const allComments = await Promise.all(results.map(async (row: any) => ({
|
const allComments = await Promise.all(results.map(async (row: any) => ({
|
||||||
...row,
|
...row,
|
||||||
avatar: await getCravatar(row.email, avatar_prefix || undefined),
|
avatar: await getCravatar(row.email, row.name, avatar_prefix || undefined),
|
||||||
isAdmin: adminEmail && row.email === adminEmail,
|
isAdmin: adminEmail && row.email === adminEmail,
|
||||||
replies: []
|
replies: []
|
||||||
})))
|
})))
|
||||||
|
|||||||
@@ -4,16 +4,38 @@
|
|||||||
const DEFAULT_AVATAR_PREFIX = 'https://gravatar.com/avatar';
|
const DEFAULT_AVATAR_PREFIX = 'https://gravatar.com/avatar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 辅助函数:生成 gravatar.com 头像地址 (MD5 算法)
|
* 当缺少邮箱或邮箱为空时使用的占位 hash
|
||||||
* @param email - 邮箱地址
|
* 32 个 0,符合 MD5 长度要求,Gravatar 会回退到默认头像样式
|
||||||
* @param prefix - 头像服务前缀,默认为 https://gravatar.com/avatar
|
|
||||||
*/
|
*/
|
||||||
export const getCravatar = async (email: string, prefix?: string): Promise<string> => {
|
const DEFAULT_AVATAR_HASH = '00000000000000000000000000000000';
|
||||||
const cleanEmail = email.trim().toLowerCase();
|
|
||||||
const msgUint8 = new TextEncoder().encode(cleanEmail);
|
/**
|
||||||
const hashBuffer = await crypto.subtle.digest('MD5', msgUint8);
|
* 辅助函数:生成 gravatar.com 头像地址 (MD5 算法)
|
||||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
* 优先使用邮箱;当邮箱不存在或为空时,使用昵称计算 MD5。
|
||||||
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
*/
|
||||||
const avatarPrefix = prefix || DEFAULT_AVATAR_PREFIX;
|
export const getCravatar = async (
|
||||||
return `${avatarPrefix}/${hashHex}?s=200&d=retro`;
|
email: string | null | undefined,
|
||||||
};
|
name?: string | null | undefined,
|
||||||
|
prefix?: string
|
||||||
|
): Promise<string> => {
|
||||||
|
const avatarPrefix = prefix || DEFAULT_AVATAR_PREFIX;
|
||||||
|
|
||||||
|
const pickIdentifier = (value: string | null | undefined) => {
|
||||||
|
if (!value || typeof value !== 'string') return null;
|
||||||
|
const trimmed = value.trim().toLowerCase();
|
||||||
|
return trimmed || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const identifier = pickIdentifier(email) || pickIdentifier(name);
|
||||||
|
|
||||||
|
if (!identifier) {
|
||||||
|
return `${avatarPrefix}/${DEFAULT_AVATAR_HASH}?s=200&d=retro`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgUint8 = new TextEncoder().encode(identifier);
|
||||||
|
const hashBuffer = await crypto.subtle.digest('MD5', msgUint8);
|
||||||
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||||
|
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
|
||||||
|
return `${avatarPrefix}/${hashHex}?s=200&d=retro`;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user