1 | "use strict";
|
2 |
|
3 |
|
4 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
5 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
6 | return new (P || (P = Promise))(function (resolve, reject) {
|
7 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
8 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
9 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
10 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
11 | });
|
12 | };
|
13 | Object.defineProperty(exports, "__esModule", { value: true });
|
14 | exports.CloudAdapter = void 0;
|
15 | const z = require("zod");
|
16 | const botbuilder_core_1 = require("botbuilder-core");
|
17 | const streaming_1 = require("./streaming");
|
18 | const ms_rest_js_1 = require("@azure/ms-rest-js");
|
19 | const zod_1 = require("./zod");
|
20 | const interfaces_1 = require("./interfaces");
|
21 | const botFrameworkAdapter_1 = require("./botFrameworkAdapter");
|
22 | const botbuilder_stdlib_1 = require("botbuilder-stdlib");
|
23 | const activityValidator_1 = require("./activityValidator");
|
24 | const botframework_connector_1 = require("botframework-connector");
|
25 | const botframework_streaming_1 = require("botframework-streaming");
|
26 |
|
27 | const ActivityT = z.custom((val) => z.record(z.unknown()).check(val), { message: 'Activity' });
|
28 | class CloudAdapter extends botbuilder_core_1.CloudAdapterBase {
|
29 | |
30 |
|
31 |
|
32 |
|
33 |
|
34 | constructor(botFrameworkAuthentication = botframework_connector_1.BotFrameworkAuthenticationFactory.create()) {
|
35 | super(botFrameworkAuthentication);
|
36 | }
|
37 | |
38 |
|
39 |
|
40 | process(req, resOrSocket, logicOrHead, maybeLogic) {
|
41 | var _a, _b, _c, _d;
|
42 | return __awaiter(this, void 0, void 0, function* () {
|
43 |
|
44 | if (maybeLogic) {
|
45 | const socket = zod_1.INodeSocketT.parse(resOrSocket);
|
46 | const head = zod_1.INodeBufferT.parse(logicOrHead);
|
47 | const logic = zod_1.LogicT.parse(maybeLogic);
|
48 | return this.connect(req, socket, head, logic);
|
49 | }
|
50 | const res = interfaces_1.ResponseT.parse(resOrSocket);
|
51 | const logic = zod_1.LogicT.parse(logicOrHead);
|
52 | const end = (status, body) => {
|
53 | res.status(status);
|
54 | if (body) {
|
55 | res.send(body);
|
56 | }
|
57 | res.end();
|
58 | };
|
59 |
|
60 | if (req.method !== 'POST') {
|
61 | return end(botbuilder_core_1.StatusCodes.METHOD_NOT_ALLOWED);
|
62 | }
|
63 |
|
64 |
|
65 |
|
66 | if (!z.record(z.unknown()).check(req.body)) {
|
67 | return end(botbuilder_core_1.StatusCodes.BAD_REQUEST, '`req.body` not an object, make sure you are using middleware to parse incoming requests.');
|
68 | }
|
69 | const activity = activityValidator_1.validateAndFixActivity(ActivityT.parse(req.body));
|
70 | if (!activity.type) {
|
71 | return end(botbuilder_core_1.StatusCodes.BAD_REQUEST);
|
72 | }
|
73 | const authHeader = z.string().parse((_b = (_a = req.headers.Authorization) !== null && _a !== void 0 ? _a : req.headers.authorization) !== null && _b !== void 0 ? _b : '');
|
74 | try {
|
75 | const invokeResponse = yield this.processActivity(authHeader, activity, logic);
|
76 | return end((_c = invokeResponse === null || invokeResponse === void 0 ? void 0 : invokeResponse.status) !== null && _c !== void 0 ? _c : botbuilder_core_1.StatusCodes.OK, invokeResponse === null || invokeResponse === void 0 ? void 0 : invokeResponse.body);
|
77 | }
|
78 | catch (err) {
|
79 | return end(err instanceof botframework_connector_1.AuthenticationError ? botbuilder_core_1.StatusCodes.UNAUTHORIZED : botbuilder_core_1.StatusCodes.INTERNAL_SERVER_ERROR, (_d = err.message) !== null && _d !== void 0 ? _d : err);
|
80 | }
|
81 | });
|
82 | }
|
83 | |
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 | connectNamedPipe(pipeName, logic, appId, audience, callerId, retryCount = 7) {
|
94 | return __awaiter(this, void 0, void 0, function* () {
|
95 | z.object({
|
96 | pipeName: z.string(),
|
97 | logic: zod_1.LogicT,
|
98 | appId: z.string(),
|
99 | audience: z.string(),
|
100 | callerId: z.string().optional(),
|
101 | }).parse({ pipeName, logic, appId, audience, callerId });
|
102 |
|
103 | const authenticateRequestResult = {
|
104 | audience,
|
105 | callerId,
|
106 | claimsIdentity: appId ? this.createClaimsIdentity(appId) : new botframework_connector_1.ClaimsIdentity([]),
|
107 | };
|
108 |
|
109 | const requestHandler = new StreamingRequestHandler(authenticateRequestResult, (authenticateRequestResult, activity) => this.processActivity(authenticateRequestResult, activity, logic));
|
110 |
|
111 | const server = new botframework_streaming_1.NamedPipeServer(pipeName, requestHandler);
|
112 |
|
113 | requestHandler.server = server;
|
114 |
|
115 | yield botbuilder_stdlib_1.retry(() => server.start(), retryCount);
|
116 | });
|
117 | }
|
118 | connect(req, socket, head, logic) {
|
119 | var _a, _b;
|
120 | return __awaiter(this, void 0, void 0, function* () {
|
121 |
|
122 | const authHeader = z.string().parse((_b = (_a = req.headers.Authorization) !== null && _a !== void 0 ? _a : req.headers.authorization) !== null && _b !== void 0 ? _b : '');
|
123 |
|
124 | const channelIdHeader = z.string().optional().parse(req.headers.channelid);
|
125 |
|
126 | const authenticateRequestResult = yield this.botFrameworkAuthentication.authenticateStreamingRequest(authHeader, channelIdHeader);
|
127 |
|
128 | const requestHandler = new StreamingRequestHandler(authenticateRequestResult, (authenticateRequestResult, activity) => this.processActivity(authenticateRequestResult, activity, logic));
|
129 |
|
130 | const server = new botframework_streaming_1.WebSocketServer(yield new botframework_streaming_1.NodeWebSocketFactory().createWebSocket(req, socket, head), requestHandler);
|
131 |
|
132 | requestHandler.server = server;
|
133 |
|
134 | yield server.start();
|
135 | });
|
136 | }
|
137 | }
|
138 | exports.CloudAdapter = CloudAdapter;
|
139 |
|
140 |
|
141 |
|
142 | class StreamingRequestHandler extends botframework_streaming_1.RequestHandler {
|
143 |
|
144 |
|
145 | constructor(authenticateRequestResult, processActivity) {
|
146 | super();
|
147 | this.authenticateRequestResult = authenticateRequestResult;
|
148 | this.processActivity = processActivity;
|
149 |
|
150 | this.authenticateRequestResult.connectorFactory = new StreamingConnectorFactory(this);
|
151 | }
|
152 | processRequest(request) {
|
153 | var _a, _b;
|
154 | return __awaiter(this, void 0, void 0, function* () {
|
155 | const response = new botframework_streaming_1.StreamingResponse();
|
156 | const end = (statusCode, body) => {
|
157 | response.statusCode = statusCode;
|
158 | if (body) {
|
159 | response.setBody(body);
|
160 | }
|
161 | return response;
|
162 | };
|
163 | if (!request) {
|
164 | return end(botbuilder_core_1.StatusCodes.BAD_REQUEST, 'No request provided.');
|
165 | }
|
166 | if (!request.verb || !request.path) {
|
167 | return end(botbuilder_core_1.StatusCodes.BAD_REQUEST, `Request missing verb and/or path. Verb: ${request.verb}, Path: ${request.path}`);
|
168 | }
|
169 | if (request.verb.toUpperCase() !== streaming_1.POST && request.verb.toUpperCase() !== streaming_1.GET) {
|
170 | return end(botbuilder_core_1.StatusCodes.METHOD_NOT_ALLOWED, `Invalid verb received. Only GET and POST are accepted. Verb: ${request.verb}`);
|
171 | }
|
172 | if (request.path.toLowerCase() === streaming_1.VERSION_PATH) {
|
173 | if (request.verb.toUpperCase() === streaming_1.GET) {
|
174 | return end(botbuilder_core_1.StatusCodes.OK, { UserAgent: botFrameworkAdapter_1.USER_AGENT });
|
175 | }
|
176 | else {
|
177 | return end(botbuilder_core_1.StatusCodes.METHOD_NOT_ALLOWED, `Invalid verb received for path: ${request.path}. Only GET is accepted. Verb: ${request.verb}`);
|
178 | }
|
179 | }
|
180 | const [activityStream, ...attachmentStreams] = request.streams;
|
181 | let activity;
|
182 | try {
|
183 | activity = activityValidator_1.validateAndFixActivity(ActivityT.parse(yield activityStream.readAsJson()));
|
184 | activity.attachments = yield Promise.all(attachmentStreams.map((attachmentStream) => __awaiter(this, void 0, void 0, function* () {
|
185 | const contentType = attachmentStream.contentType;
|
186 | const content = contentType === 'application/json'
|
187 | ? yield attachmentStream.readAsJson()
|
188 | : yield attachmentStream.readAsString();
|
189 | return { contentType, content };
|
190 | })));
|
191 | }
|
192 | catch (err) {
|
193 | return end(botbuilder_core_1.StatusCodes.BAD_REQUEST, `Request body missing or malformed: ${err}`);
|
194 | }
|
195 | try {
|
196 | const invokeResponse = yield this.processActivity(this.authenticateRequestResult, activity);
|
197 | return end((_a = invokeResponse === null || invokeResponse === void 0 ? void 0 : invokeResponse.status) !== null && _a !== void 0 ? _a : botbuilder_core_1.StatusCodes.OK, invokeResponse === null || invokeResponse === void 0 ? void 0 : invokeResponse.body);
|
198 | }
|
199 | catch (err) {
|
200 | return end(botbuilder_core_1.StatusCodes.INTERNAL_SERVER_ERROR, (_b = err.message) !== null && _b !== void 0 ? _b : err);
|
201 | }
|
202 | });
|
203 | }
|
204 | }
|
205 |
|
206 |
|
207 |
|
208 | class StreamingConnectorFactory {
|
209 | constructor(requestHandler) {
|
210 | this.requestHandler = requestHandler;
|
211 | }
|
212 | create(serviceUrl, _audience) {
|
213 | var _a;
|
214 | return __awaiter(this, void 0, void 0, function* () {
|
215 | (_a = this.serviceUrl) !== null && _a !== void 0 ? _a : (this.serviceUrl = serviceUrl);
|
216 | if (serviceUrl !== this.serviceUrl) {
|
217 | throw new Error('This is a streaming scenario, all connectors from this factory must all be for the same url.');
|
218 | }
|
219 | const httpClient = new StreamingHttpClient(this.requestHandler);
|
220 | return new botframework_connector_1.ConnectorClient(botframework_connector_1.MicrosoftAppCredentials.Empty, { httpClient });
|
221 | });
|
222 | }
|
223 | }
|
224 |
|
225 |
|
226 |
|
227 | class StreamingHttpClient {
|
228 | constructor(requestHandler) {
|
229 | this.requestHandler = requestHandler;
|
230 | }
|
231 | sendRequest(httpRequest) {
|
232 | var _a;
|
233 | return __awaiter(this, void 0, void 0, function* () {
|
234 | const streamingRequest = this.createStreamingRequest(httpRequest);
|
235 | const receiveResponse = yield ((_a = this.requestHandler.server) === null || _a === void 0 ? void 0 : _a.send(streamingRequest));
|
236 | return this.createHttpResponse(receiveResponse, httpRequest);
|
237 | });
|
238 | }
|
239 | createStreamingRequest(httpRequest) {
|
240 | const verb = httpRequest.method.toString();
|
241 | const path = httpRequest.url.slice(httpRequest.url.indexOf('/v3'));
|
242 | const request = botframework_streaming_1.StreamingRequest.create(verb, path);
|
243 | request.setBody(httpRequest.body);
|
244 | return request;
|
245 | }
|
246 | createHttpResponse(receiveResponse, httpRequest) {
|
247 | var _a, _b, _c;
|
248 | return __awaiter(this, void 0, void 0, function* () {
|
249 | const [bodyAsText] = (_c = (yield Promise.all((_b = (_a = receiveResponse.streams) === null || _a === void 0 ? void 0 : _a.map((stream) => stream.readAsString())) !== null && _b !== void 0 ? _b : []))) !== null && _c !== void 0 ? _c : [];
|
250 | return {
|
251 | bodyAsText,
|
252 | headers: new ms_rest_js_1.HttpHeaders(),
|
253 | request: httpRequest,
|
254 | status: receiveResponse.statusCode,
|
255 | };
|
256 | });
|
257 | }
|
258 | }
|
259 |
|
\ | No newline at end of file |