1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | Object.defineProperty(exports, "__esModule", { value: true });
|
18 | const slack_messages_1 = require("@atomist/slack-messages");
|
19 | const pubsub_1 = require("@google-cloud/pubsub");
|
20 | const log_1 = require("./log");
|
21 | const payload_1 = require("./payload");
|
22 | const util_1 = require("./util");
|
23 | const cloneDeep = require("lodash.clonedeep");
|
24 |
|
25 | exports.MessageMimeTypes = {
|
26 | SLACK_JSON: "application/x-atomist-slack+json",
|
27 | SLACK_FILE_JSON: "application/x-atomist-slack-file+json",
|
28 | PLAIN_TEXT: "text/plain",
|
29 | APPLICATION_JSON: "application/json",
|
30 | };
|
31 | class MessageClientSupport {
|
32 | respond(msg, options) {
|
33 | return this.doSend(msg, { users: [], channels: [] }, options);
|
34 | }
|
35 | send(msg, destinations, options) {
|
36 | return this.doSend(msg, destinations, options);
|
37 | }
|
38 | }
|
39 | exports.MessageClientSupport = MessageClientSupport;
|
40 | class AbstractMessageClient extends MessageClientSupport {
|
41 | constructor(request, correlationId, team, source, graphClient) {
|
42 | super();
|
43 | this.request = request;
|
44 | this.correlationId = correlationId;
|
45 | this.team = team;
|
46 | this.source = source;
|
47 | this.graphClient = graphClient;
|
48 | }
|
49 | async delete(destinations, options) {
|
50 | return this.doSend(undefined, destinations, Object.assign(Object.assign({}, options), { delete: true }));
|
51 | }
|
52 |
|
53 | async doSend(msg, destinations, options = {}) {
|
54 | var _a, _b, _c, _d, _e;
|
55 | if (!!msg && msg.content_type === "application/x-atomist-continuation+json") {
|
56 | return this.sendResponse(msg).then(() => msg);
|
57 | }
|
58 | const ts = this.ts(options);
|
59 | const responseDestinations = [];
|
60 | let threadTs;
|
61 | if (options.thread === true && !!this.source) {
|
62 | threadTs = (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.slack) === null || _b === void 0 ? void 0 : _b.message.ts;
|
63 | }
|
64 | else if (typeof options.thread === "string") {
|
65 | threadTs = options.thread;
|
66 | }
|
67 | const teamId = await this.getTeamId((_e = (_d = (_c = this.source) === null || _c === void 0 ? void 0 : _c.slack) === null || _d === void 0 ? void 0 : _d.team) === null || _e === void 0 ? void 0 : _e.id, this.graphClient);
|
68 | util_1.toArray(destinations.users || []).forEach(d => {
|
69 | responseDestinations.push({
|
70 | user_agent: "slack",
|
71 | slack: {
|
72 | team: {
|
73 | id: teamId,
|
74 | },
|
75 | user: {
|
76 | name: d,
|
77 | },
|
78 | thread_ts: threadTs,
|
79 | },
|
80 | });
|
81 | });
|
82 | util_1.toArray(destinations.channels || []).forEach(d => {
|
83 | responseDestinations.push({
|
84 | user_agent: "slack",
|
85 | slack: {
|
86 | team: {
|
87 | id: teamId,
|
88 | },
|
89 | channel: {
|
90 | name: d,
|
91 | },
|
92 | thread_ts: threadTs,
|
93 | },
|
94 | });
|
95 | });
|
96 | if (responseDestinations.length === 0 && this.source) {
|
97 | const responseDestination = cloneDeep(this.source);
|
98 | if (responseDestination.slack) {
|
99 | delete responseDestination.slack.user;
|
100 | if (threadTs) {
|
101 | responseDestination.slack.thread_ts = threadTs;
|
102 | }
|
103 | }
|
104 | responseDestinations.push(responseDestination);
|
105 | }
|
106 | const response = {
|
107 | api_version: "1",
|
108 | correlation_id: this.correlationId,
|
109 | team: this.team,
|
110 | source: this.source ? this.source : undefined,
|
111 | command: payload_1.isCommandIncoming(this.request) ? this.request.command : undefined,
|
112 | event: payload_1.isEventIncoming(this.request) ? this.request.extensions.operationName : undefined,
|
113 | destinations: responseDestinations,
|
114 | id: options.id ? options.id : undefined,
|
115 | timestamp: ts,
|
116 | ttl: ts && options.ttl ? options.ttl : undefined,
|
117 | post_mode: options.post === "update_only" ? "update_only" : (options.post === "always" ? "always" : "ttl"),
|
118 | skill: this.request.skill,
|
119 | };
|
120 | if (isSlackMessage(msg)) {
|
121 | const msgClone = cloneDeep(msg);
|
122 | const actions = mapActions(msgClone);
|
123 | response.content_type = exports.MessageMimeTypes.SLACK_JSON;
|
124 | response.body = slack_messages_1.render(msgClone, false);
|
125 | response.actions = actions;
|
126 | }
|
127 | else if (isFileMessage(msg)) {
|
128 | response.content_type = exports.MessageMimeTypes.SLACK_FILE_JSON;
|
129 | response.body = JSON.stringify({
|
130 | content: msg.content,
|
131 | filename: msg.fileName,
|
132 | filetype: msg.fileType,
|
133 | title: msg.title,
|
134 | initial_comment: msg.comment,
|
135 | });
|
136 | }
|
137 | else if (typeof msg === "string") {
|
138 | response.content_type = exports.MessageMimeTypes.PLAIN_TEXT;
|
139 | response.body = msg;
|
140 | }
|
141 | else if (options.delete) {
|
142 | response.content_type = "application/x-atomist-delete";
|
143 | response.body = undefined;
|
144 | }
|
145 | return this.sendResponse(response).then(() => response);
|
146 | }
|
147 | ts(options) {
|
148 | if (options.id) {
|
149 | if (options.ts) {
|
150 | return options.ts;
|
151 | }
|
152 | else {
|
153 | return Date.now();
|
154 | }
|
155 | }
|
156 | else {
|
157 | return undefined;
|
158 | }
|
159 | }
|
160 | async getTeamId(teamId, graphClient) {
|
161 | var _a;
|
162 | if (teamId) {
|
163 | return teamId;
|
164 | }
|
165 | else {
|
166 | const query = `query ChatTeam { ChatTeam { id } }`;
|
167 | const result = await graphClient.query(query);
|
168 | return (_a = result === null || result === void 0 ? void 0 : result.ChatTeam[0]) === null || _a === void 0 ? void 0 : _a.id;
|
169 | }
|
170 | }
|
171 | }
|
172 | exports.AbstractMessageClient = AbstractMessageClient;
|
173 | function mapActions(msg) {
|
174 | const actions = [];
|
175 | let counter = 0;
|
176 | if (msg.attachments) {
|
177 | msg.attachments.filter(attachment => attachment.actions).forEach(attachment => {
|
178 | attachment.actions.forEach(a => {
|
179 | if (!!a && !!a.command) {
|
180 | const cra = a;
|
181 | const id = counter++;
|
182 | cra.command.id = `${cra.command.id}-${id}`;
|
183 | a.name = `${a.name}-${id}`;
|
184 | const action = {
|
185 | id: cra.command.id,
|
186 | parameter_name: cra.command.parameterName,
|
187 | command: cra.command.name,
|
188 | parameters: mapParameters(cra.command.parameters),
|
189 | };
|
190 | actions.push(action);
|
191 |
|
192 | cra.command = undefined;
|
193 | }
|
194 | });
|
195 | });
|
196 | }
|
197 | return actions;
|
198 | }
|
199 | exports.mapActions = mapActions;
|
200 | function mapParameters(data) {
|
201 | const parameters = [];
|
202 | for (const key in data) {
|
203 | const value = data[key];
|
204 | if (value) {
|
205 | parameters.push({
|
206 | name: key,
|
207 | value: value.toString(),
|
208 | });
|
209 | }
|
210 | else {
|
211 |
|
212 | }
|
213 | }
|
214 | return parameters;
|
215 | }
|
216 | function isSlackMessage(object) {
|
217 | return !!object && (object.text || object.attachments || object.blocks) && !object.content;
|
218 | }
|
219 | exports.isSlackMessage = isSlackMessage;
|
220 | function isFileMessage(object) {
|
221 | return !!object && !object.length && object.content;
|
222 | }
|
223 | exports.isFileMessage = isFileMessage;
|
224 | class AbstractPubSubMessageClient extends AbstractMessageClient {
|
225 | constructor(request, correlationId, team, source, graphClient) {
|
226 | super(request, correlationId, team, source, graphClient);
|
227 | this.request = request;
|
228 | this.correlationId = correlationId;
|
229 | this.team = team;
|
230 | this.source = source;
|
231 | this.graphClient = graphClient;
|
232 | this.pubsub = new pubsub_1.PubSub();
|
233 | }
|
234 | async sendResponse(message) {
|
235 | const topicName = process.env.ATOMIST_TOPIC || process.env.TOPIC;
|
236 | try {
|
237 | log_1.debug(`Sending message: ${JSON.stringify(message, util_1.replacer)}`);
|
238 | if (topicName) {
|
239 | const topic = this.pubsub.topic(topicName);
|
240 | const messageBuffer = Buffer.from(JSON.stringify(message), "utf8");
|
241 | await topic.publish(messageBuffer);
|
242 | }
|
243 | }
|
244 | catch (err) {
|
245 | log_1.error(`Error occurred sending message: ${err.message}`);
|
246 | }
|
247 | }
|
248 | }
|
249 | class PubSubCommandMessageClient extends AbstractPubSubMessageClient {
|
250 | constructor(request, graphClient) {
|
251 | super(request, request.correlation_id, request.team, request.source, graphClient);
|
252 | this.request = request;
|
253 | this.graphClient = graphClient;
|
254 | }
|
255 | async doSend(msg, destinations, options = {}) {
|
256 | return super.doSend(msg, destinations, options);
|
257 | }
|
258 | async publish(status) {
|
259 | const source = cloneDeep(this.request.source);
|
260 | if (source && source.slack) {
|
261 | delete source.slack.user;
|
262 | }
|
263 | const response = {
|
264 | api_version: "1",
|
265 | correlation_id: this.request.correlation_id,
|
266 | team: this.request.team,
|
267 | command: this.request.command,
|
268 | source: this.request.source,
|
269 | destinations: [source],
|
270 | status,
|
271 | skill: this.request.skill,
|
272 | };
|
273 | return this.sendResponse(response);
|
274 | }
|
275 | }
|
276 | exports.PubSubCommandMessageClient = PubSubCommandMessageClient;
|
277 | class PubSubEventMessageClient extends AbstractPubSubMessageClient {
|
278 | constructor(request, graphClient) {
|
279 | super(request, request.extensions.correlation_id, { id: request.extensions.team_id, name: request.extensions.team_name }, undefined, graphClient);
|
280 | this.request = request;
|
281 | this.graphClient = graphClient;
|
282 | }
|
283 | async doSend(msg, destinations, options = {}) {
|
284 | return super.doSend(msg, destinations, options);
|
285 | }
|
286 | async publish(status) {
|
287 | const response = {
|
288 | api_version: "1",
|
289 | correlation_id: this.request.extensions.correlation_id,
|
290 | team: {
|
291 | id: this.request.extensions.team_id,
|
292 | name: this.request.extensions.team_name,
|
293 | },
|
294 | event: this.request.extensions.operationName,
|
295 | status,
|
296 | skill: this.request.skill,
|
297 | };
|
298 | return this.sendResponse(response);
|
299 | }
|
300 | }
|
301 | exports.PubSubEventMessageClient = PubSubEventMessageClient;
|
302 | function prepareStatus(status, context) {
|
303 | if (status instanceof Error) {
|
304 | return {
|
305 | code: 1,
|
306 | reason: `Error invoking ${context.skill.namespace}/${context.skill.name}`,
|
307 | };
|
308 | }
|
309 | else {
|
310 | const reason = `${(status === null || status === void 0 ? void 0 : status.code) === 0 ? "Successfully" : "Unsuccessfully"} invoked ${context.skill.namespace}/${context.skill.name}`;
|
311 | return {
|
312 | visibility: status === null || status === void 0 ? void 0 : status.visibility,
|
313 | code: (status === null || status === void 0 ? void 0 : status.code) || 0,
|
314 | reason: (status === null || status === void 0 ? void 0 : status.reason) || reason,
|
315 | };
|
316 | }
|
317 | }
|
318 | exports.prepareStatus = prepareStatus;
|
319 |
|
\ | No newline at end of file |