@prosopo/procaptcha-audio 0.0.0-stage → 0.2.0
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.
- package/.turbo/turbo-build$colon$cjs.log +52 -0
- package/.turbo/turbo-build$colon$tsc.log +53 -0
- package/.turbo/turbo-build.log +54 -0
- package/CHANGELOG.md +25 -0
- package/LICENSE +201 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -0
- package/dist/cjs/components/audioPlayer.cjs +275 -0
- package/dist/cjs/components/procaptchaAudio.cjs +7 -0
- package/dist/cjs/components/procaptchaWidget.cjs +195 -0
- package/dist/cjs/index.cjs +8 -0
- package/dist/cjs/services/Manager.cjs +218 -0
- package/dist/components/audioPlayer.d.ts +18 -0
- package/dist/components/audioPlayer.d.ts.map +1 -0
- package/dist/components/audioPlayer.js +275 -0
- package/dist/components/audioPlayer.js.map +1 -0
- package/dist/components/procaptchaAudio.d.ts +7 -0
- package/dist/components/procaptchaAudio.d.ts.map +1 -0
- package/dist/components/procaptchaAudio.js +6 -0
- package/dist/components/procaptchaAudio.js.map +1 -0
- package/dist/components/procaptchaWidget.d.ts +7 -0
- package/dist/components/procaptchaWidget.d.ts.map +1 -0
- package/dist/components/procaptchaWidget.js +195 -0
- package/dist/components/procaptchaWidget.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/services/Manager.d.ts +10 -0
- package/dist/services/Manager.d.ts.map +1 -0
- package/dist/services/Manager.js +217 -0
- package/dist/services/Manager.js.map +1 -0
- package/dist/tests/audioPlayer.unit.test.d.ts +2 -0
- package/dist/tests/audioPlayer.unit.test.d.ts.map +1 -0
- package/dist/tests/audioPlayer.unit.test.js +341 -0
- package/dist/tests/audioPlayer.unit.test.js.map +1 -0
- package/dist/tests/domHarness.d.ts +20 -0
- package/dist/tests/domHarness.d.ts.map +1 -0
- package/dist/tests/domHarness.js +56 -0
- package/dist/tests/domHarness.js.map +1 -0
- package/dist/tests/manager.unit.test.d.ts +2 -0
- package/dist/tests/manager.unit.test.d.ts.map +1 -0
- package/dist/tests/manager.unit.test.js +627 -0
- package/dist/tests/manager.unit.test.js.map +1 -0
- package/dist/tests/managerHarness.d.ts +21 -0
- package/dist/tests/managerHarness.d.ts.map +1 -0
- package/dist/tests/managerHarness.js +67 -0
- package/dist/tests/managerHarness.js.map +1 -0
- package/dist/tests/procaptchaAudio.test-d.d.ts +2 -0
- package/dist/tests/procaptchaAudio.test-d.d.ts.map +1 -0
- package/dist/tests/procaptchaAudio.test-d.js +103 -0
- package/dist/tests/procaptchaAudio.test-d.js.map +1 -0
- package/dist/tests/procaptchaAudio.unit.test.d.ts +2 -0
- package/dist/tests/procaptchaAudio.unit.test.d.ts.map +1 -0
- package/dist/tests/procaptchaAudio.unit.test.js +93 -0
- package/dist/tests/procaptchaAudio.unit.test.js.map +1 -0
- package/dist/tests/procaptchaWidget.unit.test.d.ts +2 -0
- package/dist/tests/procaptchaWidget.unit.test.d.ts.map +1 -0
- package/dist/tests/procaptchaWidget.unit.test.js +597 -0
- package/dist/tests/procaptchaWidget.unit.test.js.map +1 -0
- package/dist/tests/setup.d.ts +2 -0
- package/dist/tests/setup.d.ts.map +1 -0
- package/dist/tests/setup.js +12 -0
- package/dist/tests/setup.js.map +1 -0
- package/package.json +70 -3
- package/vite.cjs.config.ts +22 -0
- package/vite.esm.config.ts +20 -0
- package/vite.test.config.ts +26 -0
- package/README.md +0 -3
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
let _prosopo_procaptcha_common = require("@prosopo/procaptcha-common");
|
|
2
|
+
//#region src/components/procaptchaAudio.ts
|
|
3
|
+
var loadProcaptchaAudio = async () => (await Promise.resolve().then(() => require("./procaptchaWidget.cjs"))).mountProcaptchaAudioWidget;
|
|
4
|
+
var mountProcaptchaAudio = (0, _prosopo_procaptcha_common.lazyMount)(loadProcaptchaAudio);
|
|
5
|
+
//#endregion
|
|
6
|
+
exports.loadProcaptchaAudio = loadProcaptchaAudio;
|
|
7
|
+
exports.mountProcaptchaAudio = mountProcaptchaAudio;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
const require_Manager = require("../services/Manager.cjs");
|
|
2
|
+
const require_audioPlayer = require("./audioPlayer.cjs");
|
|
3
|
+
let _prosopo_locale = require("@prosopo/locale");
|
|
4
|
+
let _prosopo_procaptcha_common = require("@prosopo/procaptcha-common");
|
|
5
|
+
let _prosopo_types = require("@prosopo/types");
|
|
6
|
+
let _prosopo_widget_skeleton = require("@prosopo/widget-skeleton");
|
|
7
|
+
//#region src/components/procaptchaWidget.ts
|
|
8
|
+
var mountProcaptchaAudioWidget = (container, props) => {
|
|
9
|
+
const teardown = new _prosopo_procaptcha_common.Teardown();
|
|
10
|
+
const config = props.config;
|
|
11
|
+
const i18n = props.i18n;
|
|
12
|
+
const frictionlessState = props.frictionlessState;
|
|
13
|
+
const callbacks = props.callbacks || {};
|
|
14
|
+
const translator = (0, _prosopo_locale.createTranslator)(i18n);
|
|
15
|
+
const isInvisible = _prosopo_types.ModeEnum.invisible === config.mode;
|
|
16
|
+
const theme = "light" === config.theme ? _prosopo_widget_skeleton.lightTheme : _prosopo_widget_skeleton.darkTheme;
|
|
17
|
+
const store = (0, _prosopo_procaptcha_common.createProcaptchaState)();
|
|
18
|
+
let loading = false;
|
|
19
|
+
let audioPhase = "checkbox";
|
|
20
|
+
let challengeData = null;
|
|
21
|
+
let showRetry = true === props.startShowRetry;
|
|
22
|
+
let lastError = store.state.error;
|
|
23
|
+
let lastCoords = null;
|
|
24
|
+
let sessionInvalidatedFired = false;
|
|
25
|
+
let honeypot;
|
|
26
|
+
let checkbox;
|
|
27
|
+
let player;
|
|
28
|
+
const onReload = props.onReload;
|
|
29
|
+
const updateState = (0, _prosopo_procaptcha_common.buildUpdateState)(store.state, store.update);
|
|
30
|
+
const manager = require_Manager.Manager(config, store.state, updateState, callbacks, frictionlessState, () => honeypot?.getValue(), onReload ? (x, y) => onReload(x, y, { showRetry: true }) : void 0);
|
|
31
|
+
const root = (0, _prosopo_procaptcha_common.createElement)("div");
|
|
32
|
+
container.appendChild(root);
|
|
33
|
+
if (frictionlessState?.hp) honeypot = (0, _prosopo_procaptcha_common.mountHoneypot)(root, { encodedQuestion: frictionlessState.hp });
|
|
34
|
+
const reportError = (error) => {
|
|
35
|
+
callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
36
|
+
};
|
|
37
|
+
const returnToCheckbox = () => {
|
|
38
|
+
audioPhase = "checkbox";
|
|
39
|
+
challengeData = null;
|
|
40
|
+
showRetry = false;
|
|
41
|
+
};
|
|
42
|
+
const showChallenge = (challenge) => {
|
|
43
|
+
if (challenge) {
|
|
44
|
+
challengeData = challenge;
|
|
45
|
+
audioPhase = "answering";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const handleAudioComplete = async (answer, replays, audioEvents) => {
|
|
49
|
+
audioPhase = "submitting";
|
|
50
|
+
scheduler.schedule();
|
|
51
|
+
let verified = false;
|
|
52
|
+
try {
|
|
53
|
+
verified = await manager.submitSolution(answer, replays, audioEvents);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
reportError(error);
|
|
56
|
+
}
|
|
57
|
+
if (verified) {
|
|
58
|
+
returnToCheckbox();
|
|
59
|
+
loading = false;
|
|
60
|
+
scheduler.schedule();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
showRetry = true;
|
|
64
|
+
if (onReload) {
|
|
65
|
+
scheduler.schedule();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
audioPhase = "answering";
|
|
69
|
+
scheduler.schedule();
|
|
70
|
+
try {
|
|
71
|
+
const newChallenge = await manager.start();
|
|
72
|
+
if (newChallenge) challengeData = newChallenge;
|
|
73
|
+
else returnToCheckbox();
|
|
74
|
+
} catch {
|
|
75
|
+
returnToCheckbox();
|
|
76
|
+
}
|
|
77
|
+
loading = false;
|
|
78
|
+
scheduler.schedule();
|
|
79
|
+
};
|
|
80
|
+
const handleDismiss = () => {
|
|
81
|
+
returnToCheckbox();
|
|
82
|
+
loading = false;
|
|
83
|
+
scheduler.schedule();
|
|
84
|
+
};
|
|
85
|
+
const playerProps = (challenge) => ({
|
|
86
|
+
clip: challenge.clip,
|
|
87
|
+
characterCount: challenge.characterCount,
|
|
88
|
+
onComplete: (answer, replays, events) => {
|
|
89
|
+
handleAudioComplete(answer, replays, events);
|
|
90
|
+
},
|
|
91
|
+
showRetry,
|
|
92
|
+
submitting: "submitting" === audioPhase,
|
|
93
|
+
theme,
|
|
94
|
+
translator,
|
|
95
|
+
placement: config.placement,
|
|
96
|
+
anchor: props.container,
|
|
97
|
+
onDismiss: handleDismiss
|
|
98
|
+
});
|
|
99
|
+
const runErrorEffect = () => {
|
|
100
|
+
if (store.state.error === lastError) return;
|
|
101
|
+
lastError = store.state.error;
|
|
102
|
+
if (!store.state.error) return;
|
|
103
|
+
loading = false;
|
|
104
|
+
returnToCheckbox();
|
|
105
|
+
if ("CAPTCHA.NO_SESSION_FOUND" !== store.state.error.key) return;
|
|
106
|
+
if (props.onSessionInvalidated && !sessionInvalidatedFired || void 0 !== frictionlessState) {
|
|
107
|
+
loading = true;
|
|
108
|
+
store.update({ error: void 0 });
|
|
109
|
+
}
|
|
110
|
+
if (props.onSessionInvalidated && !sessionInvalidatedFired) {
|
|
111
|
+
sessionInvalidatedFired = true;
|
|
112
|
+
props.onSessionInvalidated(lastCoords?.x, lastCoords?.y);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (frictionlessState) {
|
|
116
|
+
const timer = setTimeout(() => {
|
|
117
|
+
frictionlessState.restart();
|
|
118
|
+
}, 100);
|
|
119
|
+
teardown.add(() => clearTimeout(timer));
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const render = () => {
|
|
123
|
+
runErrorEffect();
|
|
124
|
+
if (("answering" === audioPhase || "submitting" === audioPhase) && null !== challengeData) if (void 0 === player) player = require_audioPlayer.mountAudioPlayer(playerProps(challengeData));
|
|
125
|
+
else player.update(playerProps(challengeData));
|
|
126
|
+
else {
|
|
127
|
+
player?.destroy();
|
|
128
|
+
player = void 0;
|
|
129
|
+
}
|
|
130
|
+
checkbox?.update(checkboxProps());
|
|
131
|
+
};
|
|
132
|
+
const scheduler = (0, _prosopo_procaptcha_common.createRenderScheduler)(render);
|
|
133
|
+
const beginChallenge = async (coords) => {
|
|
134
|
+
if (loading) return;
|
|
135
|
+
loading = true;
|
|
136
|
+
showRetry = false;
|
|
137
|
+
scheduler.schedule();
|
|
138
|
+
if (coords) lastCoords = coords;
|
|
139
|
+
try {
|
|
140
|
+
showChallenge(await manager.start(coords?.x, coords?.y));
|
|
141
|
+
} catch (error) {
|
|
142
|
+
reportError(error);
|
|
143
|
+
} finally {
|
|
144
|
+
loading = false;
|
|
145
|
+
scheduler.schedule();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const checkboxProps = () => ({
|
|
149
|
+
checked: store.state.isHuman,
|
|
150
|
+
theme,
|
|
151
|
+
labelText: translator.isReady() ? translator.t("WIDGET.I_AM_HUMAN") : "",
|
|
152
|
+
error: store.state.error ? (0, _prosopo_locale.localiseErrorMessage)(translator.i18n, store.state.error) : void 0,
|
|
153
|
+
loadingText: translator.t("WIDGET.CHECKING", { defaultValue: "Checking that you are human" }),
|
|
154
|
+
loading: loading || "submitting" === audioPhase,
|
|
155
|
+
onChange: (event) => beginChallenge((0, _prosopo_procaptcha_common.trustedClickCoords)(event))
|
|
156
|
+
});
|
|
157
|
+
if (!isInvisible) checkbox = (0, _prosopo_procaptcha_common.mountCheckbox)(root, checkboxProps());
|
|
158
|
+
teardown.add(scheduler.cancel);
|
|
159
|
+
teardown.add(store.subscribe(scheduler.schedule));
|
|
160
|
+
teardown.add(translator.subscribe(scheduler.schedule));
|
|
161
|
+
const handleExecute = () => {
|
|
162
|
+
beginChallenge();
|
|
163
|
+
};
|
|
164
|
+
if (props.container) teardown.addEventListener(props.container, _prosopo_procaptcha_common.PROCAPTCHA_EXECUTE_EVENT, handleExecute);
|
|
165
|
+
if (isInvisible) teardown.addEventListener(document, _prosopo_procaptcha_common.PROCAPTCHA_EXECUTE_EVENT, handleExecute);
|
|
166
|
+
if (config.language) if (i18n) {
|
|
167
|
+
if (i18n.language !== config.language) i18n.changeLanguage(config.language);
|
|
168
|
+
} else (0, _prosopo_locale.loadI18next)(false, config.language);
|
|
169
|
+
if (props.autoStart) {
|
|
170
|
+
loading = true;
|
|
171
|
+
const coords = props.startCoords;
|
|
172
|
+
lastCoords = coords ?? null;
|
|
173
|
+
scheduler.schedule();
|
|
174
|
+
manager.start(coords?.x ?? 0, coords?.y ?? 0).then((challenge) => {
|
|
175
|
+
showChallenge(challenge);
|
|
176
|
+
loading = false;
|
|
177
|
+
scheduler.schedule();
|
|
178
|
+
}, () => {
|
|
179
|
+
loading = false;
|
|
180
|
+
scheduler.schedule();
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
render();
|
|
184
|
+
return { destroy: () => {
|
|
185
|
+
manager.dispose();
|
|
186
|
+
teardown.run();
|
|
187
|
+
player?.destroy();
|
|
188
|
+
checkbox?.destroy();
|
|
189
|
+
honeypot?.destroy();
|
|
190
|
+
root.parentNode?.removeChild(root);
|
|
191
|
+
} };
|
|
192
|
+
};
|
|
193
|
+
//#endregion
|
|
194
|
+
exports.default = mountProcaptchaAudioWidget;
|
|
195
|
+
exports.mountProcaptchaAudioWidget = mountProcaptchaAudioWidget;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_audioPlayer = require("./components/audioPlayer.cjs");
|
|
3
|
+
const require_procaptchaWidget = require("./components/procaptchaWidget.cjs");
|
|
4
|
+
const require_procaptchaAudio = require("./components/procaptchaAudio.cjs");
|
|
5
|
+
exports.loadProcaptchaAudio = require_procaptchaAudio.loadProcaptchaAudio;
|
|
6
|
+
exports.mountAudioPlayer = require_audioPlayer.mountAudioPlayer;
|
|
7
|
+
exports.mountProcaptchaAudio = require_procaptchaAudio.mountProcaptchaAudio;
|
|
8
|
+
exports.mountProcaptchaAudioWidget = require_procaptchaWidget.default;
|
|
@@ -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"}
|