feat: add find message action in Slack
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
import SendMessageToChannel from './actions/send-message-to-channel';
|
import SendMessageToChannel from './actions/send-message-to-channel';
|
||||||
|
import FindMessage from './actions/find-message';
|
||||||
import SlackClient from './client';
|
import SlackClient from './client';
|
||||||
|
|
||||||
export default class Actions {
|
export default class Actions {
|
||||||
client: SlackClient;
|
client: SlackClient;
|
||||||
sendMessageToChannel: SendMessageToChannel;
|
sendMessageToChannel: SendMessageToChannel;
|
||||||
|
findMessage: FindMessage;
|
||||||
|
|
||||||
constructor(client: SlackClient) {
|
constructor(client: SlackClient) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.sendMessageToChannel = new SendMessageToChannel(client);
|
this.sendMessageToChannel = new SendMessageToChannel(client);
|
||||||
|
this.findMessage = new FindMessage(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
packages/backend/src/apps/slack/actions/find-message.ts
Normal file
26
packages/backend/src/apps/slack/actions/find-message.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import SlackClient from '../client';
|
||||||
|
|
||||||
|
export default class FindMessage {
|
||||||
|
client: SlackClient;
|
||||||
|
|
||||||
|
constructor(client: SlackClient) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
async run() {
|
||||||
|
const parameters = this.client.step.parameters;
|
||||||
|
const query = parameters.query as string;
|
||||||
|
const sortBy = parameters.sortBy as string;
|
||||||
|
const sortDirection = parameters.sortDirection as string;
|
||||||
|
const count = 1;
|
||||||
|
|
||||||
|
const messages = await this.client.findMessages.run(
|
||||||
|
query,
|
||||||
|
sortBy,
|
||||||
|
sortDirection,
|
||||||
|
count,
|
||||||
|
);
|
||||||
|
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
import SlackClient from '../index';
|
||||||
|
|
||||||
|
export default class FindMessages {
|
||||||
|
client: SlackClient;
|
||||||
|
|
||||||
|
constructor(client: SlackClient) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(
|
||||||
|
query: string,
|
||||||
|
sortBy: string,
|
||||||
|
sortDirection: string,
|
||||||
|
count = 1,
|
||||||
|
) {
|
||||||
|
const headers = {
|
||||||
|
Authorization: `Bearer ${this.client.connection.formattedData.accessToken}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
query,
|
||||||
|
sort: sortBy,
|
||||||
|
sort_dir: sortDirection,
|
||||||
|
count,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await this.client.httpClient.get(
|
||||||
|
'/search.messages',
|
||||||
|
{ headers, params }
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = response.data;
|
||||||
|
const messages = data.messages.matches;
|
||||||
|
const message = messages?.[0];
|
||||||
|
|
||||||
|
if (!data.ok) {
|
||||||
|
if (data.error === 'missing_scope') {
|
||||||
|
throw new Error(
|
||||||
|
`Error occured while finding messages; ${data.error}: ${data.needed}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Error occured while finding messages; ${data.error}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,6 +2,7 @@ import { IFlow, IStep, IConnection } from '@automatisch/types';
|
|||||||
import HttpClient from '../../../helpers/http-client';
|
import HttpClient from '../../../helpers/http-client';
|
||||||
import VerifyAccessToken from './endpoints/verify-access-token';
|
import VerifyAccessToken from './endpoints/verify-access-token';
|
||||||
import PostMessageToChannel from './endpoints/post-message-to-channel';
|
import PostMessageToChannel from './endpoints/post-message-to-channel';
|
||||||
|
import FindMessages from './endpoints/find-messages';
|
||||||
|
|
||||||
export default class SlackClient {
|
export default class SlackClient {
|
||||||
flow: IFlow;
|
flow: IFlow;
|
||||||
@@ -11,6 +12,7 @@ export default class SlackClient {
|
|||||||
|
|
||||||
verifyAccessToken: VerifyAccessToken;
|
verifyAccessToken: VerifyAccessToken;
|
||||||
postMessageToChannel: PostMessageToChannel;
|
postMessageToChannel: PostMessageToChannel;
|
||||||
|
findMessages: FindMessages;
|
||||||
|
|
||||||
static baseUrl = 'https://slack.com/api';
|
static baseUrl = 'https://slack.com/api';
|
||||||
|
|
||||||
@@ -22,5 +24,6 @@ export default class SlackClient {
|
|||||||
this.httpClient = new HttpClient({ baseURL: SlackClient.baseUrl });
|
this.httpClient = new HttpClient({ baseURL: SlackClient.baseUrl });
|
||||||
this.verifyAccessToken = new VerifyAccessToken(this);
|
this.verifyAccessToken = new VerifyAccessToken(this);
|
||||||
this.postMessageToChannel = new PostMessageToChannel(this);
|
this.postMessageToChannel = new PostMessageToChannel(this);
|
||||||
|
this.findMessages = new FindMessages(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -204,6 +204,73 @@
|
|||||||
"name": "Test action"
|
"name": "Test action"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Find message",
|
||||||
|
"key": "findMessage",
|
||||||
|
"description": "Find a Slack message using the Slack Search feature.",
|
||||||
|
"substeps": [
|
||||||
|
{
|
||||||
|
"key": "chooseConnection",
|
||||||
|
"name": "Choose connection"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "setupAction",
|
||||||
|
"name": "Set up action",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"label": "Search Query",
|
||||||
|
"key": "query",
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"description": "Search query to use for finding matching messages. See the Slack Search Documentation for more information on constructing a query.",
|
||||||
|
"variables": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Sort by",
|
||||||
|
"key": "sortBy",
|
||||||
|
"type": "dropdown",
|
||||||
|
"description": "Sort messages by their match strength or by their date. Default is score.",
|
||||||
|
"required": true,
|
||||||
|
"value": "score",
|
||||||
|
"variables": false,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "Match strength",
|
||||||
|
"value": "score"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Message date time",
|
||||||
|
"value": "timestamp"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Sort direction",
|
||||||
|
"key": "sortDirection",
|
||||||
|
"type": "dropdown",
|
||||||
|
"description": "Sort matching messages in ascending or descending order. Default is descending.",
|
||||||
|
"required": true,
|
||||||
|
"value": "desc",
|
||||||
|
"variables": false,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "Descending (newest or best match first)",
|
||||||
|
"value": "desc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Ascending (oldest or worst match first)",
|
||||||
|
"value": "asc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "testStep",
|
||||||
|
"name": "Test action"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -73,6 +73,7 @@ type ActionSubstepArgument {
|
|||||||
description: String
|
description: String
|
||||||
required: Boolean
|
required: Boolean
|
||||||
variables: Boolean
|
variables: Boolean
|
||||||
|
options: [ActionSubstepArgumentOption]
|
||||||
source: ActionSubstepArgumentSource
|
source: ActionSubstepArgumentSource
|
||||||
dependsOn: [String]
|
dependsOn: [String]
|
||||||
}
|
}
|
||||||
@@ -83,6 +84,11 @@ type ActionSubstepArgumentSource {
|
|||||||
arguments: [ActionSubstepArgumentSourceArgument]
|
arguments: [ActionSubstepArgumentSourceArgument]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ActionSubstepArgumentOption {
|
||||||
|
label: String
|
||||||
|
value: JSONObject
|
||||||
|
}
|
||||||
|
|
||||||
type ActionSubstepArgumentSourceArgument {
|
type ActionSubstepArgumentSourceArgument {
|
||||||
name: String
|
name: String
|
||||||
value: String
|
value: String
|
||||||
|
@@ -73,7 +73,7 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
|||||||
{error?.graphQLErrors.map((error) => (<>{error.message}<br /></>))}
|
{error?.graphQLErrors.map((error) => (<>{error.message}<br /></>))}
|
||||||
</Alert>}
|
</Alert>}
|
||||||
|
|
||||||
{called && !response && (
|
{called && !loading && !error && !response && (
|
||||||
<Alert severity="warning" sx={{ mb: 1, width: '100%' }}>
|
<Alert severity="warning" sx={{ mb: 1, width: '100%' }}>
|
||||||
<AlertTitle sx={{ fontWeight: 700 }}>{formatMessage('flowEditor.noTestDataTitle')}</AlertTitle>
|
<AlertTitle sx={{ fontWeight: 700 }}>{formatMessage('flowEditor.noTestDataTitle')}</AlertTitle>
|
||||||
|
|
||||||
|
@@ -95,6 +95,10 @@ export const GET_APPS = gql`
|
|||||||
description
|
description
|
||||||
variables
|
variables
|
||||||
dependsOn
|
dependsOn
|
||||||
|
options {
|
||||||
|
label
|
||||||
|
value
|
||||||
|
}
|
||||||
source {
|
source {
|
||||||
type
|
type
|
||||||
name
|
name
|
||||||
|
Reference in New Issue
Block a user