()
| 399 | * Returns null if the user's email cannot be retrieved or avatar fetch fails. |
| 400 | */ |
| 401 | export async function getNpmAvatar(): Promise<string | null> { |
| 402 | const result = await execNpm(['profile', 'get', 'email', '--json'], { silent: true }) |
| 403 | if (result.exitCode !== 0 || !result.stdout) { |
| 404 | return null |
| 405 | } |
| 406 | |
| 407 | try { |
| 408 | const parsed = JSON.parse(result.stdout) as { email?: string } |
| 409 | if (!parsed.email) { |
| 410 | return null |
| 411 | } |
| 412 | |
| 413 | const email = parsed.email.trim().toLowerCase() |
| 414 | const hash = crypto.createHash('md5').update(email).digest('hex') |
| 415 | const gravatarUrl = `https://www.gravatar.com/avatar/${hash}?s=64&d=retro` |
| 416 | |
| 417 | const response = await fetch(gravatarUrl) |
| 418 | if (!response.ok) { |
| 419 | return null |
| 420 | } |
| 421 | |
| 422 | const contentType = response.headers.get('content-type') || 'image/png' |
| 423 | const buffer = await response.arrayBuffer() |
| 424 | const base64 = Buffer.from(buffer).toString('base64') |
| 425 | return `data:${contentType};base64,${base64}` |
| 426 | } catch { |
| 427 | return null |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | export async function orgAddUser( |
| 432 | org: string, |
no test coverage detected