mirror of
https://github.com/jambonz/jambonz-webapp.git
synced 2026-01-25 02:08:19 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf87e4fb80 | ||
|
|
b8140ba0d6 | ||
|
|
9fd847015e | ||
|
|
c237b7e7f2 |
@@ -318,7 +318,6 @@ export interface Application {
|
||||
app_json: null | string;
|
||||
call_hook: null | WebHook;
|
||||
account_sid: null | string;
|
||||
messaging_hook: null | WebHook;
|
||||
application_sid: string;
|
||||
call_status_hook: null | WebHook;
|
||||
speech_synthesis_voice: null | string;
|
||||
@@ -481,6 +480,7 @@ export interface Carrier {
|
||||
smpp_enquire_link_interval: number;
|
||||
register_status: CarrierRegisterStatus;
|
||||
dtmf_type: DtmfType;
|
||||
outbound_sip_proxy: string | null;
|
||||
}
|
||||
|
||||
export interface PredefinedCarrier extends Carrier {
|
||||
|
||||
@@ -77,11 +77,6 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
|
||||
const [tmpStatusWebhook, setTmpStatusWebhook] =
|
||||
useState<WebHook>(DEFAULT_WEBHOOK);
|
||||
const [initialStatusWebhook, setInitialStatusWebhook] = useState(false);
|
||||
const [messageWebhook, setMessageWebhook] =
|
||||
useState<WebHook>(DEFAULT_WEBHOOK);
|
||||
const [tmpMessageWebhook, setTmpMessageWebhook] =
|
||||
useState<WebHook>(DEFAULT_WEBHOOK);
|
||||
const [initialMessageWebhook, setInitialMessageWebhook] = useState(false);
|
||||
const [synthVendor, setSynthVendor] =
|
||||
useState<keyof SynthesisVendors>(VENDOR_GOOGLE);
|
||||
const [synthLang, setSynthLang] = useState(LANG_EN_US);
|
||||
@@ -150,16 +145,6 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
|
||||
initialCheck: initialStatusWebhook,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: "Messaging",
|
||||
prefix: "message_webhook",
|
||||
stateVal: messageWebhook,
|
||||
tmpStateVal: tmpMessageWebhook,
|
||||
stateSet: setMessageWebhook,
|
||||
tmpStateSet: setTmpMessageWebhook,
|
||||
initialCheck: initialMessageWebhook,
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
|
||||
useRedirect<Account>(
|
||||
@@ -202,7 +187,6 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
|
||||
app_json: applicationJson || null,
|
||||
call_hook: callWebhook || null,
|
||||
account_sid: accountSid || null,
|
||||
messaging_hook: messageWebhook || null,
|
||||
call_status_hook: statusWebhook || null,
|
||||
speech_synthesis_vendor: synthVendor || null,
|
||||
speech_synthesis_language: synthLang || null,
|
||||
@@ -471,24 +455,9 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
|
||||
else setInitialStatusWebhook(false);
|
||||
}
|
||||
|
||||
if (application.data.messaging_hook) {
|
||||
setMessageWebhook(application.data.messaging_hook);
|
||||
setTmpMessageWebhook(application.data.messaging_hook);
|
||||
|
||||
if (
|
||||
application.data.messaging_hook.username ||
|
||||
application.data.messaging_hook.password
|
||||
)
|
||||
setInitialMessageWebhook(true);
|
||||
else setInitialMessageWebhook(false);
|
||||
}
|
||||
|
||||
if (application.data.account_sid)
|
||||
setAccountSid(application.data.account_sid);
|
||||
|
||||
if (application.data.messaging_hook)
|
||||
setMessageWebhook(application.data.messaging_hook);
|
||||
|
||||
if (application.data.speech_synthesis_vendor)
|
||||
setSynthVendor(
|
||||
application.data.speech_synthesis_vendor as keyof SynthesisVendors,
|
||||
|
||||
@@ -31,6 +31,8 @@ import {
|
||||
VENDOR_SPEECHMATICS,
|
||||
VENDOR_PLAYHT,
|
||||
VENDOR_CARTESIA,
|
||||
VENDOR_VOXIST,
|
||||
VENDOR_RIMELABS,
|
||||
} from "src/vendor";
|
||||
import {
|
||||
LabelOptions,
|
||||
@@ -291,6 +293,12 @@ export const SpeechProviderSelection = ({
|
||||
updateTtsVoice(newLang!.voices[0].value);
|
||||
return;
|
||||
}
|
||||
if (synthVendor === VENDOR_RIMELABS) {
|
||||
const newLang = json.tts.find((lang) => lang.value === "eng");
|
||||
setSynthLang(newLang!.value);
|
||||
updateTtsVoice(newLang!.voices[0].value);
|
||||
return;
|
||||
}
|
||||
/** Google and AWS have different language lists */
|
||||
/** If the new language doesn't map then default to "en-US" */
|
||||
let newLang = json.tts.find((lang) => lang.value === synthLang);
|
||||
@@ -391,6 +399,7 @@ export const SpeechProviderSelection = ({
|
||||
options={ttsVendorOptions.filter(
|
||||
(vendor) =>
|
||||
vendor.value !== VENDOR_ASSEMBLYAI &&
|
||||
vendor.value !== VENDOR_VOXIST &&
|
||||
vendor.value !== VENDOR_SONIOX &&
|
||||
vendor.value !== VENDOR_SPEECHMATICS &&
|
||||
vendor.value !== VENDOR_CUSTOM &&
|
||||
|
||||
@@ -119,6 +119,9 @@ export const CarrierForm = ({
|
||||
const [diversion, setDiversion] = useState("");
|
||||
const [initialDiversion, setInitialDiversion] = useState(false);
|
||||
|
||||
const [initialSipProxy, setInitialSipProxy] = useState(false);
|
||||
const [outboundSipProxy, setOutboundSipProxy] = useState("");
|
||||
|
||||
const [smppSystemId, setSmppSystemId] = useState("");
|
||||
const [smppPass, setSmppPass] = useState("");
|
||||
const [smppInboundSystemId, setSmppInboundSystemId] = useState("");
|
||||
@@ -142,6 +145,44 @@ export const CarrierForm = ({
|
||||
const [smppInboundMessage, setSmppInboundMessage] = useState("");
|
||||
const [smppOutboundMessage, setSmppOutboundMessage] = useState("");
|
||||
|
||||
const validateOutboundSipGateway = (gateway: string): boolean => {
|
||||
/** validate outbound sip gateway that can be
|
||||
* ip address
|
||||
dns name
|
||||
sip(s):ip address
|
||||
sip(s):dns name
|
||||
full sip uri
|
||||
full sips uri
|
||||
*/
|
||||
// firstly checkig it's including sip or sips
|
||||
if (
|
||||
gateway.includes(":") &&
|
||||
!gateway.includes("sip:") &&
|
||||
!gateway.includes("sips:")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (gateway.includes("sip:") || gateway.includes("sips:")) {
|
||||
const sipGateway = gateway.trim().split(":");
|
||||
if (sipGateway.length === 2) {
|
||||
const sipGatewayType = getIpValidationType(sipGateway[1]);
|
||||
if (sipGatewayType === INVALID) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// check IP address or domain name
|
||||
else {
|
||||
const sipGatewayType = getIpValidationType(gateway);
|
||||
if (sipGatewayType === INVALID) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const setCarrierStates = (obj: Carrier) => {
|
||||
if (obj) {
|
||||
setIsActive(obj.is_active);
|
||||
@@ -207,6 +248,13 @@ export const CarrierForm = ({
|
||||
setInitialDiversion(false);
|
||||
}
|
||||
|
||||
if (obj.outbound_sip_proxy) {
|
||||
setOutboundSipProxy(obj.outbound_sip_proxy);
|
||||
setInitialSipProxy(true);
|
||||
} else {
|
||||
setInitialSipProxy(false);
|
||||
}
|
||||
|
||||
if (obj.smpp_system_id) {
|
||||
setSmppSystemId(obj.smpp_system_id);
|
||||
}
|
||||
@@ -508,6 +556,14 @@ export const CarrierForm = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
isNotBlank(outboundSipProxy) &&
|
||||
!validateOutboundSipGateway(outboundSipProxy)
|
||||
) {
|
||||
toastError("Please provide a valid SIP Proxy domain or IP address.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentServiceProvider) {
|
||||
const carrierPayload: Partial<Carrier> = {
|
||||
name: carrierName.trim(),
|
||||
@@ -531,6 +587,7 @@ export const CarrierForm = ({
|
||||
smpp_inbound_system_id: smppInboundSystemId.trim() || null,
|
||||
smpp_inbound_password: smppInboundPass.trim() || null,
|
||||
dtmf_type: dtmfType,
|
||||
outbound_sip_proxy: outboundSipProxy.trim().replaceAll(" ", "") || null,
|
||||
};
|
||||
|
||||
if (carrier && carrier.data) {
|
||||
@@ -971,6 +1028,33 @@ export const CarrierForm = ({
|
||||
/>
|
||||
</Checkzone>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<Checkzone
|
||||
hidden
|
||||
name="outbound_sip_proxy"
|
||||
label="Outbound SIP Proxy"
|
||||
initialCheck={initialSipProxy}
|
||||
handleChecked={(e) => {
|
||||
if (!e.target.checked) {
|
||||
setOutboundSipProxy("");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MS>
|
||||
Send all calls to this carrier through an outbound proxy
|
||||
</MS>
|
||||
<input
|
||||
id="outbound_sip_proxy"
|
||||
name="outbound_sip_proxy"
|
||||
type="text"
|
||||
value={outboundSipProxy}
|
||||
placeholder="Outbound Sip Proxy"
|
||||
onChange={(e) => {
|
||||
setOutboundSipProxy(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Checkzone>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label htmlFor="sip_gateways">
|
||||
SIP gateways<span>*</span>
|
||||
|
||||
@@ -50,6 +50,7 @@ import {
|
||||
VENDOR_VERBIO,
|
||||
VENDOR_SPEECHMATICS,
|
||||
VENDOR_CARTESIA,
|
||||
VENDOR_VOXIST,
|
||||
} from "src/vendor";
|
||||
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
||||
import {
|
||||
@@ -461,6 +462,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
|
||||
vendor === VENDOR_WELLSAID ||
|
||||
vendor === VENDOR_DEEPGRAM ||
|
||||
vendor === VENDOR_ASSEMBLYAI ||
|
||||
vendor === VENDOR_VOXIST ||
|
||||
vendor === VENDOR_SONIOX ||
|
||||
vendor === VENDOR_SPEECHMATICS ||
|
||||
vendor === VENDOR_ELEVENLABS ||
|
||||
@@ -881,6 +883,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
|
||||
{vendor && (
|
||||
<fieldset>
|
||||
{vendor !== VENDOR_ASSEMBLYAI &&
|
||||
vendor !== VENDOR_VOXIST &&
|
||||
vendor !== VENDOR_COBALT &&
|
||||
vendor !== VENDOR_SONIOX &&
|
||||
vendor !== VENDOR_SPEECHMATICS &&
|
||||
@@ -1512,6 +1515,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
|
||||
|
||||
{(vendor === VENDOR_WELLSAID ||
|
||||
vendor === VENDOR_ASSEMBLYAI ||
|
||||
vendor === VENDOR_VOXIST ||
|
||||
vendor == VENDOR_ELEVENLABS ||
|
||||
vendor === VENDOR_WHISPER ||
|
||||
vendor === VENDOR_PLAYHT ||
|
||||
|
||||
5
src/vendor/index.tsx
vendored
5
src/vendor/index.tsx
vendored
@@ -20,6 +20,7 @@ export const VENDOR_CUSTOM = "custom";
|
||||
export const VENDOR_COBALT = "cobalt";
|
||||
export const VENDOR_ELEVENLABS = "elevenlabs";
|
||||
export const VENDOR_ASSEMBLYAI = "assemblyai";
|
||||
export const VENDOR_VOXIST = "voxist";
|
||||
export const VENDOR_WHISPER = "whisper";
|
||||
export const VENDOR_PLAYHT = "playht";
|
||||
export const VENDOR_RIMELABS = "rimelabs";
|
||||
@@ -83,6 +84,10 @@ export const vendors: VendorOptions[] = [
|
||||
name: "AssemblyAI",
|
||||
value: VENDOR_ASSEMBLYAI,
|
||||
},
|
||||
{
|
||||
name: "Voxist",
|
||||
value: VENDOR_VOXIST,
|
||||
},
|
||||
{
|
||||
name: "Whisper",
|
||||
value: VENDOR_WHISPER,
|
||||
|
||||
2
src/vendor/types.ts
vendored
2
src/vendor/types.ts
vendored
@@ -13,6 +13,7 @@ export type Vendor =
|
||||
| "Custom"
|
||||
| "ElevenLabs"
|
||||
| "assemblyai"
|
||||
| "voxist"
|
||||
| "whisper"
|
||||
| "playht"
|
||||
| "rimelabs"
|
||||
@@ -109,6 +110,7 @@ export interface SynthesisVendors {
|
||||
deepgram: VoiceLanguage[];
|
||||
playht: VoiceLanguage[];
|
||||
cartesia: VoiceLanguage[];
|
||||
rimelabs: VoiceLanguage[];
|
||||
}
|
||||
|
||||
export interface MSRawSpeech {
|
||||
|
||||
Reference in New Issue
Block a user