import React, { useState } from "react"; import { Show, SimpleShowLayout, BooleanField, TextField, ShowProps, EditButton, TopToolbar, useTranslate, useRefresh, } from "react-admin"; import { TextField as MuiTextField, Button, Card, Grid, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Typography, Box, CircularProgress, } from "@material-ui/core"; import { SixDigitInput } from "../../DigitInput"; import { sanitizeE164Number, isValidE164Number, } from "../../../lib/phone-numbers"; const Sidebar = ({ record }: any) => { const [phoneNumber, setPhoneNumber] = useState(""); const [errorNumber, setErrorNumber] = useState(false); const handlePhoneNumberChange = (event: any) => { setPhoneNumber(event.target.value); }; const [message, setMessage] = useState(""); const handleMessageChange = (event: any) => { setMessage(event.target.value); }; const sendMessage = async (phoneNumber: string, message: string) => { await fetch(`/api/v1/signal/bots/${record.token}/send`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ phoneNumber, message }), }); }; const resetSession = async (phoneNumber: string) => { await fetch(`/api/v1/signal/bots/${record.token}/resetSession`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ phoneNumber }), }); }; const handleBlurNumber = () => { setErrorNumber(!isValidE164Number(sanitizeE164Number(phoneNumber))); }; const handleSend = () => { const sanitized = sanitizeE164Number(phoneNumber); if (isValidE164Number(sanitized)) { setErrorNumber(false); sendMessage(sanitized, message); } else setErrorNumber(false); }; const handleResetSession = () => { const sanitized = sanitizeE164Number(phoneNumber); if (isValidE164Number(sanitized)) { setErrorNumber(false); resetSession(sanitized); } else setErrorNumber(false); }; return ( Send message ); }; const MODE = { SMS: "SMS", VOICE: "VOICE", }; const handleRequestCode = async ({ verifyMode, id, onSuccess, onFailure, captchaCode = undefined, }: any) => { if (verifyMode === MODE.SMS) console.log("REQUESTING sms"); else if (verifyMode === MODE.VOICE) console.log("REQUESTING voice"); let response: Response; let url = `/api/v1/signal/bots/${id}/requestCode?mode=${verifyMode.toLowerCase()}`; if (captchaCode) { url += `&captcha=${captchaCode}`; } try { response = await fetch(url, { method: "GET", headers: { "Content-Type": "application/json", }, }); if (response && response.ok) { onSuccess(); } else { onFailure(response.status || 400); } } catch (error: any) { console.error("Failed to request verification code:", error); } }; const VerificationCodeRequest = ({ verifyMode, data, onSuccess, onFailure, }: any) => { React.useEffect(() => { (async () => { await handleRequestCode({ verifyMode, id: data.id, onSuccess, onFailure, }); })(); }, []); return ( <> Requesting code for {data.phoneNumber} ); }; const VerificationCaptcha = ({ verifyMode, data, onSuccess, onFailure, handleClose, }: any) => { const [code, setCode] = React.useState(undefined); const [isSubmitting, setSubmitting] = React.useState(false); const handleSubmitVerification = async () => { setSubmitting(true); await handleRequestCode({ verifyMode, id: data.id, onSuccess, onFailure, captchaCode: code, }); setSubmitting(false); }; const handleCaptchaChange = (value: any) => { if (value) setCode( value .replace(/signalcaptcha:\/\//, "") .replace("“", "") .replace("”", "") .trim() ); else setCode(value); }; return ( <> Captcha for {data.phoneNumber} handleCaptchaChange(ev.target.value)} /> {isSubmitting && } {!isSubmitting && ( )} {!isSubmitting && ( )} ); }; const VerificationCodeInput = ({ data, verifyMode, handleClose, handleRestartVerification, confirmVerification, }: any) => { const [code, setValue] = React.useState(""); const [isSubmitting, setSubmitting] = React.useState(false); const [isValid, setValid] = React.useState(false); const [submissionError, setSubmissionError] = React.useState(undefined); const translate = useTranslate(); const validator = (v: any) => v.trim().length === 6; const handleValueChange = (newValue: any) => { setValue(newValue); setValid(validator(newValue)); }; const handleSubmitVerification = async () => { setSubmitting(true); // await sleep(2000) const response = await fetch( `/api/v1/signal/bots/${data.id}/register?code=${code}`, { method: "GET", headers: { "Content-Type": "application/json", }, } ); setSubmitting(false); const responseBody = await response.json(); console.log(responseBody); if (response.status === 200) { confirmVerification(); } else if (responseBody.message) // @ts-expect-error setSubmissionError(`Error: ${responseBody.message}`); else { setSubmissionError( // @ts-expect-error "There was an error, sorry about that. Please try again later or contact support." ); } }; const title = verifyMode === MODE.SMS ? translate("resources.signalBots.verifyDialog.sms", { phoneNumber: data.phoneNumber, }) : translate("resources.signalBots.verifyDialog.voice", { phoneNumber: data.phoneNumber, }); return ( <> Verify {data.phoneNumber} {title} {submissionError && ( {submissionError} )} {isSubmitting && } {!isSubmitting && ( )} {!isSubmitting && ( )} {!isSubmitting && ( )} ); }; const VerificationCodeDialog = (props: any) => { const [stage, setStage] = React.useState("request"); const onRequestSuccess = () => setStage("verify"); const onRestartVerification = () => setStage("request"); const handleClose = () => { setStage("request"); props.handleClose(); }; const onFailure = (code: number) => { if (code === 402 || code === 500) { setStage("captcha"); } else { setStage("request"); } }; return ( {props.open && stage === "request" && ( )} {props.open && stage === "verify" && ( )} {props.open && stage === "captcha" && ( )} ); }; const SignalBotShowActions = ({ basePath, data }: any) => { const [open, setOpen] = React.useState(false); const [verifyMode, setVerifyMode] = React.useState(""); const refresh = useRefresh(); const handleOpenSMS = () => { setVerifyMode(MODE.SMS); setOpen(true); }; const handleOpenVoice = () => { setVerifyMode(MODE.VOICE); setOpen(true); }; const handleClose = () => setOpen(false); const confirmVerification = () => { setOpen(false); refresh(); }; return ( {data && !data.isVerified && ( )} {data && !data.isVerified && ( )} {data && !data.isVerified && ( )} ); }; const SignalBotShow = (props: ShowProps) => ( } {...props} title="Signal Bot" aside={} > ); export default SignalBotShow;