diff options
| author | Elizabeth Hunt <me@liz.coffee> | 2025-12-14 20:36:24 -0800 |
|---|---|---|
| committer | Elizabeth Hunt <me@liz.coffee> | 2025-12-14 20:36:24 -0800 |
| commit | 6bf57766feb8321f860baf300140563cd9539053 (patch) | |
| tree | d80ff78c2a7f4dbea79f9ee850542aee1b735ef4 /src/integrations/hcaptcha.ts | |
| download | posthook-6bf57766feb8321f860baf300140563cd9539053.tar.gz posthook-6bf57766feb8321f860baf300140563cd9539053.zip | |
Init
Diffstat (limited to 'src/integrations/hcaptcha.ts')
| -rw-r--r-- | src/integrations/hcaptcha.ts | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/integrations/hcaptcha.ts b/src/integrations/hcaptcha.ts new file mode 100644 index 0000000..78ff356 --- /dev/null +++ b/src/integrations/hcaptcha.ts @@ -0,0 +1,32 @@ +import { Either, type IEither } from '@emprespresso/pengueno'; + +export interface HCaptchaResponse { + success: boolean; + challenge_ts?: string; + hostname?: string; + 'error-codes'?: string[]; +} + +export async function verifyHCaptcha(token: string, secret: string): Promise<IEither<Error, boolean>> { + try { + const response = await fetch('https://hcaptcha.com/siteverify', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ + secret, + response: token, + }), + }); + + if (!response.ok) { + return Either.left(new Error(`hCaptcha verification failed: ${response.statusText}`)); + } + + const result = (await response.json()) as HCaptchaResponse; + return Either.right(result.success); + } catch (err) { + return Either.left(err instanceof Error ? err : new Error(String(err))); + } +} |
