2025-02-27 22:33:25 +00:00
import crypto from 'node:crypto'
import {
aiFunction ,
AIFunctionsProvider ,
getEnv ,
throttleKy
} from '@agentic/core'
import defaultKy , { type KyInstance } from 'ky'
import pThrottle from 'p-throttle'
2025-04-03 15:54:40 +00:00
import { z } from 'zod'
2025-02-27 22:33:25 +00:00
export namespace gravatar {
export const API_BASE_URL = 'https://api.gravatar.com'
// Allow up to 100 unauthenticated requests per hour by default.
export const unauthenticatedThrottle = pThrottle ( {
limit : 100 ,
interval : 60 * 60 * 1000
} )
// Allow up to 1000 authenticated requests per hour by default.
export const authenticatedThrottle = pThrottle ( {
limit : 1000 ,
interval : 60 * 60 * 1000
} )
export type GetProfileByIdentifierOptions = {
email : string
}
export interface Profile {
/** The SHA256 hash of the user’ s primary email address. */
hash : string
/** The user’ s display name that appears on their profile. */
display_name : string
2025-02-27 23:16:35 +00:00
first_name? : string
last_name? : string
2025-02-27 22:33:25 +00:00
/** The full URL to the user’ s Gravatar profile. */
profile_url : string
/** The URL to the user’ s avatar image, if set. */
avatar_url : string
/** Alternative text describing the user’ s avatar. */
avatar_alt_text : string
/** The user’ s geographical location. */
location : string
/** A short biography or description about the user found on their profile. */
description : string
/** The user’ s current job title. */
job_title : string
/** The name of the company where the user is employed. */
company : string
/** An array of verified accounts the user has added to their profile. The number of verified accounts displayed is limited to a maximum of 4 in unauthenticated requests. */
2025-02-28 05:30:16 +00:00
verified_accounts : VerifiedAccount [ ]
2025-02-27 22:33:25 +00:00
/** A phonetic guide to pronouncing the user’ s name. */
pronunciation : string
/** The pronouns the user prefers to use. */
pronouns : string
2025-02-27 23:16:35 +00:00
is_organization? : boolean
links? : Link [ ]
interests? : any [ ]
2025-02-28 05:30:16 +00:00
gallery? : GalleryImage [ ]
2025-02-27 23:16:35 +00:00
payments ? : {
2025-02-28 05:30:16 +00:00
links? : Link [ ]
2025-02-27 23:16:35 +00:00
crypto_wallets? : CryptoWallet [ ]
}
2025-02-27 22:33:25 +00:00
/** The total number of verified accounts the user has added to their profile, including those not displayed on their profile. This property is only provided in authenticated API requests. */
number_verified_accounts? : number
/** The date and time (UTC) when the user last edited their profile. This property is only provided in authenticated API requests. Example: "2021-10-01T12:00:00Z" */
last_profile_edit? : string
/** The date the user registered their account. This property is only provided in authenticated API requests. Example: "2021-10-01" */
registration_date? : string
2025-02-27 23:16:35 +00:00
contact_info? : ContactInfo
}
2025-02-28 05:30:16 +00:00
export interface VerifiedAccount {
2025-02-27 23:16:35 +00:00
service_type : string
service_label : string
service_icon : string
url : string
is_hidden : boolean
}
export interface Link {
label : string
url : string
}
2025-02-28 05:30:16 +00:00
export interface GalleryImage {
2025-02-27 23:16:35 +00:00
url : string
alt_text : string
}
export interface CryptoWallet {
label : string
address : string
}
export interface ContactInfo {
home_phone : string
work_phone : string
cell_phone : string
email : string
contact_form : string
calendar : string
2025-02-27 22:33:25 +00:00
}
}
/ * *
* A client for the Gravatar API .
*
* API key is optional .
*
* @see https : //docs.gravatar.com/getting-started/
* /
export class GravatarClient extends AIFunctionsProvider {
protected readonly ky : KyInstance
protected readonly apiKey? : string
protected readonly apiBaseUrl : string
constructor ( {
apiKey = getEnv ( 'GRAVATAR_API_KEY' ) ,
apiBaseUrl = gravatar . API_BASE_URL ,
timeoutMs = 60 _000 ,
throttle = true ,
ky = defaultKy
} : {
apiKey? : string
apiBaseUrl? : string
timeoutMs? : number
throttle? : boolean
ky? : KyInstance
} = { } ) {
super ( )
// API key is optional
this . apiKey = apiKey
this . apiBaseUrl = apiBaseUrl
const throttledKy = throttle
? throttleKy (
ky ,
apiKey
? gravatar . authenticatedThrottle
: gravatar . unauthenticatedThrottle
)
: ky
this . ky = throttledKy . extend ( {
prefixUrl : apiBaseUrl ,
timeout : timeoutMs ,
headers : Object.fromEntries (
apiKey ? [ [ 'Authorization' , ` Bearer ${ apiKey } ` ] ] : [ ]
)
} )
}
2025-02-28 11:30:39 +00:00
/ * *
* Get Gravatar profile by email . Returns a profile object or ` undefined ` if not found .
* /
2025-02-27 22:33:25 +00:00
@aiFunction ( {
name : 'gravatar_get_profile' ,
description :
'Get Gravatar profile by email. Returns a profile object or `undefined` if not found.' ,
inputSchema : z.object ( {
email : z.string ( )
} )
} )
async getProfileByIdentifier (
emailOrOpts : string | gravatar . GetProfileByIdentifierOptions
) : Promise < gravatar.Profile | undefined > {
const { email } =
typeof emailOrOpts === 'string' ? { email : emailOrOpts } : emailOrOpts
const hashedEmail = crypto
. createHash ( 'SHA256' )
. update ( email . trim ( ) . toLowerCase ( ) , 'utf8' )
. digest ( 'hex' )
try {
return await this . ky
. get ( ` v3/profiles/ ${ hashedEmail } ` )
. json < gravatar.Profile > ( )
} catch ( err : any ) {
if ( err . response ? . status === 404 ) {
return
}
throw err
}
}
2025-02-27 23:16:35 +00:00
async getAvatarForIdentifier (
emailOrOpts : string | gravatar . GetProfileByIdentifierOptions
) : Promise < string > {
const { email } =
typeof emailOrOpts === 'string' ? { email : emailOrOpts } : emailOrOpts
const hashedEmail = crypto
. createHash ( 'SHA256' )
. update ( email . trim ( ) . toLowerCase ( ) , 'utf8' )
. digest ( 'hex' )
return ` https://gravatar.com/avatar/ ${ hashedEmail } `
}
2025-02-27 22:33:25 +00:00
}