@prosopo/procaptcha-audio 0.0.0-stage → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +52 -0
  2. package/.turbo/turbo-build$colon$tsc.log +53 -0
  3. package/.turbo/turbo-build.log +54 -0
  4. package/CHANGELOG.md +35 -0
  5. package/LICENSE +201 -0
  6. package/dist/_virtual/_rolldown/runtime.js +3 -0
  7. package/dist/cjs/components/audioPlayer.cjs +275 -0
  8. package/dist/cjs/components/procaptchaAudio.cjs +7 -0
  9. package/dist/cjs/components/procaptchaWidget.cjs +195 -0
  10. package/dist/cjs/index.cjs +8 -0
  11. package/dist/cjs/services/Manager.cjs +218 -0
  12. package/dist/components/audioPlayer.d.ts +18 -0
  13. package/dist/components/audioPlayer.d.ts.map +1 -0
  14. package/dist/components/audioPlayer.js +275 -0
  15. package/dist/components/audioPlayer.js.map +1 -0
  16. package/dist/components/procaptchaAudio.d.ts +7 -0
  17. package/dist/components/procaptchaAudio.d.ts.map +1 -0
  18. package/dist/components/procaptchaAudio.js +6 -0
  19. package/dist/components/procaptchaAudio.js.map +1 -0
  20. package/dist/components/procaptchaWidget.d.ts +7 -0
  21. package/dist/components/procaptchaWidget.d.ts.map +1 -0
  22. package/dist/components/procaptchaWidget.js +195 -0
  23. package/dist/components/procaptchaWidget.js.map +1 -0
  24. package/dist/index.d.ts +4 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +5 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/services/Manager.d.ts +10 -0
  29. package/dist/services/Manager.d.ts.map +1 -0
  30. package/dist/services/Manager.js +217 -0
  31. package/dist/services/Manager.js.map +1 -0
  32. package/dist/tests/audioPlayer.unit.test.d.ts +2 -0
  33. package/dist/tests/audioPlayer.unit.test.d.ts.map +1 -0
  34. package/dist/tests/audioPlayer.unit.test.js +341 -0
  35. package/dist/tests/audioPlayer.unit.test.js.map +1 -0
  36. package/dist/tests/domHarness.d.ts +20 -0
  37. package/dist/tests/domHarness.d.ts.map +1 -0
  38. package/dist/tests/domHarness.js +56 -0
  39. package/dist/tests/domHarness.js.map +1 -0
  40. package/dist/tests/manager.unit.test.d.ts +2 -0
  41. package/dist/tests/manager.unit.test.d.ts.map +1 -0
  42. package/dist/tests/manager.unit.test.js +627 -0
  43. package/dist/tests/manager.unit.test.js.map +1 -0
  44. package/dist/tests/managerHarness.d.ts +21 -0
  45. package/dist/tests/managerHarness.d.ts.map +1 -0
  46. package/dist/tests/managerHarness.js +67 -0
  47. package/dist/tests/managerHarness.js.map +1 -0
  48. package/dist/tests/procaptchaAudio.test-d.d.ts +2 -0
  49. package/dist/tests/procaptchaAudio.test-d.d.ts.map +1 -0
  50. package/dist/tests/procaptchaAudio.test-d.js +103 -0
  51. package/dist/tests/procaptchaAudio.test-d.js.map +1 -0
  52. package/dist/tests/procaptchaAudio.unit.test.d.ts +2 -0
  53. package/dist/tests/procaptchaAudio.unit.test.d.ts.map +1 -0
  54. package/dist/tests/procaptchaAudio.unit.test.js +93 -0
  55. package/dist/tests/procaptchaAudio.unit.test.js.map +1 -0
  56. package/dist/tests/procaptchaWidget.unit.test.d.ts +2 -0
  57. package/dist/tests/procaptchaWidget.unit.test.d.ts.map +1 -0
  58. package/dist/tests/procaptchaWidget.unit.test.js +597 -0
  59. package/dist/tests/procaptchaWidget.unit.test.js.map +1 -0
  60. package/dist/tests/setup.d.ts +2 -0
  61. package/dist/tests/setup.d.ts.map +1 -0
  62. package/dist/tests/setup.js +12 -0
  63. package/dist/tests/setup.js.map +1 -0
  64. package/package.json +70 -3
  65. package/vite.cjs.config.ts +22 -0
  66. package/vite.esm.config.ts +20 -0
  67. package/vite.test.config.ts +26 -0
  68. package/README.md +0 -3
@@ -0,0 +1,218 @@
1
+ let _prosopo_procaptcha_common = require("@prosopo/procaptcha-common");
2
+ let _prosopo_types = require("@prosopo/types");
3
+ let _polkadot_util_string = require("@polkadot/util/string");
4
+ let _prosopo_api = require("@prosopo/api");
5
+ let _prosopo_common = require("@prosopo/common");
6
+ let _prosopo_util = require("@prosopo/util");
7
+ let _prosopo_util_crypto = require("@prosopo/util-crypto");
8
+ //#region src/services/Manager.ts
9
+ var Manager = (configInput, state, onStateUpdate, callbacks, frictionlessState, getHoneypotValue, onReloadRequest) => {
10
+ const events = (0, _prosopo_procaptcha_common.getDefaultEvents)(callbacks);
11
+ let storedChallengeResponse;
12
+ let storedProviderApi;
13
+ let storedProviderUrl;
14
+ let storedUser;
15
+ let storedClickX;
16
+ let storedClickY;
17
+ let previousProviderUrl;
18
+ const spentSession = (0, _prosopo_procaptcha_common.createSpentSessionGuard)();
19
+ const defaultState = () => {
20
+ return {
21
+ showModal: false,
22
+ loading: false,
23
+ index: 0,
24
+ challenge: void 0,
25
+ solutions: void 0,
26
+ isHuman: false,
27
+ captchaApi: void 0,
28
+ account: void 0
29
+ };
30
+ };
31
+ const onFailed = () => {
32
+ updateState({
33
+ isHuman: false,
34
+ loading: false
35
+ });
36
+ events.onFailed();
37
+ resetState(frictionlessState?.restart);
38
+ };
39
+ const getConfig = () => {
40
+ const config = {
41
+ userAccountAddress: configInput.userAccountAddress || "",
42
+ ...configInput
43
+ };
44
+ if (state.account) config.userAccountAddress = state.account.account.address;
45
+ return _prosopo_types.ProcaptchaConfigSchema.parse(config);
46
+ };
47
+ const getAccount = () => {
48
+ if (!state.account) throw new _prosopo_common.ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", { context: { error: "Account not loaded" } });
49
+ return { account: state.account };
50
+ };
51
+ const getDappAccount = () => {
52
+ if (!state.dappAccount) throw new _prosopo_common.ProsopoEnvError("GENERAL.SITE_KEY_MISSING");
53
+ return state.dappAccount;
54
+ };
55
+ const updateState = (0, _prosopo_procaptcha_common.buildUpdateState)(state, onStateUpdate);
56
+ const lifecycle = (0, _prosopo_procaptcha_common.createManagerLifecycle)(state, updateState);
57
+ const resetState = (frictionlessRestart) => {
58
+ lifecycle.clearTimers();
59
+ updateState(defaultState());
60
+ events.onReset();
61
+ if (frictionlessRestart) frictionlessRestart();
62
+ storedChallengeResponse = void 0;
63
+ storedProviderApi = void 0;
64
+ storedProviderUrl = void 0;
65
+ storedUser = void 0;
66
+ storedClickX = void 0;
67
+ storedClickY = void 0;
68
+ };
69
+ const setValidChallengeTimeout = () => {
70
+ lifecycle.expireSolutionAfter(getConfig().captchas.audio.solutionTimeout, () => {
71
+ updateState({ isHuman: false });
72
+ events.onExpired();
73
+ resetState(frictionlessState?.restart);
74
+ });
75
+ };
76
+ const start = async (x = 0, y = 0) => {
77
+ await (0, _prosopo_procaptcha_common.providerRetry)(async () => {
78
+ if (state.loading) return;
79
+ if (state.isHuman) return;
80
+ resetState();
81
+ storedClickX = x;
82
+ storedClickY = y;
83
+ updateState({ loading: true });
84
+ updateState({ attemptCount: state.attemptCount + 1 });
85
+ const config = getConfig();
86
+ const selectAccount = async () => {
87
+ if (frictionlessState) return frictionlessState.userAccount;
88
+ return new (await ((0, _prosopo_procaptcha_common.ExtensionLoader)(config.web2)))().getAccount(config);
89
+ };
90
+ const user = await selectAccount();
91
+ const userAccount = user.account.address;
92
+ updateState({ account: { account: { address: userAccount } } });
93
+ updateState({ dappAccount: config.account.address });
94
+ await (0, _prosopo_util.sleep)(100);
95
+ if (!config.web2 && !config.userAccountAddress) throw new _prosopo_common.ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", { context: { error: "Account address has not been set for web3 mode" } });
96
+ let getRandomProviderResponse = void 0;
97
+ if (frictionlessState?.provider) getRandomProviderResponse = frictionlessState.provider;
98
+ else {
99
+ const currentConfig = getConfig();
100
+ getRandomProviderResponse = await (0, _prosopo_procaptcha_common.getProcaptchaRandomActiveProvider)(currentConfig.defaultEnvironment, (0, _prosopo_procaptcha_common.pickIpMode)(currentConfig), {
101
+ attempt: state.attemptCount,
102
+ excludeUrl: previousProviderUrl
103
+ });
104
+ }
105
+ const providerUrl = getRandomProviderResponse.provider.url;
106
+ previousProviderUrl = providerUrl;
107
+ const providerApi = new _prosopo_api.ProviderApi(providerUrl, getDappAccount());
108
+ const challengeSessionId = frictionlessState?.sessionId;
109
+ if (spentSession.isSpent(challengeSessionId)) {
110
+ updateState({
111
+ loading: false,
112
+ error: {
113
+ message: "No session found",
114
+ key: "CAPTCHA.NO_SESSION_FOUND"
115
+ }
116
+ });
117
+ events.onError(/* @__PURE__ */ new Error("No session found"));
118
+ return;
119
+ }
120
+ const simdReadingsOnChallenge = frictionlessState?.getSimdReadings ? await frictionlessState.getSimdReadings(0) : void 0;
121
+ const challenge = await providerApi.getAudioCaptchaChallenge(userAccount, getDappAccount(), challengeSessionId, simdReadingsOnChallenge);
122
+ spentSession.markSpent(challengeSessionId);
123
+ if (challenge.error) {
124
+ updateState({
125
+ loading: false,
126
+ error: {
127
+ message: challenge.error.message,
128
+ key: challenge.error.key || "API.UNKNOWN_ERROR"
129
+ }
130
+ });
131
+ return;
132
+ }
133
+ storedChallengeResponse = challenge;
134
+ storedProviderApi = providerApi;
135
+ storedProviderUrl = providerUrl;
136
+ storedUser = user;
137
+ updateState({ loading: false });
138
+ }, async () => {
139
+ await start(x, y);
140
+ }, () => {
141
+ resetState();
142
+ }, state.attemptCount, 3);
143
+ return storedChallengeResponse;
144
+ };
145
+ const submitSolution = async (answer, replays, audioEvents) => {
146
+ if (!storedChallengeResponse || !storedProviderApi || !storedProviderUrl || !storedUser) throw new _prosopo_common.ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", { context: { error: "No challenge data available. Call start() first." } });
147
+ updateState({ loading: true });
148
+ try {
149
+ const challenge = storedChallengeResponse;
150
+ const providerApi = storedProviderApi;
151
+ const providerUrl = storedProviderUrl;
152
+ const user = storedUser;
153
+ const signer = user.extension?.signer;
154
+ if (!signer || !signer.signRaw) throw new _prosopo_common.ProsopoEnvError("GENERAL.CANT_FIND_KEYRINGPAIR", { context: { error: "Signer is not defined, cannot sign message to prove account ownership" } });
155
+ const userTimestampSignature = await signer.signRaw({
156
+ address: user.account.address,
157
+ data: (0, _polkadot_util_string.stringToHex)(challenge[_prosopo_types.ApiParams.timestamp].toString()),
158
+ type: "bytes"
159
+ });
160
+ const encryptedBehavioralData = await (0, _prosopo_procaptcha_common.encryptBehavioralDataForSubmit)(frictionlessState);
161
+ let salt;
162
+ if (storedClickX !== void 0 && storedClickY !== void 0) {
163
+ const coords = [storedClickX, storedClickY];
164
+ const randomSalt = (0, _prosopo_util_crypto.randomAsHex)(coords.map((coord) => coord.toString(16).length + 4).reduce((acc, curr) => acc + curr, 0));
165
+ salt = (0, _prosopo_util.embedData)(randomSalt, coords);
166
+ }
167
+ const simdReadings = await (0, _prosopo_procaptcha_common.getSimdReadingsForSubmit)(frictionlessState);
168
+ const clientMetaData = (0, _prosopo_procaptcha_common.buildClientMetaData)(getHoneypotValue?.(), getConfig().clientSessionId);
169
+ const verifiedSolution = await providerApi.submitAudioCaptchaSolution(challenge, getAccount().account.account.address, getDappAccount(), answer, replays, audioEvents, userTimestampSignature.signature.toString(), encryptedBehavioralData, salt, simdReadings, clientMetaData);
170
+ if (lifecycle.isDisposed()) return false;
171
+ if (verifiedSolution[_prosopo_types.ApiParams.verified]) {
172
+ updateState({
173
+ isHuman: true,
174
+ loading: false
175
+ });
176
+ events.onHuman((0, _prosopo_types.encodeProcaptchaOutput)({
177
+ [_prosopo_types.ApiParams.providerUrl]: providerUrl,
178
+ [_prosopo_types.ApiParams.user]: getAccount().account.account.address,
179
+ [_prosopo_types.ApiParams.dapp]: getDappAccount(),
180
+ [_prosopo_types.ApiParams.challenge]: challenge.challenge,
181
+ [_prosopo_types.ApiParams.timestamp]: challenge.timestamp,
182
+ [_prosopo_types.ApiParams.signature]: {
183
+ [_prosopo_types.ApiParams.provider]: challenge.signature.provider,
184
+ [_prosopo_types.ApiParams.user]: { [_prosopo_types.ApiParams.timestamp]: userTimestampSignature.signature.toString() }
185
+ },
186
+ [_prosopo_types.ApiParams.captchaType]: _prosopo_types.CaptchaType.audio
187
+ }));
188
+ setValidChallengeTimeout();
189
+ return true;
190
+ }
191
+ if (onReloadRequest) {
192
+ updateState({
193
+ isHuman: false,
194
+ loading: false
195
+ });
196
+ events.onFailed();
197
+ const retryX = storedClickX;
198
+ const retryY = storedClickY;
199
+ resetState();
200
+ onReloadRequest(retryX, retryY);
201
+ return false;
202
+ }
203
+ onFailed();
204
+ return false;
205
+ } catch (error) {
206
+ updateState({ loading: false });
207
+ throw error;
208
+ }
209
+ };
210
+ return {
211
+ start,
212
+ submitSolution,
213
+ resetState,
214
+ dispose: lifecycle.dispose
215
+ };
216
+ };
217
+ //#endregion
218
+ exports.Manager = Manager;
@@ -0,0 +1,18 @@
1
+ import type { Translator } from "@prosopo/locale";
2
+ import { type Component } from "@prosopo/procaptcha-common";
3
+ import type { AudioEvent, PlacementType } from "@prosopo/types";
4
+ import type { Theme } from "@prosopo/widget-skeleton";
5
+ export interface AudioPlayerProps {
6
+ clip: string;
7
+ characterCount: number;
8
+ onComplete: (answer: string, replays: number, audioEvents: AudioEvent[]) => void;
9
+ showRetry: boolean;
10
+ submitting: boolean;
11
+ theme: Theme;
12
+ translator: Translator;
13
+ placement?: PlacementType;
14
+ anchor?: HTMLElement | null;
15
+ onDismiss?: () => void;
16
+ }
17
+ export declare const mountAudioPlayer: (initialProps: AudioPlayerProps) => Component<AudioPlayerProps>;
18
+ //# sourceMappingURL=audioPlayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioPlayer.d.ts","sourceRoot":"","sources":["../../src/components/audioPlayer.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAGN,KAAK,SAAS,EAOd,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAEhC,IAAI,EAAE,MAAM,CAAC;IAEb,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,CACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,UAAU,EAAE,KACrB,IAAI,CAAC;IACV,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAkCD,eAAO,MAAM,gBAAgB,iBACd,gBAAgB,KAC5B,SAAS,CAAC,gBAAgB,CA4T5B,CAAC"}
@@ -0,0 +1,275 @@
1
+ import { Teardown, applyAttributes, applyStyles, createElement, mountChallengeSurface } from "@prosopo/procaptcha-common";
2
+ //#region src/components/audioPlayer.ts
3
+ var CONTAINER_WIDTH = 320;
4
+ var SHAKE_MS = 500;
5
+ var SHAKE_KEYFRAMES = `
6
+ @keyframes prosopo-audio-shake {
7
+ 0%, 100% { transform: translateX(0); }
8
+ 10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }
9
+ 20%, 40%, 60%, 80% { transform: translateX(4px); }
10
+ }
11
+ `;
12
+ var VISUALLY_HIDDEN = {
13
+ position: "absolute",
14
+ width: "1px",
15
+ height: "1px",
16
+ overflow: "hidden",
17
+ clip: "rect(0 0 0 0)",
18
+ clipPath: "inset(50%)",
19
+ whiteSpace: "nowrap"
20
+ };
21
+ /**
22
+ * The audio challenge. Accessibility is its purpose, so:
23
+ * - every control is a native `<button>` or `<input>`, not a role on a div;
24
+ * - the `<audio>` element is hidden and driven by our buttons, because several
25
+ * browsers' native controls offer the clip as a download;
26
+ * - status changes go to a polite live region, since a screen-reader user
27
+ * cannot see the shake that marks a wrong answer;
28
+ * - nothing autoplays: browsers block audio without a gesture, and a blocked
29
+ * play() looks like a broken widget.
30
+ */
31
+ var mountAudioPlayer = (initialProps) => {
32
+ const teardown = new Teardown();
33
+ let props = initialProps;
34
+ let answer = "";
35
+ let playing = false;
36
+ let visible = false;
37
+ let shaking = false;
38
+ let shakeTimer;
39
+ let replays = 0;
40
+ let hasPlayed = false;
41
+ let events = [];
42
+ let startedAt = Date.now();
43
+ const t = (key, options) => props.translator.t(key, options);
44
+ const record = (kind) => {
45
+ events.push({
46
+ kind,
47
+ t: Date.now() - startedAt
48
+ });
49
+ };
50
+ const style = createElement("style", { text: SHAKE_KEYFRAMES });
51
+ const instruction = createElement("p", { style: {
52
+ margin: 0,
53
+ fontSize: "14px"
54
+ } });
55
+ const audio = createElement("audio", {
56
+ attributes: { preload: "auto" },
57
+ style: { display: "none" }
58
+ });
59
+ const playButton = createElement("button", { attributes: { type: "button" } });
60
+ const playRow = createElement("div", {
61
+ style: {
62
+ display: "flex",
63
+ gap: "8px"
64
+ },
65
+ children: [playButton]
66
+ });
67
+ const input = createElement("input", { attributes: {
68
+ type: "text",
69
+ inputmode: "numeric",
70
+ autocomplete: "off",
71
+ autocorrect: "off",
72
+ autocapitalize: "off",
73
+ spellcheck: "false"
74
+ } });
75
+ const submitButton = createElement("button", { attributes: { type: "button" } });
76
+ const announcer = createElement("div", {
77
+ attributes: {
78
+ "aria-live": "polite",
79
+ "aria-atomic": "true"
80
+ },
81
+ style: VISUALLY_HIDDEN
82
+ });
83
+ if ("production" !== process.env.NODE_ENV) {
84
+ applyAttributes(audio, { "data-cy": "prosopo-audio-clip" });
85
+ applyAttributes(playButton, { "data-cy": "prosopo-audio-play" });
86
+ applyAttributes(input, { "data-cy": "prosopo-audio-answer" });
87
+ applyAttributes(submitButton, { "data-cy": "prosopo-audio-submit" });
88
+ }
89
+ const panel = createElement("div", {
90
+ style: {
91
+ position: "relative",
92
+ display: "flex",
93
+ flexDirection: "column",
94
+ gap: "14px",
95
+ width: `${CONTAINER_WIDTH}px`,
96
+ boxSizing: "border-box",
97
+ padding: "20px",
98
+ borderRadius: "20px",
99
+ transition: "opacity 0.3s ease, transform 0.3s ease"
100
+ },
101
+ children: [
102
+ instruction,
103
+ audio,
104
+ playRow,
105
+ input,
106
+ submitButton,
107
+ announcer
108
+ ]
109
+ });
110
+ const surfaceProps = () => ({
111
+ show: true,
112
+ placement: props.placement,
113
+ anchor: props.anchor,
114
+ onDismiss: props.onDismiss,
115
+ scrim: visible ? "dim" : "none",
116
+ dialogLabel: t("WIDGET.AUDIO_CHALLENGE_LABEL")
117
+ });
118
+ const surface = mountChallengeSurface(surfaceProps());
119
+ surface.content.append(style, panel);
120
+ const announce = (message) => {
121
+ announcer.textContent = message;
122
+ };
123
+ const playLabel = () => {
124
+ if (playing) return t("WIDGET.AUDIO_PLAYING");
125
+ return hasPlayed || answer.length > 0 ? t("WIDGET.AUDIO_REPLAY") : t("WIDGET.AUDIO_PLAY");
126
+ };
127
+ const render = () => {
128
+ const { theme, showRetry, submitting, characterCount } = props;
129
+ const accent = showRetry ? theme.palette.error.main : theme.palette.primary.main;
130
+ const blocked = submitting || 0 === answer.length;
131
+ const buttonStyle = {
132
+ fontFamily: theme.font.fontFamily,
133
+ fontSize: "14px",
134
+ padding: "10px 16px",
135
+ borderRadius: "8px",
136
+ border: `1px solid ${accent}`,
137
+ backgroundColor: "transparent",
138
+ color: accent,
139
+ cursor: "pointer"
140
+ };
141
+ applyStyles(panel, {
142
+ backgroundColor: theme.palette.surface,
143
+ color: theme.palette.onSurface,
144
+ fontFamily: theme.font.fontFamily,
145
+ opacity: visible ? 1 : 0,
146
+ transform: visible ? "scale(1)" : "scale(0.9)",
147
+ animation: shaking ? `prosopo-audio-shake ${SHAKE_MS}ms ease` : "none"
148
+ });
149
+ instruction.textContent = showRetry ? t("WIDGET.AUDIO_INCORRECT") : t("WIDGET.AUDIO_INSTRUCTIONS", { count: characterCount });
150
+ applyStyles(instruction, { color: showRetry ? theme.palette.error.main : theme.palette.onSurface });
151
+ if (audio.getAttribute("src") !== props.clip) audio.setAttribute("src", props.clip);
152
+ playButton.textContent = playLabel();
153
+ applyStyles(playButton, {
154
+ ...buttonStyle,
155
+ flex: 1
156
+ });
157
+ input.maxLength = characterCount * 2;
158
+ input.disabled = submitting;
159
+ if (input.value !== answer) input.value = answer;
160
+ applyAttributes(input, { "aria-label": t("WIDGET.AUDIO_INPUT_LABEL", { count: characterCount }) });
161
+ applyStyles(input, {
162
+ fontFamily: theme.font.fontFamily,
163
+ fontSize: "18px",
164
+ letterSpacing: "0.3em",
165
+ textAlign: "center",
166
+ padding: "10px",
167
+ borderRadius: "8px",
168
+ border: `1px solid ${accent}`,
169
+ backgroundColor: "transparent",
170
+ color: theme.palette.onSurface
171
+ });
172
+ submitButton.textContent = submitting ? t("WIDGET.AUDIO_CHECKING") : t("WIDGET.AUDIO_SUBMIT");
173
+ submitButton.disabled = blocked;
174
+ applyStyles(submitButton, {
175
+ ...buttonStyle,
176
+ backgroundColor: theme.palette.primary.main,
177
+ borderColor: theme.palette.primary.main,
178
+ color: theme.palette.primary.contrastText,
179
+ opacity: blocked ? .5 : 1,
180
+ cursor: blocked ? "not-allowed" : "pointer"
181
+ });
182
+ surface.update(surfaceProps());
183
+ };
184
+ const play = () => {
185
+ const isReplay = hasPlayed;
186
+ audio.currentTime = 0;
187
+ record(isReplay ? "replay" : "play");
188
+ if (isReplay) replays += 1;
189
+ hasPlayed = true;
190
+ const clipAtPlay = props.clip;
191
+ audio.play().then(() => {
192
+ if (clipAtPlay !== props.clip) return;
193
+ playing = true;
194
+ announce(t("WIDGET.AUDIO_PLAYING"));
195
+ render();
196
+ }, () => {
197
+ playing = false;
198
+ announce(t("WIDGET.AUDIO_PLAYBACK_FAILED"));
199
+ render();
200
+ });
201
+ render();
202
+ };
203
+ const submit = () => {
204
+ if (props.submitting || 0 === answer.length) return;
205
+ props.onComplete(answer, replays, [...events]);
206
+ };
207
+ teardown.addEventListener(playButton, "click", play);
208
+ teardown.addEventListener(submitButton, "click", submit);
209
+ teardown.addEventListener(input, "input", () => {
210
+ record("key");
211
+ answer = input.value;
212
+ render();
213
+ });
214
+ teardown.addEventListener(input, "keydown", (event) => {
215
+ if (!(event instanceof KeyboardEvent) || "Enter" !== event.key) return;
216
+ event.preventDefault();
217
+ submit();
218
+ });
219
+ teardown.addEventListener(audio, "ended", () => {
220
+ playing = false;
221
+ announce(t("WIDGET.AUDIO_FINISHED"));
222
+ render();
223
+ });
224
+ teardown.addEventListener(audio, "pause", () => {
225
+ playing = false;
226
+ render();
227
+ });
228
+ const resetForNewClip = () => {
229
+ audio.pause();
230
+ audio.currentTime = 0;
231
+ answer = "";
232
+ playing = false;
233
+ replays = 0;
234
+ hasPlayed = false;
235
+ events = [];
236
+ startedAt = Date.now();
237
+ };
238
+ const startShake = () => {
239
+ shaking = true;
240
+ announce(t("WIDGET.AUDIO_INCORRECT"));
241
+ if (void 0 !== shakeTimer) clearTimeout(shakeTimer);
242
+ shakeTimer = setTimeout(() => {
243
+ shakeTimer = void 0;
244
+ shaking = false;
245
+ render();
246
+ }, SHAKE_MS);
247
+ };
248
+ teardown.add(() => {
249
+ if (void 0 !== shakeTimer) clearTimeout(shakeTimer);
250
+ });
251
+ if (props.showRetry) startShake();
252
+ render();
253
+ input.focus();
254
+ const frameRequest = requestAnimationFrame(() => {
255
+ visible = true;
256
+ render();
257
+ });
258
+ teardown.add(() => cancelAnimationFrame(frameRequest));
259
+ return {
260
+ update: (nextProps) => {
261
+ const previous = props;
262
+ props = nextProps;
263
+ if (nextProps.clip !== previous.clip) resetForNewClip();
264
+ if (nextProps.showRetry && !previous.showRetry) startShake();
265
+ render();
266
+ },
267
+ destroy: () => {
268
+ teardown.run();
269
+ audio.pause();
270
+ surface.destroy();
271
+ }
272
+ };
273
+ };
274
+ //#endregion
275
+ export { mountAudioPlayer };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioPlayer.js","sourceRoot":"","sources":["../../src/components/audioPlayer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type WidgetMountFn } from "@prosopo/procaptcha-common";
2
+ import type { ProcaptchaAudioHandle } from "./procaptchaWidget.js";
3
+ export type { ProcaptchaAudioHandle };
4
+ export type ProcaptchaAudioMountFn = WidgetMountFn<ProcaptchaAudioHandle>;
5
+ export declare const loadProcaptchaAudio: () => Promise<ProcaptchaAudioMountFn>;
6
+ export declare const mountProcaptchaAudio: ProcaptchaAudioMountFn;
7
+ //# sourceMappingURL=procaptchaAudio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procaptchaAudio.d.ts","sourceRoot":"","sources":["../../src/components/procaptchaAudio.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,aAAa,EAAa,MAAM,4BAA4B,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC,MAAM,MAAM,sBAAsB,GAAG,aAAa,CAAC,qBAAqB,CAAC,CAAC;AAE1E,eAAO,MAAM,mBAAmB,QAAa,OAAO,CAAC,sBAAsB,CACR,CAAC;AAEpE,eAAO,MAAM,oBAAoB,EAAE,sBACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { lazyMount } from "@prosopo/procaptcha-common";
2
+ //#region src/components/procaptchaAudio.ts
3
+ var loadProcaptchaAudio = async () => (await import("./procaptchaWidget.js")).mountProcaptchaAudioWidget;
4
+ var mountProcaptchaAudio = lazyMount(loadProcaptchaAudio);
5
+ //#endregion
6
+ export { loadProcaptchaAudio, mountProcaptchaAudio };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procaptchaAudio.js","sourceRoot":"","sources":["../../src/components/procaptchaAudio.ts"],"names":[],"mappings":"AAcA,OAAO,EAAsB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAO3E,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,IAAqC,EAAE,CAC9E,CAAC,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC,0BAA0B,CAAC;AAEpE,MAAM,CAAC,MAAM,oBAAoB,GAChC,SAAS,CAAC,mBAAmB,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type ProcaptchaProps } from "@prosopo/types";
2
+ export interface ProcaptchaAudioHandle {
3
+ destroy(): void;
4
+ }
5
+ export declare const mountProcaptchaAudioWidget: (container: HTMLElement, props: ProcaptchaProps) => ProcaptchaAudioHandle;
6
+ export default mountProcaptchaAudioWidget;
7
+ //# sourceMappingURL=procaptchaWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procaptchaWidget.d.ts","sourceRoot":"","sources":["../../src/components/procaptchaWidget.ts"],"names":[],"mappings":"AAmCA,OAAO,EAIN,KAAK,eAAe,EAEpB,MAAM,gBAAgB,CAAC;AAOxB,MAAM,WAAW,qBAAqB;IACrC,OAAO,IAAI,IAAI,CAAC;CAChB;AAED,eAAO,MAAM,0BAA0B,cAC3B,WAAW,SACf,eAAe,KACpB,qBAoTF,CAAC;AAEF,eAAe,0BAA0B,CAAC"}