kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
210 wiersze
5.6 KiB
TypeScript
210 wiersze
5.6 KiB
TypeScript
import crypto from 'node:crypto'
|
||
|
||
import {
|
||
aiFunction,
|
||
AIFunctionsProvider,
|
||
getEnv,
|
||
throttleKy
|
||
} from '@agentic/core'
|
||
import defaultKy, { type KyInstance } from 'ky'
|
||
import pThrottle from 'p-throttle'
|
||
import { z } from 'zod'
|
||
|
||
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
|
||
first_name?: string
|
||
last_name?: string
|
||
/** 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. */
|
||
verified_accounts: VerifiedAccount[]
|
||
/** A phonetic guide to pronouncing the user’s name. */
|
||
pronunciation: string
|
||
/** The pronouns the user prefers to use. */
|
||
pronouns: string
|
||
|
||
is_organization?: boolean
|
||
links?: Link[]
|
||
interests?: any[]
|
||
gallery?: GalleryImage[]
|
||
payments?: {
|
||
links?: Link[]
|
||
crypto_wallets?: CryptoWallet[]
|
||
}
|
||
|
||
/** 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
|
||
|
||
contact_info?: ContactInfo
|
||
}
|
||
|
||
export interface VerifiedAccount {
|
||
service_type: string
|
||
service_label: string
|
||
service_icon: string
|
||
url: string
|
||
is_hidden: boolean
|
||
}
|
||
|
||
export interface Link {
|
||
label: string
|
||
url: string
|
||
}
|
||
|
||
export interface GalleryImage {
|
||
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
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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}`]] : []
|
||
)
|
||
})
|
||
}
|
||
|
||
/**
|
||
* Get Gravatar profile by email. Returns a profile object or `undefined` if not found.
|
||
*/
|
||
@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
|
||
}
|
||
}
|
||
|
||
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}`
|
||
}
|
||
}
|