@credal/actions 0.2.154 → 0.2.156
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/actions/actionMapper.js +43 -1
- package/dist/actions/autogen/templates.js +24 -15
- package/dist/actions/autogen/types.d.ts +22 -13
- package/dist/actions/autogen/types.js +24 -3
- package/dist/actions/groups.js +1 -11
- package/dist/actions/providers/github/fetchFile.d.ts +3 -0
- package/dist/actions/providers/github/fetchFile.js +131 -0
- package/dist/actions/providers/github/getContents.d.ts +3 -0
- package/dist/actions/providers/github/getContents.js +41 -0
- package/dist/actions/providers/jira/getJiraIssuesByQuery.js +42 -27
- package/dist/actions/providers/slack/getChannelMessages.js +98 -2
- package/dist/actions/providers/slack/messageTransformers.d.ts +53 -0
- package/dist/actions/providers/slack/messageTransformers.js +267 -0
- package/dist/actions/providers/slackUser/searchSlack.d.ts +0 -26
- package/dist/actions/providers/slackUser/searchSlack.js +5 -171
- package/package.json +2 -2
- package/dist/actions/providers/confluence/updatePage.d.ts +0 -3
- package/dist/actions/providers/confluence/updatePage.js +0 -46
- package/dist/actions/providers/credal/callCopilot.d.ts +0 -3
- package/dist/actions/providers/credal/callCopilot.js +0 -36
- package/dist/actions/providers/generic/fillTemplateAction.d.ts +0 -7
- package/dist/actions/providers/generic/fillTemplateAction.js +0 -18
- package/dist/actions/providers/generic/genericApiCall.d.ts +0 -3
- package/dist/actions/providers/generic/genericApiCall.js +0 -38
- package/dist/actions/providers/google-oauth/getDriveContentById.d.ts +0 -3
- package/dist/actions/providers/google-oauth/getDriveContentById.js +0 -161
- package/dist/actions/providers/google-oauth/searchAndGetDriveContentByKeywords.d.ts +0 -3
- package/dist/actions/providers/google-oauth/searchAndGetDriveContentByKeywords.js +0 -47
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByKeywords.d.ts +0 -3
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByKeywords.js +0 -110
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByQuery.d.ts +0 -3
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByQuery.js +0 -78
- package/dist/actions/providers/google-oauth/utils/extractContentFromDriveFileId.d.ts +0 -15
- package/dist/actions/providers/google-oauth/utils/extractContentFromDriveFileId.js +0 -129
- package/dist/actions/providers/googlemaps/nearbysearch.d.ts +0 -3
- package/dist/actions/providers/googlemaps/nearbysearch.js +0 -96
- package/dist/actions/providers/math/index.d.ts +0 -1
- package/dist/actions/providers/math/index.js +0 -37
- package/dist/actions/providers/slack/index.d.ts +0 -1
- package/dist/actions/providers/slack/index.js +0 -37
- package/dist/actions/providers/slack/listConversations.d.ts +0 -3
- package/dist/actions/providers/slack/listConversations.js +0 -41
- package/dist/actions/providers/slackUser/getSlackMessagesInTimeRange.d.ts +0 -3
- package/dist/actions/providers/slackUser/getSlackMessagesInTimeRange.js +0 -81
- package/dist/actions/providers/snowflake/runSnowflakeQueryWriteResultsToS3.d.ts +0 -3
- package/dist/actions/providers/snowflake/runSnowflakeQueryWriteResultsToS3.js +0 -154
- package/dist/actions/providers/x/scrapeTweetDataWithNitter.d.ts +0 -3
- package/dist/actions/providers/x/scrapeTweetDataWithNitter.js +0 -45
|
@@ -10,6 +10,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { axiosClient } from "../../util/axiosClient.js";
|
|
11
11
|
import { getJiraApiConfig, getErrorMessage } from "./utils.js";
|
|
12
12
|
const DEFAULT_LIMIT = 100;
|
|
13
|
+
function extractPlainText(adf) {
|
|
14
|
+
if (!adf || adf.type !== "doc" || !Array.isArray(adf.content))
|
|
15
|
+
return "";
|
|
16
|
+
return adf.content
|
|
17
|
+
.map(block => {
|
|
18
|
+
if (block.type === "paragraph" && Array.isArray(block.content)) {
|
|
19
|
+
return block.content.map(inline => { var _a; return (_a = inline.text) !== null && _a !== void 0 ? _a : ""; }).join("");
|
|
20
|
+
}
|
|
21
|
+
return "";
|
|
22
|
+
})
|
|
23
|
+
.join("\n")
|
|
24
|
+
.trim();
|
|
25
|
+
}
|
|
13
26
|
const getJiraIssuesByQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
14
27
|
const { authToken } = authParams;
|
|
15
28
|
const { query, limit } = params;
|
|
@@ -17,9 +30,6 @@ const getJiraIssuesByQuery = (_a) => __awaiter(void 0, [_a], void 0, function* (
|
|
|
17
30
|
if (!authToken) {
|
|
18
31
|
throw new Error("Auth token is required");
|
|
19
32
|
}
|
|
20
|
-
const queryParams = new URLSearchParams();
|
|
21
|
-
queryParams.set("jql", query);
|
|
22
|
-
queryParams.set("maxResults", String(limit != undefined && limit <= DEFAULT_LIMIT ? limit : DEFAULT_LIMIT));
|
|
23
33
|
const fields = [
|
|
24
34
|
"key",
|
|
25
35
|
"id",
|
|
@@ -39,19 +49,37 @@ const getJiraIssuesByQuery = (_a) => __awaiter(void 0, [_a], void 0, function* (
|
|
|
39
49
|
"timespent",
|
|
40
50
|
"aggregatetimeoriginalestimate",
|
|
41
51
|
];
|
|
42
|
-
queryParams.set("fields", fields.join(","));
|
|
43
52
|
const searchEndpoint = strategy.getSearchEndpoint();
|
|
44
|
-
const
|
|
53
|
+
const requestedLimit = limit !== null && limit !== void 0 ? limit : DEFAULT_LIMIT;
|
|
54
|
+
const allIssues = [];
|
|
55
|
+
let startAt = 0;
|
|
45
56
|
try {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
// Keep fetching pages until we have all requested issues
|
|
58
|
+
while (allIssues.length < requestedLimit) {
|
|
59
|
+
// Calculate how many results to fetch in this request
|
|
60
|
+
const remainingIssues = requestedLimit - allIssues.length;
|
|
61
|
+
const maxResults = Math.min(remainingIssues, DEFAULT_LIMIT);
|
|
62
|
+
const queryParams = new URLSearchParams();
|
|
63
|
+
queryParams.set("jql", query);
|
|
64
|
+
queryParams.set("maxResults", String(maxResults));
|
|
65
|
+
queryParams.set("startAt", String(startAt));
|
|
66
|
+
queryParams.set("fields", fields.join(","));
|
|
67
|
+
const fullApiUrl = `${apiUrl}${searchEndpoint}?${queryParams.toString()}`;
|
|
68
|
+
const response = yield axiosClient.get(fullApiUrl, {
|
|
69
|
+
headers: {
|
|
70
|
+
Authorization: `Bearer ${authToken}`,
|
|
71
|
+
Accept: "application/json",
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
const { issues, total } = response.data;
|
|
75
|
+
allIssues.push(...issues);
|
|
76
|
+
if (allIssues.length >= total || issues.length === 0) {
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
startAt += issues.length;
|
|
80
|
+
}
|
|
52
81
|
return {
|
|
53
|
-
|
|
54
|
-
results: response.data.issues.map(issue => {
|
|
82
|
+
results: allIssues.map(issue => {
|
|
55
83
|
const { id, key, fields } = issue;
|
|
56
84
|
const { summary, description, project, issuetype, status, assignee, reporter, creator, created, updated, resolution, duedate, } = fields;
|
|
57
85
|
const ticketUrl = `${browseUrl}/browse/${key}`;
|
|
@@ -93,22 +121,9 @@ const getJiraIssuesByQuery = (_a) => __awaiter(void 0, [_a], void 0, function* (
|
|
|
93
121
|
catch (error) {
|
|
94
122
|
console.error("Error retrieving Jira issues:", error);
|
|
95
123
|
return {
|
|
96
|
-
|
|
124
|
+
results: [],
|
|
97
125
|
error: getErrorMessage(error),
|
|
98
126
|
};
|
|
99
127
|
}
|
|
100
128
|
});
|
|
101
|
-
function extractPlainText(adf) {
|
|
102
|
-
if (!adf || adf.type !== "doc" || !Array.isArray(adf.content))
|
|
103
|
-
return "";
|
|
104
|
-
return adf.content
|
|
105
|
-
.map(block => {
|
|
106
|
-
if (block.type === "paragraph" && Array.isArray(block.content)) {
|
|
107
|
-
return block.content.map(inline => { var _a; return (_a = inline.text) !== null && _a !== void 0 ? _a : ""; }).join("");
|
|
108
|
-
}
|
|
109
|
-
return "";
|
|
110
|
-
})
|
|
111
|
-
.join("\n")
|
|
112
|
-
.trim();
|
|
113
|
-
}
|
|
114
129
|
export default getJiraIssuesByQuery;
|
|
@@ -10,12 +10,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { WebClient } from "@slack/web-api";
|
|
11
11
|
import { getSlackChannels } from "./helpers.js";
|
|
12
12
|
import { MISSING_AUTH_TOKEN } from "../../util/missingAuthConstants.js";
|
|
13
|
+
import { extractMessageText, transformToSlackMessage, simplifyFile, removeRedundantFields, } from "./messageTransformers.js";
|
|
13
14
|
const getChannelMessages = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
15
|
+
var _b;
|
|
14
16
|
if (!authParams.authToken) {
|
|
15
17
|
throw new Error(MISSING_AUTH_TOKEN);
|
|
16
18
|
}
|
|
17
19
|
const client = new WebClient(authParams.authToken);
|
|
18
|
-
const { channelId: inputChannelId, channelName, oldest } = params;
|
|
20
|
+
const { channelId: inputChannelId, channelName, oldest, latest, limit, cursor, includeThreadReplies } = params;
|
|
19
21
|
if (!inputChannelId && !channelName) {
|
|
20
22
|
throw Error("Either channelId or channelName must be provided");
|
|
21
23
|
}
|
|
@@ -31,12 +33,106 @@ const getChannelMessages = (_a) => __awaiter(void 0, [_a], void 0, function* ({
|
|
|
31
33
|
const messages = yield client.conversations.history({
|
|
32
34
|
channel: channelId,
|
|
33
35
|
oldest: oldest,
|
|
36
|
+
latest: latest,
|
|
37
|
+
limit: limit,
|
|
38
|
+
cursor: cursor,
|
|
34
39
|
});
|
|
35
40
|
if (!messages.ok) {
|
|
36
41
|
throw Error(`Failed to fetch messages from channel ${channelName}, channelId: ${channelId}`);
|
|
37
42
|
}
|
|
43
|
+
let processedMessages = messages.messages;
|
|
44
|
+
// Fetch thread replies if requested
|
|
45
|
+
if (includeThreadReplies) {
|
|
46
|
+
processedMessages = yield Promise.all(processedMessages.map((msg) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
// If message has replies, fetch them
|
|
48
|
+
if (msg.reply_count && msg.reply_count > 0 && msg.ts) {
|
|
49
|
+
try {
|
|
50
|
+
const threadReplies = yield client.conversations.replies({
|
|
51
|
+
channel: channelId,
|
|
52
|
+
ts: msg.ts,
|
|
53
|
+
limit: 20,
|
|
54
|
+
});
|
|
55
|
+
if (threadReplies.ok && threadReplies.messages) {
|
|
56
|
+
// Skip the first message (it's the parent) and process replies
|
|
57
|
+
const replies = threadReplies.messages.slice(1);
|
|
58
|
+
// Process each reply: extract text, simplify files, simplify reactions, remove redundant fields
|
|
59
|
+
msg.replies = replies.map(reply => {
|
|
60
|
+
// Extract text from reply
|
|
61
|
+
const replyTransformed = transformToSlackMessage(reply);
|
|
62
|
+
const replyExtractedText = extractMessageText(replyTransformed);
|
|
63
|
+
if (replyExtractedText) {
|
|
64
|
+
reply.extractedText = replyExtractedText;
|
|
65
|
+
}
|
|
66
|
+
// Simplify files in reply
|
|
67
|
+
if (reply.files && Array.isArray(reply.files)) {
|
|
68
|
+
reply.files = reply.files.map((file) => simplifyFile(file));
|
|
69
|
+
}
|
|
70
|
+
// Simplify reactions in reply
|
|
71
|
+
if (reply.reactions && Array.isArray(reply.reactions)) {
|
|
72
|
+
reply.reactions = reply.reactions.map((reaction) => ({
|
|
73
|
+
name: reaction.name,
|
|
74
|
+
count: reaction.count,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
// Remove redundant fields from reply
|
|
78
|
+
removeRedundantFields(reply);
|
|
79
|
+
return reply;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error(`Failed to fetch replies for message ${msg.ts}:`, error);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return msg;
|
|
88
|
+
})));
|
|
89
|
+
}
|
|
90
|
+
// Transform and enrich messages with extracted text
|
|
91
|
+
processedMessages = processedMessages.map(msg => {
|
|
92
|
+
// Transform to structured message format
|
|
93
|
+
const transformed = transformToSlackMessage(msg);
|
|
94
|
+
// Extract readable text from blocks/attachments
|
|
95
|
+
const extractedText = extractMessageText(transformed);
|
|
96
|
+
if (extractedText) {
|
|
97
|
+
msg.extractedText = extractedText;
|
|
98
|
+
}
|
|
99
|
+
// Simplify files first (to extract highest quality thumb before removing thumb fields)
|
|
100
|
+
if (msg.files && Array.isArray(msg.files)) {
|
|
101
|
+
msg.files = msg.files.map(file => simplifyFile(file));
|
|
102
|
+
}
|
|
103
|
+
// Simplify reactions (remove users array, keep just name and count)
|
|
104
|
+
if (msg.reactions && Array.isArray(msg.reactions)) {
|
|
105
|
+
msg.reactions = msg.reactions.map((reaction) => ({
|
|
106
|
+
name: reaction.name,
|
|
107
|
+
count: reaction.count,
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
// Process root field for thread_broadcast messages
|
|
111
|
+
if (msg.root && typeof msg.root === "object") {
|
|
112
|
+
const root = msg.root;
|
|
113
|
+
// Simplify files in root
|
|
114
|
+
if (root.files && Array.isArray(root.files)) {
|
|
115
|
+
root.files = root.files.map((file) => simplifyFile(file));
|
|
116
|
+
}
|
|
117
|
+
// Simplify reactions in root
|
|
118
|
+
if (root.reactions && Array.isArray(root.reactions)) {
|
|
119
|
+
root.reactions = root.reactions.map((reaction) => ({
|
|
120
|
+
name: reaction.name,
|
|
121
|
+
count: reaction.count,
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
// Remove redundant fields from root
|
|
125
|
+
removeRedundantFields(root);
|
|
126
|
+
}
|
|
127
|
+
// Remove all redundant fields recursively from the entire message
|
|
128
|
+
// Note: replies are already processed when fetched if includeThreadReplies is true
|
|
129
|
+
removeRedundantFields(msg);
|
|
130
|
+
return msg;
|
|
131
|
+
});
|
|
38
132
|
return {
|
|
39
|
-
messages:
|
|
133
|
+
messages: processedMessages,
|
|
134
|
+
hasMore: messages.has_more,
|
|
135
|
+
nextCursor: (_b = messages.response_metadata) === null || _b === void 0 ? void 0 : _b.next_cursor,
|
|
40
136
|
};
|
|
41
137
|
});
|
|
42
138
|
export default getChannelMessages;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { KnownBlock } from "@slack/web-api";
|
|
2
|
+
import type { Attachment } from "@slack/web-api/dist/types/response/ChannelsHistoryResponse.js";
|
|
3
|
+
import type { MessageElement } from "@slack/web-api/dist/types/response/ConversationsHistoryResponse.js";
|
|
4
|
+
export interface SlackMessage {
|
|
5
|
+
ts?: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
user?: string;
|
|
8
|
+
username?: string;
|
|
9
|
+
thread_ts?: string;
|
|
10
|
+
blocks?: KnownBlock[];
|
|
11
|
+
attachments?: Attachment[];
|
|
12
|
+
reactions?: Array<{
|
|
13
|
+
name: string;
|
|
14
|
+
count: number;
|
|
15
|
+
users: string[];
|
|
16
|
+
}>;
|
|
17
|
+
files?: Array<{
|
|
18
|
+
name?: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
mimetype?: string;
|
|
21
|
+
url_private?: string;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
export type SimplifiedFile = {
|
|
25
|
+
id: string;
|
|
26
|
+
created?: number;
|
|
27
|
+
timestamp?: number;
|
|
28
|
+
name?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
mimetype?: string;
|
|
31
|
+
file_access?: string;
|
|
32
|
+
highest_thumb?: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Get the highest quality thumbnail from a file
|
|
36
|
+
*/
|
|
37
|
+
export declare function getHighestQualityThumb(file: Record<string, unknown>): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Simplify file objects to only include essential fields and highest quality thumbnail
|
|
40
|
+
*/
|
|
41
|
+
export declare function simplifyFile(file: Record<string, unknown>): SimplifiedFile;
|
|
42
|
+
/**
|
|
43
|
+
* Recursively remove redundant fields from an object to reduce payload size
|
|
44
|
+
*/
|
|
45
|
+
export declare function removeRedundantFields(obj: Record<string, unknown>): void;
|
|
46
|
+
/**
|
|
47
|
+
* Extracts all visible text from a Slack message
|
|
48
|
+
*/
|
|
49
|
+
export declare function extractMessageText(m: SlackMessage | undefined): string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Transforms a Slack MessageElement to a simplified SlackMessage
|
|
52
|
+
*/
|
|
53
|
+
export declare function transformToSlackMessage(message: MessageElement): SlackMessage;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the highest quality thumbnail from a file
|
|
3
|
+
*/
|
|
4
|
+
export function getHighestQualityThumb(file) {
|
|
5
|
+
const thumbSizes = [
|
|
6
|
+
"thumb_1024",
|
|
7
|
+
"thumb_960",
|
|
8
|
+
"thumb_800",
|
|
9
|
+
"thumb_720",
|
|
10
|
+
"thumb_480",
|
|
11
|
+
"thumb_360",
|
|
12
|
+
"thumb_160",
|
|
13
|
+
"thumb_80",
|
|
14
|
+
"thumb_64",
|
|
15
|
+
];
|
|
16
|
+
for (const size of thumbSizes) {
|
|
17
|
+
const thumb = file[size];
|
|
18
|
+
if (thumb && typeof thumb === "string") {
|
|
19
|
+
return thumb;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Simplify file objects to only include essential fields and highest quality thumbnail
|
|
26
|
+
*/
|
|
27
|
+
export function simplifyFile(file) {
|
|
28
|
+
const simplified = {
|
|
29
|
+
id: file.id,
|
|
30
|
+
created: file.created,
|
|
31
|
+
timestamp: file.timestamp,
|
|
32
|
+
name: file.name,
|
|
33
|
+
title: file.title,
|
|
34
|
+
mimetype: file.mimetype,
|
|
35
|
+
file_access: file.file_access,
|
|
36
|
+
};
|
|
37
|
+
const highestThumb = getHighestQualityThumb(file);
|
|
38
|
+
if (highestThumb) {
|
|
39
|
+
simplified.highest_thumb = highestThumb;
|
|
40
|
+
}
|
|
41
|
+
return simplified;
|
|
42
|
+
}
|
|
43
|
+
// Redundant fields to remove from messages - not useful (fills up context window so we can ditch these)
|
|
44
|
+
const REDUNDANT_FIELDS = [
|
|
45
|
+
// Image/media metadata
|
|
46
|
+
"app_icons",
|
|
47
|
+
"image_width",
|
|
48
|
+
"image_height",
|
|
49
|
+
"image_bytes",
|
|
50
|
+
"fallback",
|
|
51
|
+
"is_animated",
|
|
52
|
+
// Message metadata (not content-related)
|
|
53
|
+
"team",
|
|
54
|
+
"client_msg_id",
|
|
55
|
+
"is_locked",
|
|
56
|
+
"subscribed",
|
|
57
|
+
"display_as_bot",
|
|
58
|
+
"upload",
|
|
59
|
+
// Block metadata
|
|
60
|
+
"block_id",
|
|
61
|
+
"unicode", // Emoji unicode values (name is sufficient)
|
|
62
|
+
// File metadata (duplicates or not useful)
|
|
63
|
+
"file_access",
|
|
64
|
+
"filetype", // Redundant with mimetype
|
|
65
|
+
"pretty_type", // Redundant with mimetype
|
|
66
|
+
"thumb_tiny", // Base64 preview, not needed
|
|
67
|
+
// Attachment metadata
|
|
68
|
+
"service_icon", // Icon URLs for link previews
|
|
69
|
+
"from_url", // Duplicate of original_url
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Recursively remove redundant fields from an object to reduce payload size
|
|
73
|
+
*/
|
|
74
|
+
export function removeRedundantFields(obj) {
|
|
75
|
+
for (const key of REDUNDANT_FIELDS) {
|
|
76
|
+
delete obj[key];
|
|
77
|
+
}
|
|
78
|
+
// Recursively clean nested objects and arrays
|
|
79
|
+
for (const key in obj) {
|
|
80
|
+
const value = obj[key];
|
|
81
|
+
if (value && typeof value === "object") {
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
value.forEach(item => {
|
|
84
|
+
if (item && typeof item === "object") {
|
|
85
|
+
removeRedundantFields(item);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
removeRedundantFields(value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Extracts all visible text from a Slack message
|
|
97
|
+
*/
|
|
98
|
+
export function extractMessageText(m) {
|
|
99
|
+
var _a, _b, _c, _d;
|
|
100
|
+
if (!m)
|
|
101
|
+
return undefined;
|
|
102
|
+
const pieces = [];
|
|
103
|
+
// ---- Rich text helpers ----
|
|
104
|
+
const walkRichTextInline = (el) => {
|
|
105
|
+
var _a;
|
|
106
|
+
const blockPieces = [];
|
|
107
|
+
switch (el.type) {
|
|
108
|
+
case "text":
|
|
109
|
+
blockPieces.push(el.text);
|
|
110
|
+
break;
|
|
111
|
+
case "link":
|
|
112
|
+
blockPieces.push(el.text || el.url);
|
|
113
|
+
break;
|
|
114
|
+
case "user":
|
|
115
|
+
blockPieces.push(`<@${el.user_id}>`);
|
|
116
|
+
break;
|
|
117
|
+
case "channel":
|
|
118
|
+
blockPieces.push(`<#${el.channel_id}>`);
|
|
119
|
+
break;
|
|
120
|
+
case "emoji":
|
|
121
|
+
blockPieces.push(`:${el.name}:`);
|
|
122
|
+
break;
|
|
123
|
+
case "broadcast":
|
|
124
|
+
blockPieces.push(`@${el.range}`);
|
|
125
|
+
break;
|
|
126
|
+
case "date":
|
|
127
|
+
blockPieces.push((_a = el.fallback) !== null && _a !== void 0 ? _a : `<date:${el.timestamp}>`);
|
|
128
|
+
break;
|
|
129
|
+
case "team":
|
|
130
|
+
blockPieces.push(`<team:${el.team_id}>`);
|
|
131
|
+
break;
|
|
132
|
+
case "usergroup":
|
|
133
|
+
blockPieces.push(`<usergroup:${el.usergroup_id}>`);
|
|
134
|
+
break;
|
|
135
|
+
case "color":
|
|
136
|
+
// Usually formatting only, skip
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
return blockPieces;
|
|
140
|
+
};
|
|
141
|
+
const walkRichTextElement = (el) => {
|
|
142
|
+
const result = [];
|
|
143
|
+
switch (el.type) {
|
|
144
|
+
case "rich_text_section":
|
|
145
|
+
case "rich_text_quote":
|
|
146
|
+
result.push(el.elements.map(walkRichTextInline).join("\n"));
|
|
147
|
+
break;
|
|
148
|
+
case "rich_text_list":
|
|
149
|
+
result.push(el.elements.map(section => section.elements.map(walkRichTextInline).join("\n")).join("\n"));
|
|
150
|
+
break;
|
|
151
|
+
case "rich_text_preformatted":
|
|
152
|
+
result.push(el.elements.map(walkRichTextInline).join("\n"));
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
};
|
|
157
|
+
// ---- Block helpers ----
|
|
158
|
+
const walkBlock = (block) => {
|
|
159
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
160
|
+
const blockPieces = [];
|
|
161
|
+
switch (block.type) {
|
|
162
|
+
case "section":
|
|
163
|
+
if ((_a = block.text) === null || _a === void 0 ? void 0 : _a.text)
|
|
164
|
+
blockPieces.push(block.text.text);
|
|
165
|
+
if (block.fields) {
|
|
166
|
+
for (const f of block.fields)
|
|
167
|
+
if (f.text)
|
|
168
|
+
blockPieces.push(f.text);
|
|
169
|
+
}
|
|
170
|
+
if (block.accessory && "text" in block.accessory && block.accessory.text) {
|
|
171
|
+
blockPieces.push(block.accessory.text.text);
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
case "context":
|
|
175
|
+
if (Array.isArray(block.elements)) {
|
|
176
|
+
block.elements.forEach(el => {
|
|
177
|
+
if ("text" in el && el.text)
|
|
178
|
+
blockPieces.push(el.text);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
case "header":
|
|
183
|
+
if ((_b = block.text) === null || _b === void 0 ? void 0 : _b.text)
|
|
184
|
+
blockPieces.push(block.text.text);
|
|
185
|
+
break;
|
|
186
|
+
case "rich_text":
|
|
187
|
+
blockPieces.push(block.elements.map(walkRichTextElement).join("\n"));
|
|
188
|
+
break;
|
|
189
|
+
case "markdown":
|
|
190
|
+
if (block.text)
|
|
191
|
+
blockPieces.push(block.text);
|
|
192
|
+
break;
|
|
193
|
+
case "video":
|
|
194
|
+
if ((_c = block.title) === null || _c === void 0 ? void 0 : _c.text)
|
|
195
|
+
blockPieces.push(block.title.text);
|
|
196
|
+
if ((_d = block.description) === null || _d === void 0 ? void 0 : _d.text)
|
|
197
|
+
blockPieces.push(block.description.text);
|
|
198
|
+
break;
|
|
199
|
+
case "image":
|
|
200
|
+
if ((_e = block.title) === null || _e === void 0 ? void 0 : _e.text)
|
|
201
|
+
blockPieces.push(block.title.text);
|
|
202
|
+
break;
|
|
203
|
+
case "input":
|
|
204
|
+
if ((_f = block.label) === null || _f === void 0 ? void 0 : _f.text)
|
|
205
|
+
blockPieces.push(block.label.text);
|
|
206
|
+
if ((_g = block.hint) === null || _g === void 0 ? void 0 : _g.text)
|
|
207
|
+
blockPieces.push(block.hint.text);
|
|
208
|
+
break;
|
|
209
|
+
// divider, file, actions, input don't contribute visible text
|
|
210
|
+
case "divider":
|
|
211
|
+
case "file":
|
|
212
|
+
case "actions":
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
return blockPieces;
|
|
216
|
+
};
|
|
217
|
+
let blockText = "";
|
|
218
|
+
if (Array.isArray(m.blocks)) {
|
|
219
|
+
const blockPieces = m.blocks.map(b => walkBlock(b));
|
|
220
|
+
blockText = blockPieces.join("\n");
|
|
221
|
+
}
|
|
222
|
+
if (blockText) {
|
|
223
|
+
pieces.push(blockText);
|
|
224
|
+
}
|
|
225
|
+
else if (m.text) {
|
|
226
|
+
pieces.push(m.text);
|
|
227
|
+
}
|
|
228
|
+
// 3. Attachments
|
|
229
|
+
if (m.attachments) {
|
|
230
|
+
for (const att of m.attachments) {
|
|
231
|
+
if (att.pretext)
|
|
232
|
+
pieces.push(att.pretext);
|
|
233
|
+
if (att.title)
|
|
234
|
+
pieces.push(att.title);
|
|
235
|
+
if (att.text)
|
|
236
|
+
pieces.push(att.text);
|
|
237
|
+
if (att.fields) {
|
|
238
|
+
for (const f of att.fields) {
|
|
239
|
+
const title = (_b = (_a = f.title) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : "";
|
|
240
|
+
const value = (_d = (_c = f.value) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : "";
|
|
241
|
+
if (title || value) {
|
|
242
|
+
pieces.push(title && value ? `${title}: ${value}` : title || value);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Deduplicate and join
|
|
249
|
+
const out = Array.from(new Set(pieces.map(s => s.trim()).filter(Boolean))).join("\n");
|
|
250
|
+
return out || undefined;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Transforms a Slack MessageElement to a simplified SlackMessage
|
|
254
|
+
*/
|
|
255
|
+
export function transformToSlackMessage(message) {
|
|
256
|
+
return {
|
|
257
|
+
ts: message.ts,
|
|
258
|
+
text: message.text,
|
|
259
|
+
user: message.user,
|
|
260
|
+
username: message.username,
|
|
261
|
+
thread_ts: message.thread_ts,
|
|
262
|
+
blocks: message.blocks,
|
|
263
|
+
attachments: message.attachments,
|
|
264
|
+
reactions: message.reactions,
|
|
265
|
+
files: message.files,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { type KnownBlock } from "@slack/web-api";
|
|
2
1
|
import { type slackUserSearchSlackFunction } from "../../autogen/types.js";
|
|
3
|
-
import type { Attachment } from "@slack/web-api/dist/types/response/ChannelsHistoryResponse.js";
|
|
4
2
|
export type TimeRange = "latest" | "today" | "yesterday" | "last_7d" | "last_30d" | "all";
|
|
5
3
|
export interface SlackSearchMessage {
|
|
6
4
|
channelId: string;
|
|
@@ -21,29 +19,5 @@ export interface SlackSearchMessage {
|
|
|
21
19
|
userName?: string;
|
|
22
20
|
}>;
|
|
23
21
|
}
|
|
24
|
-
interface SlackMessage {
|
|
25
|
-
ts?: string;
|
|
26
|
-
text?: string;
|
|
27
|
-
user?: string;
|
|
28
|
-
username?: string;
|
|
29
|
-
thread_ts?: string;
|
|
30
|
-
blocks?: KnownBlock[];
|
|
31
|
-
attachments?: Attachment[];
|
|
32
|
-
reactions?: Array<{
|
|
33
|
-
name: string;
|
|
34
|
-
count: number;
|
|
35
|
-
users: string[];
|
|
36
|
-
}>;
|
|
37
|
-
files?: Array<{
|
|
38
|
-
name?: string;
|
|
39
|
-
title?: string;
|
|
40
|
-
mimetype?: string;
|
|
41
|
-
url_private?: string;
|
|
42
|
-
}>;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Extracts all visible text from a Slack message
|
|
46
|
-
*/
|
|
47
|
-
export declare function extractMessageText(m: SlackMessage | undefined): string | undefined;
|
|
48
22
|
declare const searchSlack: slackUserSearchSlackFunction;
|
|
49
23
|
export default searchSlack;
|