Posting to Slack uses either channelId or channelName

This commit is contained in:
Matt Aitken
2023-01-20 14:04:09 -08:00
parent 55c0a8bb11
commit 111b0c76a7
6 changed files with 79 additions and 35 deletions
+10 -8
View File
@@ -2,7 +2,7 @@ import { Trigger, customEvent } from "@trigger.dev/sdk";
import { slack } from "@trigger.dev/integrations";
import { z } from "zod";
const trigger = new Trigger({
new Trigger({
id: "send-to-slack-on-new-domain",
name: "Send to Slack on new domain",
apiKey: "trigger_dev_zC25mKNn6c0q",
@@ -21,17 +21,19 @@ const trigger = new Trigger({
"Received domain.created event, waiting for 1 minutes..."
);
await ctx.waitFor("initial-wait", { seconds: 5 });
const response = await slack.postMessage("send-to-slack", {
channel: "test-integrations",
channelName: "test-integrations",
text: `New domain created: ${event.domain} by customer ${event.customerId} cc @Eric #general`,
});
await ctx.logger.debug("Debug message");
await ctx.waitFor("initial-wait", { seconds: 5 });
return response.message;
const secondResponse = await slack.postMessage("send-to-slack-channel-id", {
channelId: response.channel,
text: `Sent using the channelId: ${response.channel}`,
});
return {};
},
});
}).listen();
trigger.listen();
@@ -8,7 +8,6 @@ import {
AccessInfo,
} from "../types";
import { slack } from "@trigger.dev/providers";
import debug from "debug";
import { getAccessToken } from "../accessInfo";
import { z } from "zod";
@@ -66,7 +65,9 @@ class SlackRequestIntegration implements RequestIntegration {
switch (endpoint) {
case "chat.postMessage": {
return {
title: `Post message to #${params.channel}`,
title: `Post message to ${
"channelName" in params ? params.channelName : params.channelId
}`,
properties: [
{
key: "Text",
@@ -86,7 +87,7 @@ class SlackRequestIntegration implements RequestIntegration {
params: any,
cache?: CacheService
): Promise<PerformedRequestResponse> {
const parsedParams = slack.schemas.PostMessageBodySchema.parse(params);
const parsedParams = slack.schemas.PostMessageOptionsSchema.parse(params);
log("chat.postMessage %O", parsedParams);
@@ -97,18 +98,30 @@ class SlackRequestIntegration implements RequestIntegration {
baseUrl: this.baseUrl,
});
const channel = await this.#findChannelId(
service,
parsedParams.channel,
cache
);
const channelId = await this.#findChannelId(service, params, cache);
log("found channelId %s", channel);
if (!channelId) {
return {
ok: false,
isRetryable: false,
response: {
output: {
message: `channelId not found`,
},
context: {
statusCode: 404,
headers: {},
},
},
};
}
log("found channelId %s", channelId);
const response = await service.performRequest(this.#postMessageEndpoint, {
...parsedParams,
link_names: 1,
channel,
channel: channelId,
});
if (!response.success) {
@@ -118,7 +131,7 @@ class SlackRequestIntegration implements RequestIntegration {
ok: false,
isRetryable: this.#isRetryable(response.statusCode),
response: {
output: null,
output: {},
context: {
statusCode: response.statusCode,
headers: response.headers,
@@ -130,19 +143,19 @@ class SlackRequestIntegration implements RequestIntegration {
if (!response.data.ok && response.data.error === "not_in_channel") {
log(
"chat.postMessage failed with not_in_channel, attempting to join channel %s",
channel
channelId
);
// Attempt to join the channel, and then retry the request
const joinResponse = await service.performRequest(
this.#joinChannelEndpoint,
{
channel,
channel: channelId,
}
);
if (joinResponse.success && joinResponse.data.ok) {
log("joined channel %s, retrying postMessage", channel);
log("joined channel %s, retrying postMessage", channelId);
return this.#postMessage(accessInfo, params);
}
@@ -182,14 +195,23 @@ class SlackRequestIntegration implements RequestIntegration {
// unless the channel is already provided in the format of a channelID (for example: "D8572TUFR" or "C01BQJZLJGZ")
async #findChannelId(
service: HttpService,
channel: string,
params: z.infer<typeof slack.schemas.ChannelNameOrIdSchema>,
cache?: CacheService
): Promise<string> {
if (channel.startsWith("C") || channel.startsWith("D")) {
return channel;
): Promise<string | undefined> {
if ("channelId" in params) {
return params.channelId;
}
const cachedChannelId = await cache?.get(channel);
if (!("channelName" in params)) {
throw new Error("Invalid params, mising channelId and channelName");
}
//if the channelName starts with a #, remove it
if (params.channelName.startsWith("#")) {
params.channelName = params.channelName.substring(1);
}
const cachedChannelId = await cache?.get(params.channelName);
if (cachedChannelId) {
return cachedChannelId;
@@ -202,16 +224,17 @@ class SlackRequestIntegration implements RequestIntegration {
if (response.success && response.data.ok) {
const { channels } = response.data;
const channelInfo = channels.find((c: any) => c.name === channel);
const channelInfo = channels.find(
(c: any) => c.name === params.channelName
);
if (channelInfo) {
await cache?.set(channel, channelInfo.id, 60 * 60 * 24);
await cache?.set(params.channelName, channelInfo.id, 60 * 60 * 24);
return channelInfo.id;
}
return channelInfo?.id || channel;
}
return channel;
return undefined;
}
}
+1 -1
View File
@@ -19,7 +19,7 @@ export interface NormalizedRequest {
}
export interface NormalizedResponse {
output: any;
output: NonNullable<any>;
context: any;
}
@@ -3,7 +3,7 @@ import { z } from "zod";
import { slack } from "@trigger.dev/providers";
export type PostMessageOptions = z.infer<
typeof slack.schemas.PostMessageBodySchema
typeof slack.schemas.PostMessageOptionsSchema
>;
export type PostMessageResponse = z.infer<
@@ -7,7 +7,15 @@ export const slack = {
enabledFor: "all",
authentication: {
type: "oauth",
scopes: ["channels:read", "channels:join", "chat:write"],
scopes: [
"channels:read",
"channels:join",
"channels:manage",
"chat:write",
"groups:write",
"im:write",
"mpim:write",
],
},
schemas,
};
@@ -30,6 +30,17 @@ export const PostMessageBodySchema = z.object({
text: z.string(),
});
export const ChannelNameOrIdSchema = z.union([
z.object({ channelId: z.string() }),
z.object({ channelName: z.string() }),
]);
export const PostMessageOptionsSchema = z
.object({
text: z.string(),
})
.and(ChannelNameOrIdSchema);
export const JoinConversationSuccessResponseSchema = z.object({
ok: z.literal(true),
channel: z.object({