@fonoster/apiserver 0.6.6 → 0.7.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.
- package/dist/applications/createGetFnUtil.d.ts +1 -1
- package/dist/applications/getApplication.js +1 -3
- package/dist/applications/types.d.ts +1 -1
- package/dist/applications/utils/applicationWithEncodedStruct.js +20 -1
- package/dist/applications/utils/convertToApplicationData.js +1 -1
- package/dist/applications/utils/getApplicationValidationSchema.d.ts +3 -3
- package/dist/applications/utils/getApplicationValidationSchema.js +12 -5
- package/dist/applications/utils/prepareForValidation.js +1 -1
- package/dist/calls/ListCallsRequestSchema.d.ts +1 -4
- package/dist/calls/ListCallsRequestSchema.js +0 -4
- package/dist/calls/buildService.d.ts +2 -2
- package/dist/calls/buildService.js +6 -5
- package/dist/calls/createCall.d.ts +6 -4
- package/dist/calls/createCall.js +18 -8
- package/dist/calls/createFetchCalls.js +3 -7
- package/dist/calls/createFetchSingleCall.js +9 -2
- package/dist/calls/{trackCall.d.ts → makeTrackCall.d.ts} +3 -3
- package/dist/calls/makeTrackCall.js +67 -0
- package/dist/calls/runCallManager.js +12 -13
- package/dist/calls/types.d.ts +8 -42
- package/dist/calls/types.js +5 -38
- package/dist/core/seed.js +20 -0
- package/dist/core/services.d.ts +2 -2
- package/dist/envs.d.ts +0 -2
- package/dist/envs.js +1 -3
- package/dist/events/createInfluxDbPub.js +2 -1
- package/dist/events/mapCallDirectionToEnum.d.ts +3 -0
- package/dist/events/mapCallDirectionToEnum.js +37 -0
- package/dist/events/nats.js +5 -6
- package/dist/events/transformEvent.d.ts +2 -0
- package/dist/events/transformEvent.js +72 -0
- package/dist/index.js +4 -5
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/makeHandleDialEventsWithNats.d.ts +5 -0
- package/dist/{voice/handlers/StasisEnd.js → utils/makeHandleDialEventsWithNats.js} +10 -15
- package/dist/utils/makeHandleDialEventsWithVoiceClient.d.ts +5 -0
- package/dist/{voice/handlers/dial/handleDialEvents.js → utils/makeHandleDialEventsWithVoiceClient.js} +6 -17
- package/dist/utils/mapDialStatus.d.ts +3 -0
- package/dist/utils/mapDialStatus.js +38 -0
- package/dist/voice/VoiceClientImpl.d.ts +10 -1
- package/dist/voice/VoiceClientImpl.js +47 -7
- package/dist/voice/VoiceDispatcher.d.ts +6 -2
- package/dist/voice/VoiceDispatcher.js +50 -37
- package/dist/voice/connectToAri.js +3 -1
- package/dist/voice/createExternalMediaConfig.d.ts +3 -0
- package/dist/voice/createExternalMediaConfig.js +4 -1
- package/dist/voice/handlers/Answer.js +1 -1
- package/dist/voice/handlers/Hangup.js +1 -1
- package/dist/voice/handlers/Mute.js +1 -1
- package/dist/voice/handlers/Play.js +2 -2
- package/dist/voice/handlers/PlayDtmf.js +1 -1
- package/dist/voice/handlers/PlaybackControl.js +1 -1
- package/dist/voice/handlers/Record.js +2 -2
- package/dist/voice/handlers/Say.js +2 -2
- package/dist/voice/handlers/StreamGather.d.ts +3 -0
- package/dist/voice/handlers/StreamGather.js +66 -0
- package/dist/voice/handlers/Unmute.js +1 -1
- package/dist/voice/handlers/dial/Dial.js +10 -6
- package/dist/voice/handlers/gather/Gather.js +5 -4
- package/dist/voice/handlers/index.d.ts +12 -0
- package/dist/voice/handlers/index.js +46 -0
- package/dist/voice/handlers/{awaitForPlaybackFinished.js → utils/awaitForPlaybackFinished.js} +1 -1
- package/dist/voice/handlers/{awaitForRecordingFinished.js → utils/awaitForRecordingFinished.js} +1 -1
- package/dist/voice/handlers/utils/index.d.ts +3 -0
- package/dist/voice/handlers/utils/index.js +37 -0
- package/dist/voice/handlers/utils/isDtmf.d.ts +2 -0
- package/dist/voice/handlers/utils/isDtmf.js +24 -0
- package/dist/voice/integrations/findIntegrationsCredentials.d.ts +1 -1
- package/dist/voice/integrations/findIntegrationsCredentials.js +2 -1
- package/dist/voice/integrations/getSttConfig.d.ts +4 -2
- package/dist/voice/integrations/getSttConfig.js +4 -1
- package/dist/voice/integrations/getTtsConfig.d.ts +2 -1
- package/dist/voice/integrations/getTtsConfig.js +5 -1
- package/dist/voice/integrations/makeCreateContainer.js +1 -1
- package/dist/voice/integrations/types.d.ts +1 -1
- package/dist/voice/makeCreateVoiceClient.js +4 -10
- package/dist/voice/makeGetChannelVar.d.ts +2 -1
- package/dist/voice/makeGetChannelVar.js +13 -0
- package/dist/voice/stt/AbstractSpeechToText.d.ts +4 -3
- package/dist/voice/stt/Deepgram.d.ts +18 -0
- package/dist/voice/stt/Deepgram.js +156 -0
- package/dist/voice/stt/Google.d.ts +5 -6
- package/dist/voice/stt/Google.js +13 -13
- package/dist/voice/stt/SpeechToTextFactory.js +2 -0
- package/dist/voice/stt/types.d.ts +22 -10
- package/dist/voice/stt/types.js +7 -0
- package/dist/voice/tts/Deepgram.d.ts +25 -0
- package/dist/voice/tts/Deepgram.js +122 -0
- package/dist/voice/tts/Google.d.ts +2 -1
- package/dist/voice/tts/Google.js +7 -8
- package/dist/voice/tts/TextToSpeechFactory.js +2 -0
- package/dist/voice/types/ari.d.ts +2 -1
- package/dist/voice/types/ari.js +1 -0
- package/dist/voice/types/voice.d.ts +9 -1
- package/package.json +9 -8
- package/dist/calls/createTrackCallSubscriber.d.ts +0 -5
- package/dist/calls/createTrackCallSubscriber.js +0 -52
- package/dist/calls/trackCall.js +0 -63
- package/dist/voice/handlers/StasisEnd.d.ts +0 -4
- package/dist/voice/handlers/dial/handleDialEvents.d.ts +0 -5
- /package/dist/voice/handlers/{awaitForPlaybackFinished.d.ts → utils/awaitForPlaybackFinished.d.ts} +0 -0
- /package/dist/voice/handlers/{awaitForRecordingFinished.d.ts → utils/awaitForRecordingFinished.d.ts} +0 -0
- /package/dist/voice/handlers/{withErrorHandling.d.ts → utils/withErrorHandling.d.ts} +0 -0
- /package/dist/voice/handlers/{withErrorHandling.js → utils/withErrorHandling.js} +0 -0
|
@@ -28,7 +28,6 @@ exports.getApplication = getApplication;
|
|
|
28
28
|
* See the License for the specific language governing permissions and
|
|
29
29
|
* limitations under the License.
|
|
30
30
|
*/
|
|
31
|
-
const common_1 = require("@fonoster/common");
|
|
32
31
|
const identity_1 = require("@fonoster/identity");
|
|
33
32
|
const logger_1 = require("@fonoster/logger");
|
|
34
33
|
const createGetFnUtil_1 = require("./createGetFnUtil");
|
|
@@ -40,7 +39,6 @@ function getApplication(prisma) {
|
|
|
40
39
|
const { ref } = call.request;
|
|
41
40
|
logger.verbose("call to getApplication", { ref });
|
|
42
41
|
const result = yield getFn(ref);
|
|
43
|
-
|
|
44
|
-
return result ? (0, applicationWithEncodedStruct_1.applicationWithEncodedStruct)(resultWithParsedDate) : null;
|
|
42
|
+
return result ? (0, applicationWithEncodedStruct_1.applicationWithEncodedStruct)(result) : null;
|
|
45
43
|
}), (ref) => getFn(ref));
|
|
46
44
|
}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.applicationWithEncodedStruct = applicationWithEncodedStruct;
|
|
4
|
+
/*
|
|
5
|
+
* Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
|
|
6
|
+
* http://github.com/fonoster/fonoster
|
|
7
|
+
*
|
|
8
|
+
* This file is part of Fonoster
|
|
9
|
+
*
|
|
10
|
+
* Licensed under the MIT License (the "License");
|
|
11
|
+
* you may not use this file except in compliance with
|
|
12
|
+
* the License. You may obtain a copy of the License at
|
|
13
|
+
*
|
|
14
|
+
* https://opensource.org/licenses/MIT
|
|
15
|
+
*
|
|
16
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
18
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
19
|
+
* See the License for the specific language governing permissions and
|
|
20
|
+
* limitations under the License.
|
|
21
|
+
*/
|
|
22
|
+
const common_1 = require("@fonoster/common");
|
|
4
23
|
const pb_util_1 = require("pb-util");
|
|
5
24
|
function applicationWithEncodedStruct(application) {
|
|
6
25
|
const encodeConfig = (property) => {
|
|
@@ -18,5 +37,5 @@ function applicationWithEncodedStruct(application) {
|
|
|
18
37
|
delete intelligenceCopy.credentials;
|
|
19
38
|
result.intelligence = Object.assign(Object.assign({}, intelligenceCopy), { config: encodeConfig(intelligenceCopy) });
|
|
20
39
|
}
|
|
21
|
-
return result;
|
|
40
|
+
return (0, common_1.datesMapper)(result);
|
|
22
41
|
}
|
|
@@ -9,7 +9,7 @@ function convertToApplicationData(request) {
|
|
|
9
9
|
ref: request.ref, // Only for UpdateApplicationRequest
|
|
10
10
|
name: request.name,
|
|
11
11
|
type,
|
|
12
|
-
|
|
12
|
+
endpoint: request.endpoint
|
|
13
13
|
};
|
|
14
14
|
const createProperty = (property) => {
|
|
15
15
|
return property
|
|
@@ -7,7 +7,7 @@ declare function getApplicationValidationSchema(request: {
|
|
|
7
7
|
type: z.ZodNativeEnum<{
|
|
8
8
|
PROGRAMMABLE_VOICE: "PROGRAMMABLE_VOICE";
|
|
9
9
|
}>;
|
|
10
|
-
|
|
10
|
+
endpoint: z.ZodEffects<z.ZodNullable<z.ZodOptional<z.ZodString>>, string, string>;
|
|
11
11
|
textToSpeech: z.ZodUndefined | z.ZodObject<{
|
|
12
12
|
productRef: z.ZodString;
|
|
13
13
|
config: any;
|
|
@@ -35,7 +35,7 @@ declare function getApplicationValidationSchema(request: {
|
|
|
35
35
|
}, "strip", z.ZodTypeAny, {
|
|
36
36
|
name?: string;
|
|
37
37
|
type?: "PROGRAMMABLE_VOICE";
|
|
38
|
-
|
|
38
|
+
endpoint?: string;
|
|
39
39
|
textToSpeech?: {
|
|
40
40
|
[x: string]: any;
|
|
41
41
|
productRef?: unknown;
|
|
@@ -49,7 +49,7 @@ declare function getApplicationValidationSchema(request: {
|
|
|
49
49
|
}, {
|
|
50
50
|
name?: string;
|
|
51
51
|
type?: "PROGRAMMABLE_VOICE";
|
|
52
|
-
|
|
52
|
+
endpoint?: string;
|
|
53
53
|
textToSpeech?: {
|
|
54
54
|
[x: string]: any;
|
|
55
55
|
productRef?: unknown;
|
|
@@ -21,24 +21,31 @@ exports.getApplicationValidationSchema = getApplicationValidationSchema;
|
|
|
21
21
|
*/
|
|
22
22
|
const client_1 = require("@prisma/client");
|
|
23
23
|
const zod_1 = require("zod");
|
|
24
|
+
const Deepgram_1 = require("../../voice/stt/Deepgram");
|
|
24
25
|
const Google_1 = require("../../voice/stt/Google");
|
|
25
26
|
const Azure_1 = require("../../voice/tts/Azure");
|
|
27
|
+
const Deepgram_2 = require("../../voice/tts/Deepgram");
|
|
26
28
|
const Google_2 = require("../../voice/tts/Google");
|
|
27
29
|
const hostOrHostPortSchema_1 = require("../hostOrHostPortSchema");
|
|
30
|
+
// TODO: We need a way to add this values dynamically
|
|
28
31
|
const validators = {
|
|
29
32
|
ttsConfigValidators: {
|
|
30
33
|
"tts.google": Google_2.Google.getConfigValidationSchema,
|
|
31
|
-
"tts.azure": Azure_1.Azure.getConfigValidationSchema
|
|
34
|
+
"tts.azure": Azure_1.Azure.getConfigValidationSchema,
|
|
35
|
+
"tts.deepgram": Deepgram_2.Deepgram.getConfigValidationSchema
|
|
32
36
|
},
|
|
33
37
|
ttsCredentialsValidators: {
|
|
34
38
|
"tts.google": Google_2.Google.getCredentialsValidationSchema,
|
|
35
|
-
"tts.azure": Azure_1.Azure.getCredentialsValidationSchema
|
|
39
|
+
"tts.azure": Azure_1.Azure.getCredentialsValidationSchema,
|
|
40
|
+
"tts.deepgram": Deepgram_2.Deepgram.getCredentialsValidationSchema
|
|
36
41
|
},
|
|
37
42
|
sttConfigValidators: {
|
|
38
|
-
"stt.google": Google_1.Google.getConfigValidationSchema
|
|
43
|
+
"stt.google": Google_1.Google.getConfigValidationSchema,
|
|
44
|
+
"stt.deepgram": Deepgram_1.Deepgram.getConfigValidationSchema
|
|
39
45
|
},
|
|
40
46
|
sttCredentialsValidators: {
|
|
41
|
-
"stt.google": Google_1.Google.getCredentialsValidationSchema
|
|
47
|
+
"stt.google": Google_1.Google.getCredentialsValidationSchema,
|
|
48
|
+
"stt.deepgram": Deepgram_1.Deepgram.getCredentialsValidationSchema
|
|
42
49
|
}
|
|
43
50
|
};
|
|
44
51
|
function getApplicationValidationSchema(request) {
|
|
@@ -46,7 +53,7 @@ function getApplicationValidationSchema(request) {
|
|
|
46
53
|
return zod_1.z.object({
|
|
47
54
|
name: zod_1.z.string(),
|
|
48
55
|
type: zod_1.z.nativeEnum(client_1.ApplicationType),
|
|
49
|
-
|
|
56
|
+
endpoint: hostOrHostPortSchema_1.hostOrHostPortSchema,
|
|
50
57
|
textToSpeech: ttsEngineName
|
|
51
58
|
? zod_1.z.object({
|
|
52
59
|
productRef: zod_1.z.string(),
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { CallStatus, CallType
|
|
2
|
+
import { CallStatus, CallType } from "./types";
|
|
3
3
|
declare const ListCallsRequestSchema: z.ZodObject<{
|
|
4
4
|
after: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
5
5
|
before: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
6
6
|
pageSize: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
|
|
7
7
|
type: z.ZodNullable<z.ZodOptional<z.ZodNativeEnum<typeof CallType>>>;
|
|
8
|
-
hangupCause: z.ZodNullable<z.ZodOptional<z.ZodNativeEnum<typeof HangupCause>>>;
|
|
9
8
|
status: z.ZodNullable<z.ZodOptional<z.ZodNativeEnum<typeof CallStatus>>>;
|
|
10
9
|
pageToken: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
11
10
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -15,7 +14,6 @@ declare const ListCallsRequestSchema: z.ZodObject<{
|
|
|
15
14
|
pageToken?: string;
|
|
16
15
|
after?: string;
|
|
17
16
|
before?: string;
|
|
18
|
-
hangupCause?: HangupCause;
|
|
19
17
|
}, {
|
|
20
18
|
type?: CallType;
|
|
21
19
|
status?: CallStatus;
|
|
@@ -23,6 +21,5 @@ declare const ListCallsRequestSchema: z.ZodObject<{
|
|
|
23
21
|
pageToken?: string;
|
|
24
22
|
after?: string;
|
|
25
23
|
before?: string;
|
|
26
|
-
hangupCause?: HangupCause;
|
|
27
24
|
}>;
|
|
28
25
|
export { ListCallsRequestSchema };
|
|
@@ -42,10 +42,6 @@ const ListCallsRequestSchema = zod_1.z.object({
|
|
|
42
42
|
})
|
|
43
43
|
.optional()
|
|
44
44
|
.nullable(),
|
|
45
|
-
hangupCause: zod_1.z
|
|
46
|
-
.nativeEnum(types_1.HangupCause, { message: "Invalid hangup cause" })
|
|
47
|
-
.optional()
|
|
48
|
-
.nullable(),
|
|
49
45
|
status: zod_1.z
|
|
50
46
|
.nativeEnum(types_1.CallStatus, { message: "Invalid call status" })
|
|
51
47
|
.optional()
|
|
@@ -8,8 +8,8 @@ declare function buildService(influxdb: InfluxDBClient): Promise<{
|
|
|
8
8
|
};
|
|
9
9
|
handlers: {
|
|
10
10
|
createCall: (call: {
|
|
11
|
-
request: import("
|
|
12
|
-
}, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: import("
|
|
11
|
+
request: import("@fonoster/types").CreateCallRequest;
|
|
12
|
+
}, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: import("@fonoster/common").BaseApiObject) => void) => Promise<void>;
|
|
13
13
|
listCalls: (call: {
|
|
14
14
|
request: import("./types").ListCallsRequest;
|
|
15
15
|
}, callback: (error: import("@fonoster/common").GrpcErrorMessage, response?: import("./types").ListCallsResponse) => void) => Promise<void>;
|
|
@@ -28,17 +28,18 @@ exports.buildService = buildService;
|
|
|
28
28
|
* See the License for the specific language governing permissions and
|
|
29
29
|
* limitations under the License.
|
|
30
30
|
*/
|
|
31
|
+
const nats_1 = require("nats");
|
|
31
32
|
const createCall_1 = require("./createCall");
|
|
32
33
|
const createCallPublisher_1 = require("./createCallPublisher");
|
|
33
|
-
const createTrackCallSubscriber_1 = require("./createTrackCallSubscriber");
|
|
34
34
|
const getCall_1 = require("./getCall");
|
|
35
35
|
const listCalls_1 = require("./listCalls");
|
|
36
|
-
const
|
|
36
|
+
const makeTrackCall_1 = require("./makeTrackCall");
|
|
37
|
+
const db_1 = require("../core/db");
|
|
37
38
|
const envs_1 = require("../envs");
|
|
38
39
|
function buildService(influxdb) {
|
|
39
40
|
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
-
const trackCallSubscriber = yield (0, createTrackCallSubscriber_1.createTrackCallSubscriber)(envs_1.NATS_URL);
|
|
41
41
|
const callPublisher = yield (0, createCallPublisher_1.createCallPublisher)(envs_1.NATS_URL);
|
|
42
|
+
const nc = yield (0, nats_1.connect)({ servers: envs_1.NATS_URL });
|
|
42
43
|
return {
|
|
43
44
|
definition: {
|
|
44
45
|
serviceName: "Calls",
|
|
@@ -47,10 +48,10 @@ function buildService(influxdb) {
|
|
|
47
48
|
proto: "calls.proto"
|
|
48
49
|
},
|
|
49
50
|
handlers: {
|
|
50
|
-
createCall: (0, createCall_1.createCall)(callPublisher),
|
|
51
|
+
createCall: (0, createCall_1.createCall)(db_1.prisma, callPublisher),
|
|
51
52
|
listCalls: (0, listCalls_1.listCalls)(influxdb),
|
|
52
53
|
getCall: (0, getCall_1.getCall)(influxdb),
|
|
53
|
-
trackCall: (0,
|
|
54
|
+
trackCall: (0, makeTrackCall_1.makeTrackCall)(nc)
|
|
54
55
|
}
|
|
55
56
|
};
|
|
56
57
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { GrpcErrorMessage } from "@fonoster/common";
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { BaseApiObject, GrpcErrorMessage } from "@fonoster/common";
|
|
2
|
+
import { CreateCallRequest } from "@fonoster/types";
|
|
3
|
+
import { CallPublisher } from "./types";
|
|
4
|
+
import { Prisma } from "../core/db";
|
|
5
|
+
declare function createCall(prisma: Prisma, publisher: CallPublisher): (call: {
|
|
4
6
|
request: CreateCallRequest;
|
|
5
|
-
}, callback: (error?: GrpcErrorMessage, response?:
|
|
7
|
+
}, callback: (error?: GrpcErrorMessage, response?: BaseApiObject) => void) => Promise<void>;
|
|
6
8
|
export { createCall };
|
package/dist/calls/createCall.js
CHANGED
|
@@ -33,27 +33,37 @@ const identity_1 = require("@fonoster/identity");
|
|
|
33
33
|
const logger_1 = require("@fonoster/logger");
|
|
34
34
|
const uuid_1 = require("uuid");
|
|
35
35
|
const zod_1 = require("zod");
|
|
36
|
+
const notFoundError_1 = require("../core/notFoundError");
|
|
36
37
|
const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
|
|
37
38
|
const CreateCallRequestSchema = zod_1.z.object({
|
|
38
39
|
from: zod_1.z.string(),
|
|
39
40
|
to: zod_1.z.string(),
|
|
40
|
-
appRef: zod_1.z.string()
|
|
41
|
+
appRef: zod_1.z.string(),
|
|
42
|
+
timeout: zod_1.z.number().optional()
|
|
41
43
|
});
|
|
42
|
-
function createCall(publisher) {
|
|
44
|
+
function createCall(prisma, publisher) {
|
|
43
45
|
return (call, callback) => __awaiter(this, void 0, void 0, function* () {
|
|
44
46
|
try {
|
|
45
|
-
const { from, to, appRef } = call.request;
|
|
46
|
-
CreateCallRequestSchema.parse(call.request);
|
|
47
|
+
const { from, to, appRef, timeout } = call.request;
|
|
47
48
|
const ref = (0, uuid_1.v4)();
|
|
49
|
+
logger.verbose("call to createCall", Object.assign(Object.assign({}, call.request), { ref }));
|
|
50
|
+
CreateCallRequestSchema.parse(call.request);
|
|
48
51
|
const accessKeyId = (0, identity_1.getAccessKeyIdFromCall)(call);
|
|
49
|
-
|
|
50
|
-
accessKeyId
|
|
52
|
+
const app = yield prisma.application.findUnique({
|
|
53
|
+
where: { ref: appRef, accessKeyId }
|
|
54
|
+
});
|
|
55
|
+
if (!app) {
|
|
56
|
+
throw (0, notFoundError_1.notFoundError)(`Application with ref ${appRef} not found`);
|
|
57
|
+
}
|
|
58
|
+
// TODO: Must validate that the from number exists and is owned by the user
|
|
59
|
+
publisher.publishCall({
|
|
51
60
|
ref,
|
|
52
61
|
from,
|
|
53
62
|
to,
|
|
54
|
-
appRef
|
|
63
|
+
appRef,
|
|
64
|
+
accessKeyId,
|
|
65
|
+
timeout: timeout || 60
|
|
55
66
|
});
|
|
56
|
-
publisher.publishCall({ ref, from, to, appRef });
|
|
57
67
|
callback(null, { ref });
|
|
58
68
|
}
|
|
59
69
|
catch (error) {
|
|
@@ -35,7 +35,7 @@ const envs_1 = require("../envs");
|
|
|
35
35
|
const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
|
|
36
36
|
function createFetchCalls(influxdb) {
|
|
37
37
|
return (accessKeyId, request) => __awaiter(this, void 0, void 0, function* () {
|
|
38
|
-
const { after, before, type, from, to, status,
|
|
38
|
+
const { after, before, type, from, to, status, pageSize, pageToken } = request;
|
|
39
39
|
const accessKeyIdFilter = accessKeyId
|
|
40
40
|
? (0, influxdb_client_1.flux) `and r.accessKeyId == "${accessKeyId}"`
|
|
41
41
|
: (0, influxdb_client_1.flux) ``;
|
|
@@ -43,9 +43,6 @@ function createFetchCalls(influxdb) {
|
|
|
43
43
|
const fromFilter = from ? (0, influxdb_client_1.flux) `and r.from == "${from}"` : (0, influxdb_client_1.flux) ``;
|
|
44
44
|
const toFilter = to ? (0, influxdb_client_1.flux) `and r.to == "${to}"` : (0, influxdb_client_1.flux) ``;
|
|
45
45
|
const statusFilter = status ? (0, influxdb_client_1.flux) `and r.status == "${status}"` : (0, influxdb_client_1.flux) ``;
|
|
46
|
-
const hangupCauseFilter = hangupCause
|
|
47
|
-
? (0, influxdb_client_1.flux) `and r.hangupCause == "${hangupCause}"`
|
|
48
|
-
: (0, influxdb_client_1.flux) ``;
|
|
49
46
|
const pageTokenFilter = pageToken
|
|
50
47
|
? (0, influxdb_client_1.flux) `|> filter(fn: (r) => r.startedAtParsed < int(v: ${pageToken}))`
|
|
51
48
|
: (0, influxdb_client_1.flux) ``;
|
|
@@ -56,7 +53,7 @@ function createFetchCalls(influxdb) {
|
|
|
56
53
|
: new Date().getTime() / 1000;
|
|
57
54
|
const query = (0, influxdb_client_1.flux) `from(bucket: "${envs_1.INFLUXDB_BUCKET}")
|
|
58
55
|
|> range(start: ${parsedAfter})
|
|
59
|
-
|> pivot(rowKey: ["
|
|
56
|
+
|> pivot(rowKey: ["callId"], columnKey: ["_field"], valueColumn: "_value")
|
|
60
57
|
|> map(fn: (r) => ({
|
|
61
58
|
r with
|
|
62
59
|
duration: (int(v: r.endedAt) - int(v: r.startedAt)) / 1000,
|
|
@@ -69,8 +66,7 @@ function createFetchCalls(influxdb) {
|
|
|
69
66
|
${typeFilter}
|
|
70
67
|
${fromFilter}
|
|
71
68
|
${toFilter}
|
|
72
|
-
${statusFilter}
|
|
73
|
-
${hangupCauseFilter})
|
|
69
|
+
${statusFilter})
|
|
74
70
|
|> group()
|
|
75
71
|
|> sort(columns: ["startedAtParsed"], desc: true)
|
|
76
72
|
${pageTokenFilter}
|
|
@@ -28,19 +28,26 @@ exports.createFetchSingleCall = createFetchSingleCall;
|
|
|
28
28
|
* See the License for the specific language governing permissions and
|
|
29
29
|
* limitations under the License.
|
|
30
30
|
*/
|
|
31
|
+
const logger_1 = require("@fonoster/logger");
|
|
31
32
|
const influxdb_client_1 = require("@influxdata/influxdb-client");
|
|
32
33
|
const types_1 = require("./types");
|
|
33
34
|
const envs_1 = require("../envs");
|
|
35
|
+
const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
|
|
34
36
|
function createFetchSingleCall(influxdb) {
|
|
35
37
|
return (accessKeyId, ref) => __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
// TODO: Look into best practices for range and limit
|
|
37
38
|
const query = (0, influxdb_client_1.flux) `from(bucket: "${envs_1.INFLUXDB_BUCKET}")
|
|
38
39
|
|> range(start: -360d)
|
|
39
|
-
|> pivot(rowKey: ["
|
|
40
|
+
|> pivot(rowKey: ["callId"], columnKey: ["_field"], valueColumn: "_value")
|
|
41
|
+
|> map(fn: (r) => ({
|
|
42
|
+
r with
|
|
43
|
+
duration: (int(v: r.endedAt) - int(v: r.startedAt)) / 1000,
|
|
44
|
+
startedAtParsed: int(v: r.startedAt) / 1000,
|
|
45
|
+
}))
|
|
40
46
|
|> filter(fn: (r) => r._measurement == "${types_1.CALL_DETAIL_RECORD_MEASUREMENT}")
|
|
41
47
|
|> filter(fn: (r) => r.ref == ${ref} and r.accessKeyId == "${accessKeyId}")
|
|
42
48
|
|> sort(columns: ["_time"], desc: true)
|
|
43
49
|
|> limit(n: 1)`;
|
|
50
|
+
logger.verbose("fetch single call request", { accessKeyId, ref });
|
|
44
51
|
const items = (yield influxdb.collectRows(query));
|
|
45
52
|
return items.length > 0 ? items[0] : null;
|
|
46
53
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { NatsConnection } from "nats";
|
|
1
2
|
import { z } from "zod";
|
|
2
|
-
import { TrackCallSubscriber } from "./types";
|
|
3
3
|
declare const TrackCallRequestSchema: z.ZodObject<{
|
|
4
4
|
ref: z.ZodString;
|
|
5
5
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -8,7 +8,7 @@ declare const TrackCallRequestSchema: z.ZodObject<{
|
|
|
8
8
|
ref?: string;
|
|
9
9
|
}>;
|
|
10
10
|
type TrackCallRequest = z.infer<typeof TrackCallRequestSchema>;
|
|
11
|
-
declare function
|
|
11
|
+
declare function makeTrackCall(nc: NatsConnection): (call: {
|
|
12
12
|
request: TrackCallRequest;
|
|
13
13
|
}) => void;
|
|
14
|
-
export {
|
|
14
|
+
export { makeTrackCall };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeTrackCall = makeTrackCall;
|
|
4
|
+
/*
|
|
5
|
+
* Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
|
|
6
|
+
* http://github.com/fonoster/fonoster
|
|
7
|
+
*
|
|
8
|
+
* This file is part of Fonoster
|
|
9
|
+
*
|
|
10
|
+
* Licensed under the MIT License (the "License");
|
|
11
|
+
* you may not use this file except in compliance with
|
|
12
|
+
* the License. You may obtain a copy of the License at
|
|
13
|
+
*
|
|
14
|
+
* https://opensource.org/licenses/MIT
|
|
15
|
+
*
|
|
16
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
18
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
19
|
+
* See the License for the specific language governing permissions and
|
|
20
|
+
* limitations under the License.
|
|
21
|
+
*/
|
|
22
|
+
const common_1 = require("@fonoster/common");
|
|
23
|
+
const logger_1 = require("@fonoster/logger");
|
|
24
|
+
const zod_1 = require("zod");
|
|
25
|
+
const envs_1 = require("../envs");
|
|
26
|
+
const FINAL_STATUSES = [
|
|
27
|
+
common_1.DialStatus.ANSWER,
|
|
28
|
+
common_1.DialStatus.BUSY,
|
|
29
|
+
common_1.DialStatus.FAILED,
|
|
30
|
+
common_1.DialStatus.NOANSWER
|
|
31
|
+
];
|
|
32
|
+
const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
|
|
33
|
+
const TrackCallRequestSchema = zod_1.z.object({
|
|
34
|
+
ref: zod_1.z.string()
|
|
35
|
+
});
|
|
36
|
+
function makeTrackCall(nc) {
|
|
37
|
+
const trackingCallsMap = new Map();
|
|
38
|
+
const subscription = nc.subscribe(envs_1.CALLS_TRACK_CALL_SUBJECT);
|
|
39
|
+
subscription.callback = (err, msg) => {
|
|
40
|
+
// We can't do much more than log the error
|
|
41
|
+
if (err) {
|
|
42
|
+
logger.error("call to subscription.callback", { err });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const { ref, status } = msg === null || msg === void 0 ? void 0 : msg.json();
|
|
46
|
+
logger.verbose("call to subscription.callback", { ref, status });
|
|
47
|
+
const stream = trackingCallsMap.get(ref);
|
|
48
|
+
if (!stream) {
|
|
49
|
+
// There is not request to track this call
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (FINAL_STATUSES.includes(status)) {
|
|
53
|
+
stream.write({ ref, status });
|
|
54
|
+
setTimeout(() => stream.end(), 500);
|
|
55
|
+
trackingCallsMap.delete(ref);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
stream.write({ ref, status });
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return (call) => {
|
|
62
|
+
const stream = call;
|
|
63
|
+
const { ref } = call.request;
|
|
64
|
+
logger.verbose("call to trackCall", { ref });
|
|
65
|
+
trackingCallsMap.set(ref, stream);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -31,6 +31,7 @@ exports.createCreateCallSubscriber = createCreateCallSubscriber;
|
|
|
31
31
|
* See the License for the specific language governing permissions and
|
|
32
32
|
* limitations under the License.
|
|
33
33
|
*/
|
|
34
|
+
const common_1 = require("@fonoster/common");
|
|
34
35
|
const logger_1 = require("@fonoster/logger");
|
|
35
36
|
const ari_client_1 = __importDefault(require("ari-client"));
|
|
36
37
|
const nats_1 = require("nats");
|
|
@@ -54,28 +55,26 @@ function createCreateCallSubscriber(config) {
|
|
|
54
55
|
if (err) {
|
|
55
56
|
logger.error(err);
|
|
56
57
|
}
|
|
57
|
-
const { ref, from, to, appRef } = msg.json();
|
|
58
|
-
logger.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
.originate({
|
|
63
|
-
context: envs_1.ASTERISK_CONTEXT,
|
|
64
|
-
extension: envs_1.ASTERISK_EXTENSION,
|
|
58
|
+
const { ref, from, to, appRef, accessKeyId, timeout } = msg.json();
|
|
59
|
+
logger.verbose("received a new call request", Object.assign({}, msg.json()));
|
|
60
|
+
yield ariConn.channels.originateWithId({
|
|
61
|
+
channelId: ref,
|
|
62
|
+
app: common_1.STASIS_APP_NAME,
|
|
65
63
|
endpoint: `PJSIP/${envs_1.ASTERISK_TRUNK}/sip:${to}@${envs_1.ASTERISK_SYSTEM_DOMAIN}`,
|
|
64
|
+
timeout,
|
|
66
65
|
variables: {
|
|
67
|
-
"PJSIP_HEADER(add,X-
|
|
66
|
+
"PJSIP_HEADER(add,X-Call-Ref)": ref,
|
|
67
|
+
"PJSIP_HEADER(add,X-Dod-Number)": from,
|
|
68
|
+
"PJSIP_HEADER(add,X-Access-Key-Id)": accessKeyId,
|
|
69
|
+
"PJSIP_HEADER(add,X-Is-Api-Originated-Type)": "true",
|
|
68
70
|
INGRESS_NUMBER: from,
|
|
69
71
|
APP_REF: appRef
|
|
70
72
|
}
|
|
71
|
-
})
|
|
72
|
-
.catch((err) => {
|
|
73
|
-
logger.error("error creating call", { err });
|
|
74
73
|
});
|
|
75
74
|
});
|
|
76
75
|
}
|
|
77
76
|
catch (e) {
|
|
78
|
-
logger.error("error connecting to ari",
|
|
77
|
+
logger.error("error connecting to ari", e);
|
|
79
78
|
}
|
|
80
79
|
});
|
|
81
80
|
}
|
package/dist/calls/types.d.ts
CHANGED
|
@@ -1,44 +1,12 @@
|
|
|
1
|
-
import { GrpcErrorMessage } from "@fonoster/common";
|
|
1
|
+
import { DialStatus, GrpcErrorMessage } from "@fonoster/common";
|
|
2
|
+
import { CallDirection, CallStatus, CallType } from "@fonoster/types";
|
|
2
3
|
import { ParameterizedQuery } from "@influxdata/influxdb-client";
|
|
3
4
|
declare const CALL_DETAIL_RECORD_MEASUREMENT = "cdr";
|
|
4
|
-
declare enum CallType {
|
|
5
|
-
PROGRAMMABLE = "PROGRAMMABLE",
|
|
6
|
-
SIP_TRUNKING = "SIP_TRUNKING"
|
|
7
|
-
}
|
|
8
|
-
declare enum HangupCause {
|
|
9
|
-
NORMAL_CLEARING = "NORMAL_CLEARING",
|
|
10
|
-
CALL_REJECTED = "CALL_REJECTED",
|
|
11
|
-
UNALLOCATED = "UNALLOCATED",
|
|
12
|
-
NO_USER_RESPONSE = "NO_USER_RESPONSE",
|
|
13
|
-
NO_ROUTE_DESTINATION = "NO_ROUTE_DESTINATION",
|
|
14
|
-
NO_ANSWER = "NO_ANSWER",
|
|
15
|
-
USER_BUSY = "USER_BUSY",
|
|
16
|
-
NOT_ACCEPTABLE_HERE = "NOT_ACCEPTABLE_HERE",
|
|
17
|
-
SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE",
|
|
18
|
-
INVALID_NUMBER_FORMAT = "INVALID_NUMBER_FORMAT"
|
|
19
|
-
}
|
|
20
|
-
declare enum CallStatus {
|
|
21
|
-
QUEUED = "QUEUED",
|
|
22
|
-
RINGING = "RINGING",
|
|
23
|
-
IN_PROGRESS = "IN_PROGRESS",
|
|
24
|
-
COMPLETED = "COMPLETED",
|
|
25
|
-
FAILED = "FAILED",
|
|
26
|
-
BUSY = "BUSY",
|
|
27
|
-
NO_ANSWER = "NO_ANSWER",
|
|
28
|
-
CANCELED = "CANCELED",
|
|
29
|
-
REJECTED = "REJECTED",
|
|
30
|
-
TIMEOUT = "TIMEOUT",
|
|
31
|
-
UNKNOWN = "UNKNOWN"
|
|
32
|
-
}
|
|
33
|
-
declare enum CallDirection {
|
|
34
|
-
INBOUND = "INBOUND",
|
|
35
|
-
OUTBOUND = "OUTBOUND"
|
|
36
|
-
}
|
|
37
5
|
type CallDetailRecord = {
|
|
38
6
|
ref: string;
|
|
39
|
-
|
|
7
|
+
callId: string;
|
|
40
8
|
status: CallStatus;
|
|
41
|
-
|
|
9
|
+
type: CallType;
|
|
42
10
|
from: string;
|
|
43
11
|
to: string;
|
|
44
12
|
duration: number;
|
|
@@ -51,7 +19,6 @@ type ListCallsRequest = {
|
|
|
51
19
|
before?: string;
|
|
52
20
|
type?: CallType;
|
|
53
21
|
status?: CallStatus;
|
|
54
|
-
hangupCause?: HangupCause;
|
|
55
22
|
from?: string;
|
|
56
23
|
to?: string;
|
|
57
24
|
pageSize?: number;
|
|
@@ -71,18 +38,17 @@ type CreateCallRequest = {
|
|
|
71
38
|
from: string;
|
|
72
39
|
to: string;
|
|
73
40
|
appRef?: string;
|
|
74
|
-
|
|
75
|
-
type CreateCallResponse = {
|
|
76
|
-
ref: string;
|
|
41
|
+
timeout?: number;
|
|
77
42
|
};
|
|
78
43
|
type CallPublisher = {
|
|
79
44
|
publishCall: (event: CreateCallRequest & {
|
|
80
45
|
ref: string;
|
|
46
|
+
accessKeyId: string;
|
|
81
47
|
}) => void;
|
|
82
48
|
};
|
|
83
49
|
type TrackCallResponse = {
|
|
84
50
|
ref: string;
|
|
85
|
-
status:
|
|
51
|
+
status: DialStatus;
|
|
86
52
|
};
|
|
87
53
|
type CallStream = {
|
|
88
54
|
write: (data: TrackCallResponse | GrpcErrorMessage) => void;
|
|
@@ -93,4 +59,4 @@ type TrackCallSubscriber = {
|
|
|
93
59
|
on: (event: string, cb: (data: TrackCallResponse | Error) => void) => void;
|
|
94
60
|
};
|
|
95
61
|
};
|
|
96
|
-
export { CALL_DETAIL_RECORD_MEASUREMENT, CallDetailRecord, ListCallsRequest, ListCallsResponse, GetCallRequest, CallType, CallStatus, CallDirection, InfluxDBClient, CreateCallRequest,
|
|
62
|
+
export { CALL_DETAIL_RECORD_MEASUREMENT, CallDetailRecord, ListCallsRequest, ListCallsResponse, GetCallRequest, CallType, CallStatus, CallDirection, InfluxDBClient, CreateCallRequest, CallPublisher, TrackCallResponse, CallStream, TrackCallSubscriber };
|
package/dist/calls/types.js
CHANGED
|
@@ -1,42 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.CallDirection = exports.CallStatus = exports.CallType = exports.CALL_DETAIL_RECORD_MEASUREMENT = void 0;
|
|
4
|
+
const types_1 = require("@fonoster/types");
|
|
5
|
+
Object.defineProperty(exports, "CallDirection", { enumerable: true, get: function () { return types_1.CallDirection; } });
|
|
6
|
+
Object.defineProperty(exports, "CallStatus", { enumerable: true, get: function () { return types_1.CallStatus; } });
|
|
7
|
+
Object.defineProperty(exports, "CallType", { enumerable: true, get: function () { return types_1.CallType; } });
|
|
4
8
|
const CALL_DETAIL_RECORD_MEASUREMENT = "cdr";
|
|
5
9
|
exports.CALL_DETAIL_RECORD_MEASUREMENT = CALL_DETAIL_RECORD_MEASUREMENT;
|
|
6
|
-
var CallType;
|
|
7
|
-
(function (CallType) {
|
|
8
|
-
CallType["PROGRAMMABLE"] = "PROGRAMMABLE";
|
|
9
|
-
CallType["SIP_TRUNKING"] = "SIP_TRUNKING";
|
|
10
|
-
})(CallType || (exports.CallType = CallType = {}));
|
|
11
|
-
var HangupCause;
|
|
12
|
-
(function (HangupCause) {
|
|
13
|
-
HangupCause["NORMAL_CLEARING"] = "NORMAL_CLEARING";
|
|
14
|
-
HangupCause["CALL_REJECTED"] = "CALL_REJECTED";
|
|
15
|
-
HangupCause["UNALLOCATED"] = "UNALLOCATED";
|
|
16
|
-
HangupCause["NO_USER_RESPONSE"] = "NO_USER_RESPONSE";
|
|
17
|
-
HangupCause["NO_ROUTE_DESTINATION"] = "NO_ROUTE_DESTINATION";
|
|
18
|
-
HangupCause["NO_ANSWER"] = "NO_ANSWER";
|
|
19
|
-
HangupCause["USER_BUSY"] = "USER_BUSY";
|
|
20
|
-
HangupCause["NOT_ACCEPTABLE_HERE"] = "NOT_ACCEPTABLE_HERE";
|
|
21
|
-
HangupCause["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
|
|
22
|
-
HangupCause["INVALID_NUMBER_FORMAT"] = "INVALID_NUMBER_FORMAT";
|
|
23
|
-
})(HangupCause || (exports.HangupCause = HangupCause = {}));
|
|
24
|
-
var CallStatus;
|
|
25
|
-
(function (CallStatus) {
|
|
26
|
-
CallStatus["QUEUED"] = "QUEUED";
|
|
27
|
-
CallStatus["RINGING"] = "RINGING";
|
|
28
|
-
CallStatus["IN_PROGRESS"] = "IN_PROGRESS";
|
|
29
|
-
CallStatus["COMPLETED"] = "COMPLETED";
|
|
30
|
-
CallStatus["FAILED"] = "FAILED";
|
|
31
|
-
CallStatus["BUSY"] = "BUSY";
|
|
32
|
-
CallStatus["NO_ANSWER"] = "NO_ANSWER";
|
|
33
|
-
CallStatus["CANCELED"] = "CANCELED";
|
|
34
|
-
CallStatus["REJECTED"] = "REJECTED";
|
|
35
|
-
CallStatus["TIMEOUT"] = "TIMEOUT";
|
|
36
|
-
CallStatus["UNKNOWN"] = "UNKNOWN";
|
|
37
|
-
})(CallStatus || (exports.CallStatus = CallStatus = {}));
|
|
38
|
-
var CallDirection;
|
|
39
|
-
(function (CallDirection) {
|
|
40
|
-
CallDirection["INBOUND"] = "INBOUND";
|
|
41
|
-
CallDirection["OUTBOUND"] = "OUTBOUND";
|
|
42
|
-
})(CallDirection || (exports.CallDirection = CallDirection = {}));
|