var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import HTTPErrorResponse from "../../../../Types/API/HTTPErrorResponse";
import URL from "../../../../Types/API/URL";
import API from "../../../../Utils/API";
import logger from "../../Logger";
import BadRequestException from "../../../../Types/Exception/BadRequestException";
import WorkspaceBase from "../WorkspaceBase";
import WorkspaceType from "../../../../Types/Workspace/WorkspaceType";
import SlackifyMarkdown from "slackify-markdown";
import OneUptimeDate from "../../../../Types/Date";
import CaptureSpan from "../../Telemetry/CaptureSpan";
import BadDataException from "../../../../Types/Exception/BadDataException";
import WorkspaceProjectAuthTokenService from "../../../Services/WorkspaceProjectAuthTokenService";
export default class SlackUtil extends WorkspaceBase {
    static isValidSlackIncomingWebhookUrl(incomingWebhookUrl) {
        // check if the URL starts with https://hooks.slack.com/services/
        return incomingWebhookUrl
            .toString()
            .startsWith("https://hooks.slack.com/services/");
    }
    static async getUsernameFromUserId(data) {
        var _a, _b, _c, _d;
        const usernameLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Getting username from user ID with data:", usernameLogAttributes);
        logger.debug(data, usernameLogAttributes);
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/users.info"),
            data: {
                user: data.userId,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/x-www-form-urlencoded",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for getting user info:", usernameLogAttributes);
        logger.debug(response, usernameLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", usernameLogAttributes);
            logger.error(response, usernameLogAttributes);
            throw response;
        }
        // check for ok response
        if (((_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", usernameLogAttributes);
            logger.error(response.jsonData, usernameLogAttributes);
            return null;
        }
        if (!((_d = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["user"]) === null || _d === void 0 ? void 0 : _d["name"])) {
            logger.error("Invalid response from Slack API:", usernameLogAttributes);
            logger.error(response.jsonData, usernameLogAttributes);
            return null;
        }
        const username = response.jsonData["user"]["name"];
        logger.debug("Username obtained:", usernameLogAttributes);
        logger.debug(username, usernameLogAttributes);
        return username;
    }
    static async showModalToUser(data) {
        var _a, _b;
        const modalLogAttributes = { triggerId: data.triggerId };
        logger.debug("Showing modal to user with data:", modalLogAttributes);
        logger.debug(data, modalLogAttributes);
        const modalJson = this.getModalBlock({
            payloadModalBlock: data.modalBlock,
        });
        logger.debug("Modal JSON generated:", modalLogAttributes);
        logger.debug(JSON.stringify(modalJson, null, 2), modalLogAttributes);
        // use view.open API to show modal
        const result = await API.post({
            url: URL.fromString("https://slack.com/api/views.open"),
            data: {
                trigger_id: data.triggerId,
                view: modalJson,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/json",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        if (result instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", modalLogAttributes);
            logger.error(result, modalLogAttributes);
            throw result;
        }
        if (((_a = result.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", modalLogAttributes);
            logger.error(result.jsonData, modalLogAttributes);
            const messageFromSlack = (_b = result.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        logger.debug("Modal shown to user successfully.", modalLogAttributes);
    }
    static async sendEphemeralMessageToChannel(data) {
        var _a, _b;
        const blocks = this.getBlocksFromWorkspaceMessagePayload({
            messageBlocks: data.messageBlocks,
        });
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/chat.postEphemeral"),
            data: {
                channel: data.channelId,
                user: data.userId,
                blocks: blocks,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/json",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API for ephemeral message:", {
                channelId: data.channelId,
            });
            logger.error(response, { channelId: data.channelId });
            throw response;
        }
        if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API for ephemeral message:", {
                channelId: data.channelId,
            });
            logger.error(response.jsonData, {
                channelId: data.channelId,
            });
            const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        logger.debug("Ephemeral message sent successfully.", {
            channelId: data.channelId,
        });
    }
    static async sendDirectMessageToUser(data) {
        // Send direct message to user
        const blocks = this.getBlocksFromWorkspaceMessagePayload({
            messageBlocks: data.messageBlocks,
        });
        await this.sendPayloadBlocksToChannel({
            authToken: data.authToken,
            workspaceChannel: {
                id: data.workspaceUserId,
                name: "",
                workspaceType: WorkspaceType.Slack,
            },
            blocks: blocks,
        });
    }
    static async archiveChannels(data) {
        var _a, _b, _c;
        if (data.sendMessageBeforeArchiving) {
            await this.sendMessage({
                workspaceMessagePayload: {
                    _type: "WorkspaceMessagePayload",
                    channelNames: [],
                    channelIds: data.channelIds,
                    messageBlocks: [data.sendMessageBeforeArchiving],
                    workspaceType: WorkspaceType.Slack,
                },
                authToken: data.authToken,
                userId: data.userId,
                projectId: data.projectId,
            });
        }
        const archiveLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Archiving channels with data:", archiveLogAttributes);
        logger.debug(data, archiveLogAttributes);
        for (const channelId of data.channelIds) {
            const response = await API.post({
                url: URL.fromString("https://slack.com/api/conversations.archive"),
                data: {
                    channel: channelId,
                },
                headers: {
                    Authorization: `Bearer ${data.authToken}`,
                    ["Content-Type"]: "application/x-www-form-urlencoded",
                },
                options: {
                    retries: 3,
                    exponentialBackoff: true,
                },
            });
            logger.debug("Response from Slack API for archiving channel:", archiveLogAttributes);
            logger.debug(response, archiveLogAttributes);
            if (response instanceof HTTPErrorResponse) {
                logger.error("Error response from Slack API:", archiveLogAttributes);
                logger.error(response, archiveLogAttributes);
                throw response;
            }
            if (((_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["ok"]) !== true) {
                logger.error("Invalid response from Slack API:", archiveLogAttributes);
                logger.error(response.jsonData, archiveLogAttributes);
                const messageFromSlack = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["error"];
                throw new BadRequestException("Error from Slack " + messageFromSlack);
            }
        }
        logger.debug("Channels archived successfully.", archiveLogAttributes);
    }
    static async joinChannel(data) {
        var _a, _b;
        const joinLogAttributes = { channelId: data.channelId };
        logger.debug("Joining channel with data:", joinLogAttributes);
        logger.debug(data, joinLogAttributes);
        // Join channel
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/conversations.join"),
            data: {
                channel: data.channelId,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/x-www-form-urlencoded",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for joining channel:", joinLogAttributes);
        logger.debug(response, joinLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", joinLogAttributes);
            logger.error(response, joinLogAttributes);
            throw response;
        }
        if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", joinLogAttributes);
            logger.error(response.jsonData, joinLogAttributes);
            const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        logger.debug("Channel joined successfully with data:", joinLogAttributes);
        logger.debug(data, joinLogAttributes);
    }
    static async inviteUserToChannelByChannelId(data) {
        var _a, _b;
        // check if already in channel.
        const isUserInChannel = await this.isUserInChannel({
            authToken: data.authToken,
            channelId: data.channelId,
            userId: data.workspaceUserId,
        });
        if (isUserInChannel) {
            logger.debug("User already in channel.", {
                channelId: data.channelId,
            });
            return;
        }
        const inviteByIdLogAttributes = {
            channelId: data.channelId,
        };
        logger.debug("Inviting user to channel with data:", inviteByIdLogAttributes);
        logger.debug(data, inviteByIdLogAttributes);
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/conversations.invite"),
            data: {
                channel: data.channelId,
                users: data.workspaceUserId,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/x-www-form-urlencoded",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for inviting user:", inviteByIdLogAttributes);
        logger.debug(response, inviteByIdLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", inviteByIdLogAttributes);
            logger.error(response, inviteByIdLogAttributes);
            throw response;
        }
        if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", inviteByIdLogAttributes);
            logger.error(response.jsonData, inviteByIdLogAttributes);
            const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        logger.debug("User invited to channel successfully.", inviteByIdLogAttributes);
    }
    static async inviteUserToChannelByChannelName(data) {
        var _a, _b;
        if (data.channelName && data.channelName.startsWith("#")) {
            // trim # from channel name
            data.channelName = data.channelName.substring(1);
        }
        logger.debug("Inviting user to channel with data:", {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        });
        logger.debug(data, {
            projectId: (_b = data.projectId) === null || _b === void 0 ? void 0 : _b.toString(),
        });
        const channelId = (await this.getWorkspaceChannelFromChannelName({
            authToken: data.authToken,
            channelName: data.channelName,
            projectId: data.projectId,
        })).id;
        return this.inviteUserToChannelByChannelId({
            authToken: data.authToken,
            channelId: channelId,
            workspaceUserId: data.workspaceUserId,
        });
    }
    static async createChannelsIfDoesNotExist(data) {
        var _a;
        const createChLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Creating channels if they do not exist with data:", createChLogAttributes);
        logger.debug(data, createChLogAttributes);
        const workspaceChannels = [];
        for (let channelName of data.channelNames) {
            /*
             * Normalize channel name: replace spaces with hyphens, then strip
             * any characters not valid in Slack channel names.
             */
            channelName = channelName
                .toLowerCase()
                .replace(/\s+/g, "-")
                .replace(/[^a-z0-9\-_]/g, "");
            // Check if channel exists using optimized method
            const existingChannel = await this.getWorkspaceChannelByName({
                authToken: data.authToken,
                channelName: channelName,
                projectId: data.projectId,
            });
            if (existingChannel) {
                logger.debug(`Channel ${channelName} already exists.`, createChLogAttributes);
                workspaceChannels.push(existingChannel);
                continue;
            }
            logger.debug(`Channel ${channelName} does not exist. Creating channel.`, createChLogAttributes);
            const channel = await this.createChannel({
                authToken: data.authToken,
                channelName: channelName,
                projectId: data.projectId,
            });
            if (channel) {
                logger.debug(`Channel ${channelName} created successfully.`, createChLogAttributes);
                workspaceChannels.push(channel);
            }
        }
        logger.debug("Channels created or found:", createChLogAttributes);
        logger.debug(workspaceChannels, createChLogAttributes);
        return workspaceChannels;
    }
    static async getWorkspaceChannelFromChannelName(data) {
        var _a;
        const getChNameLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Getting workspace channel ID from channel name with data:", getChNameLogAttributes);
        logger.debug(data, getChNameLogAttributes);
        const channel = await this.getWorkspaceChannelByName({
            authToken: data.authToken,
            channelName: data.channelName,
            projectId: data.projectId,
        });
        if (!channel) {
            logger.error("Channel not found.", getChNameLogAttributes);
            throw new BadDataException("Channel not found.");
        }
        logger.debug("Workspace channel obtained:", getChNameLogAttributes);
        logger.debug(channel, getChNameLogAttributes);
        return channel;
    }
    static async getWorkspaceChannelFromChannelId(data) {
        var _a, _b, _c, _d;
        const getChIdLogAttributes = { channelId: data.channelId };
        logger.debug("Getting workspace channel from channel ID with data:", getChIdLogAttributes);
        logger.debug(data, getChIdLogAttributes);
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/conversations.info"),
            data: {
                channel: data.channelId,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/x-www-form-urlencoded",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for getting channel info:", getChIdLogAttributes);
        logger.debug(response, getChIdLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", getChIdLogAttributes);
            logger.error(response, getChIdLogAttributes);
            throw response;
        }
        // check for ok response
        if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", getChIdLogAttributes);
            logger.error(response.jsonData, getChIdLogAttributes);
            const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        if (!((_d = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["channel"]) === null || _d === void 0 ? void 0 : _d["name"])) {
            logger.error("Invalid response from Slack API:", getChIdLogAttributes);
            logger.error(response.jsonData, getChIdLogAttributes);
            throw new Error("Invalid response");
        }
        const channel = {
            name: response.jsonData["channel"]["name"],
            id: data.channelId,
            workspaceType: WorkspaceType.Slack,
        };
        logger.debug("Workspace channel obtained:", getChIdLogAttributes);
        logger.debug(channel, getChIdLogAttributes);
        return channel;
    }
    static async getAllWorkspaceChannels(data) {
        var _a, _b, _c, _d;
        const getAllChLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Getting all workspace channels with data:", getAllChLogAttributes);
        logger.debug(data, getAllChLogAttributes);
        const channels = {};
        let cursor = undefined;
        const maxPages = 100;
        let pageCount = 0;
        const localChannelCache = {};
        do {
            const requestBody = {
                limit: 999,
                types: "public_channel,private_channel",
                exclude_archived: true,
            };
            if (cursor) {
                requestBody["cursor"] = cursor;
            }
            const response = await API.post({
                url: URL.fromString("https://slack.com/api/conversations.list"),
                data: requestBody,
                headers: {
                    Authorization: `Bearer ${data.authToken}`,
                    ["Content-Type"]: "application/x-www-form-urlencoded",
                },
                options: {
                    retries: 3,
                    exponentialBackoff: true,
                },
            });
            if (response instanceof HTTPErrorResponse) {
                logger.error("Error response from Slack API:", getAllChLogAttributes);
                logger.error(response, getAllChLogAttributes);
                throw response;
            }
            // check for ok response
            if (((_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["ok"]) !== true) {
                logger.error("Invalid response from Slack API:", getAllChLogAttributes);
                logger.error(response.jsonData, getAllChLogAttributes);
                const messageFromSlack = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["error"];
                throw new BadRequestException("Error from Slack " + messageFromSlack);
            }
            for (const channel of response.jsonData["channels"]) {
                if (!channel["id"] || !channel["name"]) {
                    continue;
                }
                const channelObj = {
                    id: channel["id"],
                    name: channel["name"],
                    workspaceType: WorkspaceType.Slack,
                };
                channels[channel["name"].toString()] = channelObj;
                // Add to local cache
                const normalizedName = channel["name"].toString().toLowerCase();
                localChannelCache[normalizedName] = {
                    id: channel["id"],
                    name: channel["name"],
                    workspaceType: WorkspaceType.Slack,
                    lastUpdated: OneUptimeDate.toString(OneUptimeDate.getCurrentDate()),
                };
            }
            cursor = (_d = response.jsonData["response_metadata"]) === null || _d === void 0 ? void 0 : _d["next_cursor"];
            pageCount++;
        } while (cursor && pageCount < maxPages);
        // Update cache in bulk
        try {
            await this.updateChannelsInCache({
                projectId: data.projectId,
                channelCache: localChannelCache,
            });
        }
        catch (error) {
            logger.error("Error bulk updating channel cache:", getAllChLogAttributes);
            logger.error(error, getAllChLogAttributes);
            // Don't fail the request if caching fails
        }
        logger.debug("All workspace channels obtained:", getAllChLogAttributes);
        return channels;
    }
    static async updateChannelsInCache(data) {
        var _a, _b;
        const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
            projectId: data.projectId,
            workspaceType: WorkspaceType.Slack,
        });
        if (!projectAuth) {
            logger.debug("No project auth found, cannot update cache", {
                projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
            });
            return;
        }
        const miscData = projectAuth.miscData || {};
        const channelCache = miscData.channelCache || {};
        // Update the cache
        Object.assign(channelCache, data.channelCache);
        // Update miscData
        miscData.channelCache = channelCache;
        // Save back to database
        await WorkspaceProjectAuthTokenService.refreshAuthToken({
            projectId: data.projectId,
            workspaceType: WorkspaceType.Slack,
            authToken: projectAuth.authToken,
            workspaceProjectId: projectAuth.workspaceProjectId,
            miscData: miscData,
        });
        logger.debug("Channel cache updated successfully", {
            projectId: (_b = data.projectId) === null || _b === void 0 ? void 0 : _b.toString(),
        });
    }
    static async getChannelFromCache(data) {
        var _a;
        const cacheGetLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Getting channel from cache with data:", cacheGetLogAttributes);
        logger.debug(data, cacheGetLogAttributes);
        const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
            projectId: data.projectId,
            workspaceType: WorkspaceType.Slack,
        });
        if (!projectAuth || !projectAuth.miscData) {
            logger.debug("No project auth found or no misc data", cacheGetLogAttributes);
            return null;
        }
        const miscData = projectAuth.miscData;
        const channelCache = miscData.channelCache;
        if (!channelCache || !channelCache[data.channelName]) {
            logger.debug("Channel not found in cache", cacheGetLogAttributes);
            return null;
        }
        const cachedChannelData = channelCache[data.channelName];
        const channel = {
            id: cachedChannelData.id,
            name: cachedChannelData.name,
            workspaceType: WorkspaceType.Slack,
        };
        logger.debug("Channel found in cache:", cacheGetLogAttributes);
        logger.debug(channel, cacheGetLogAttributes);
        return channel;
    }
    static async updateChannelCache(data) {
        var _a;
        const cacheUpdateLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Updating channel cache with data:", cacheUpdateLogAttributes);
        logger.debug(data, cacheUpdateLogAttributes);
        const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
            projectId: data.projectId,
            workspaceType: WorkspaceType.Slack,
        });
        if (!projectAuth) {
            logger.debug("No project auth found, cannot update cache", cacheUpdateLogAttributes);
            return;
        }
        const miscData = projectAuth.miscData || {};
        const channelCache = miscData.channelCache || {};
        // Update the cache
        channelCache[data.channelName] = {
            id: data.channel.id,
            name: data.channel.name,
            lastUpdated: OneUptimeDate.toString(OneUptimeDate.getCurrentDate()),
        };
        // Update miscData
        miscData.channelCache = channelCache;
        // Save back to database
        await WorkspaceProjectAuthTokenService.refreshAuthToken({
            projectId: data.projectId,
            workspaceType: WorkspaceType.Slack,
            authToken: projectAuth.authToken,
            workspaceProjectId: projectAuth.workspaceProjectId,
            miscData: miscData,
        });
        logger.debug("Channel cache updated successfully", cacheUpdateLogAttributes);
    }
    static async getWorkspaceChannelByName(data) {
        var _a, _b, _c, _d;
        const getByNameLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Getting workspace channel by name with data:", getByNameLogAttributes);
        logger.debug(data, getByNameLogAttributes);
        // Normalize channel name
        let normalizedChannelName = data.channelName;
        if (normalizedChannelName && normalizedChannelName.startsWith("#")) {
            normalizedChannelName = normalizedChannelName.substring(1);
        }
        normalizedChannelName = normalizedChannelName.toLowerCase();
        // Try to get from cache first
        try {
            const cachedChannel = await this.getChannelFromCache({
                projectId: data.projectId,
                channelName: normalizedChannelName,
            });
            if (cachedChannel) {
                logger.debug("Channel found in cache:", getByNameLogAttributes);
                logger.debug(cachedChannel, getByNameLogAttributes);
                return cachedChannel;
            }
        }
        catch (error) {
            logger.error("Error getting channel from cache, falling back to API:", getByNameLogAttributes);
            logger.error(error, getByNameLogAttributes);
        }
        let cursor = undefined;
        const maxPages = 500;
        let pageCount = 0;
        const localChannelCache = {};
        do {
            const requestBody = {
                limit: 999, // Use smaller limit for faster searches
                types: "public_channel,private_channel",
                exclude_archived: true,
            };
            if (cursor) {
                requestBody["cursor"] = cursor;
            }
            const response = await API.post({
                url: URL.fromString("https://slack.com/api/conversations.list"),
                data: requestBody,
                headers: {
                    Authorization: `Bearer ${data.authToken}`,
                    ["Content-Type"]: "application/x-www-form-urlencoded",
                },
                options: {
                    retries: 3,
                    exponentialBackoff: true,
                },
            });
            if (response instanceof HTTPErrorResponse) {
                logger.error("Error response from Slack API:", getByNameLogAttributes);
                logger.error(response, getByNameLogAttributes);
                throw response;
            }
            // check for ok response
            if (((_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["ok"]) !== true) {
                logger.error("Invalid response from Slack API:", getByNameLogAttributes);
                logger.error(response.jsonData, getByNameLogAttributes);
                const messageFromSlack = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["error"];
                throw new BadRequestException("Error from Slack " + messageFromSlack);
            }
            logger.debug("Searching for " + normalizedChannelName, getByNameLogAttributes);
            logger.debug("Searching channels in current page...", getByNameLogAttributes);
            logger.debug(JSON.stringify(response.jsonData["channels"], null, 2), getByNameLogAttributes);
            for (const channel of response.jsonData["channels"]) {
                if (!channel["id"] || !channel["name"]) {
                    continue;
                }
                const channelObj = {
                    id: channel["id"],
                    name: channel["name"],
                    workspaceType: WorkspaceType.Slack,
                };
                // Add to local cache
                const normalizedName = channel["name"].toString().toLowerCase();
                localChannelCache[normalizedName] = {
                    id: channel["id"],
                    name: channel["name"],
                    workspaceType: WorkspaceType.Slack,
                    lastUpdated: OneUptimeDate.toString(OneUptimeDate.getCurrentDate()),
                };
                const channelName = channel["name"].toLowerCase();
                if (channelName === normalizedChannelName) {
                    logger.debug("Channel found:", getByNameLogAttributes);
                    logger.debug(channel, getByNameLogAttributes);
                    // Update cache before returning
                    try {
                        await this.updateChannelsInCache({
                            projectId: data.projectId,
                            channelCache: localChannelCache,
                        });
                    }
                    catch (error) {
                        logger.error("Error bulk updating channel cache:", getByNameLogAttributes);
                        logger.error(error, getByNameLogAttributes);
                        // Don't fail the request if caching fails
                    }
                    return channelObj;
                }
            }
            cursor = (_d = response.jsonData["response_metadata"]) === null || _d === void 0 ? void 0 : _d["next_cursor"];
            pageCount++;
        } while (cursor && pageCount < maxPages);
        // Update cache even if channel not found
        try {
            await this.updateChannelsInCache({
                projectId: data.projectId,
                channelCache: localChannelCache,
            });
        }
        catch (error) {
            logger.error("Error bulk updating channel cache:", getByNameLogAttributes);
            logger.error(error, getByNameLogAttributes);
            // Don't fail the request if caching fails
        }
        logger.debug("Channel not found:", getByNameLogAttributes);
        return null;
    }
    static getDividerBlock() {
        return {
            type: "divider",
        };
    }
    static getValuesFromView(data) {
        var _a, _b;
        logger.debug("Getting values from view with data:", {});
        logger.debug(JSON.stringify(data, null, 2), {});
        const slackView = data.view;
        const values = {};
        if (!slackView["state"] || !slackView["state"]["values"]) {
            return {};
        }
        for (const valueId in slackView["state"]["values"]) {
            for (const blockId in slackView["state"]["values"][valueId]) {
                const valueObject = slackView["state"]["values"][valueId];
                const value = valueObject[blockId];
                values[blockId] = value["value"];
                if ((_a = value["selected_option"]) === null || _a === void 0 ? void 0 : _a["value"]) {
                    values[blockId] = (_b = value["selected_option"]) === null || _b === void 0 ? void 0 : _b["value"];
                }
                if (Array.isArray(value["selected_options"])) {
                    values[blockId] = value["selected_options"].map((option) => {
                        return option["value"];
                    });
                }
                // if date picker
                if (value["selected_date_time"]) {
                    values[blockId] = OneUptimeDate.fromUnixTimestamp(value["selected_date_time"]);
                }
            }
        }
        logger.debug("Values obtained from view:", {});
        logger.debug(values, {});
        return values;
    }
    static async doesChannelExist(data) {
        // if channel name starts with #, remove it
        if (data.channelName && data.channelName.startsWith("#")) {
            data.channelName = data.channelName.substring(1);
        }
        // convert channel name to lowercase
        data.channelName = data.channelName.toLowerCase();
        // Check if channel exists using optimized method
        const channel = await this.getWorkspaceChannelByName({
            authToken: data.authToken,
            channelName: data.channelName,
            projectId: data.projectId,
        });
        return channel !== null;
    }
    static async sendMessage(data) {
        var _a;
        const sendMsgLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Sending message to Slack with data:", sendMsgLogAttributes);
        logger.debug(data, sendMsgLogAttributes);
        const blocks = this.getBlocksFromWorkspaceMessagePayload(data.workspaceMessagePayload);
        logger.debug("Blocks generated from workspace message payload:", sendMsgLogAttributes);
        logger.debug(blocks, sendMsgLogAttributes);
        const workspaceChannelsToPostTo = [];
        // Resolve channel names efficiently
        for (let channelName of data.workspaceMessagePayload.channelNames) {
            if (channelName && channelName.startsWith("#")) {
                // trim # from channel name
                channelName = channelName.substring(1);
            }
            const channel = await this.getWorkspaceChannelByName({
                authToken: data.authToken,
                channelName: channelName,
                projectId: data.projectId,
            });
            if (channel) {
                workspaceChannelsToPostTo.push(channel);
            }
            else {
                logger.debug(`Channel ${channelName} does not exist.`, sendMsgLogAttributes);
            }
        }
        // add channel ids.
        for (const channelId of data.workspaceMessagePayload.channelIds) {
            try {
                // Get the channel info including name from channel ID
                const channel = await this.getWorkspaceChannelFromChannelId({
                    authToken: data.authToken,
                    channelId: channelId,
                });
                workspaceChannelsToPostTo.push(channel);
            }
            catch (err) {
                logger.error(`Error getting channel info for channel ID ${channelId}:`, sendMsgLogAttributes);
                logger.error(err, sendMsgLogAttributes);
                // Fallback: create channel object with empty name if API call fails
                const channel = {
                    id: channelId,
                    name: channelId,
                    workspaceType: WorkspaceType.Slack,
                };
                workspaceChannelsToPostTo.push(channel);
            }
        }
        logger.debug("Channel IDs to post to:", sendMsgLogAttributes);
        logger.debug(workspaceChannelsToPostTo, sendMsgLogAttributes);
        const workspaspaceMessageResponse = {
            threads: [],
            workspaceType: WorkspaceType.Slack,
            errors: [],
        };
        for (const channel of workspaceChannelsToPostTo) {
            try {
                if (data.userId) {
                    // check if the user is in the channel.
                    const isUserInChannel = await this.isUserInChannel({
                        authToken: data.authToken,
                        channelId: channel.id,
                        userId: data.userId,
                    });
                    if (!isUserInChannel) {
                        // add user to the channel
                        await this.joinChannel({
                            authToken: data.authToken,
                            channelId: channel.id,
                        });
                    }
                }
                // Slack has a limit of 50 blocks per message. Split into batches if needed.
                const maxBlocksPerMessage = 50;
                let lastThread;
                if (blocks.length <= maxBlocksPerMessage) {
                    lastThread = await this.sendPayloadBlocksToChannel({
                        authToken: data.authToken,
                        workspaceChannel: channel,
                        blocks: blocks,
                    });
                }
                else {
                    for (let i = 0; i < blocks.length; i += maxBlocksPerMessage) {
                        const chunk = blocks.slice(i, i + maxBlocksPerMessage);
                        lastThread = await this.sendPayloadBlocksToChannel({
                            authToken: data.authToken,
                            workspaceChannel: channel,
                            blocks: chunk,
                        });
                    }
                }
                if (lastThread) {
                    workspaspaceMessageResponse.threads.push(lastThread);
                }
                logger.debug(`Message sent to channel ID ${channel.id} successfully.`, sendMsgLogAttributes);
            }
            catch (e) {
                logger.error(`Error sending message to channel ID ${channel.id}:`, sendMsgLogAttributes);
                logger.error(e, sendMsgLogAttributes);
                workspaspaceMessageResponse.errors.push({
                    channel: channel,
                    error: e instanceof Error ? e.message : String(e),
                });
            }
        }
        logger.debug("Message sent successfully.", sendMsgLogAttributes);
        logger.debug(workspaspaceMessageResponse, sendMsgLogAttributes);
        return workspaspaceMessageResponse;
    }
    static async sendPayloadBlocksToChannel(data) {
        var _a, _b, _c;
        const payloadBlocksLogAttributes = {
            channelId: (_a = data.workspaceChannel) === null || _a === void 0 ? void 0 : _a.id,
        };
        logger.debug("Sending payload blocks to channel with data:", payloadBlocksLogAttributes);
        logger.debug(JSON.stringify(data, null, 2), payloadBlocksLogAttributes);
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/chat.postMessage"),
            data: {
                channel: data.workspaceChannel.id,
                blocks: data.blocks,
                unfurl_links: false,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/json",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for sending message:", payloadBlocksLogAttributes);
        logger.debug(response, payloadBlocksLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", payloadBlocksLogAttributes);
            logger.error(response, payloadBlocksLogAttributes);
            throw response;
        }
        if (((_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", payloadBlocksLogAttributes);
            logger.error(response.jsonData, payloadBlocksLogAttributes);
            const messageFromSlack = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        logger.debug("Payload blocks sent to channel successfully.", payloadBlocksLogAttributes);
        return {
            channel: data.workspaceChannel,
            threadId: response.jsonData["ts"],
        };
    }
    static async sendMessageToThread(data) {
        var _a, _b;
        const threadLogAttributes = { channelId: data.channelId };
        logger.debug("Sending message to thread with data:", threadLogAttributes);
        logger.debug(data, threadLogAttributes);
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/chat.postMessage"),
            data: {
                channel: data.channelId,
                thread_ts: data.threadTs,
                text: data.text,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/json",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for sending thread message:", threadLogAttributes);
        logger.debug(response, threadLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", threadLogAttributes);
            logger.error(response, threadLogAttributes);
            throw response;
        }
        if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", threadLogAttributes);
            logger.error(response.jsonData, threadLogAttributes);
            const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        logger.debug("Thread message sent successfully.", threadLogAttributes);
    }
    static async getMessageByTimestamp(data) {
        var _a, _b, _c, _d;
        const getMsgLogAttributes = { channelId: data.channelId };
        logger.debug("Getting message by timestamp with data:", getMsgLogAttributes);
        logger.debug(data, getMsgLogAttributes);
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/conversations.history"),
            data: {
                channel: data.channelId,
                latest: data.messageTs,
                oldest: data.messageTs,
                inclusive: true,
                limit: 1,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/x-www-form-urlencoded",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for getting message:", getMsgLogAttributes);
        logger.debug(response, getMsgLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", getMsgLogAttributes);
            logger.error(response, getMsgLogAttributes);
            throw response;
        }
        if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", getMsgLogAttributes);
            logger.error(response.jsonData, getMsgLogAttributes);
            const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        const messages = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["messages"];
        if (!messages || messages.length === 0) {
            logger.debug("No messages found for timestamp.", getMsgLogAttributes);
            return null;
        }
        const messageText = (_d = messages[0]) === null || _d === void 0 ? void 0 : _d["text"];
        logger.debug("Message text retrieved:", getMsgLogAttributes);
        logger.debug(messageText, getMsgLogAttributes);
        return messageText || null;
    }
    static getButtonsBlock(data) {
        logger.debug("Getting buttons block with data:", {});
        logger.debug(data, {});
        const buttonsBlock = {
            type: "actions",
            elements: data.payloadButtonsBlock.buttons.map((button) => {
                return this.getButtonBlock({ payloadButtonBlock: button });
            }),
        };
        logger.debug("Buttons block generated:", {});
        logger.debug(buttonsBlock, {});
        return buttonsBlock;
    }
    static async createChannel(data) {
        var _a, _b, _c, _d, _e, _f, _g;
        /*
         * Sanitize channel name: Slack only allows lowercase letters, numbers,
         * hyphens, and underscores. Remove all other characters (including #).
         */
        data.channelName = data.channelName
            .toLowerCase()
            .replace(/[^a-z0-9\-_]/g, "");
        const createChannelLogAttributes = {
            projectId: (_a = data.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        };
        logger.debug("Creating channel with data:", createChannelLogAttributes);
        logger.debug(data, createChannelLogAttributes);
        const createChannelPayload = {
            name: data.channelName,
        };
        if (data.isPrivate) {
            createChannelPayload["is_private"] = true;
        }
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/conversations.create"),
            data: createChannelPayload,
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/x-www-form-urlencoded",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for creating channel:", createChannelLogAttributes);
        logger.debug(response, createChannelLogAttributes);
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", createChannelLogAttributes);
            logger.error(response, createChannelLogAttributes);
            throw response;
        }
        // check for ok response
        if (((_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", createChannelLogAttributes);
            logger.error(response.jsonData, createChannelLogAttributes);
            const messageFromSlack = (_c = response.jsonData) === null || _c === void 0 ? void 0 : _c["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        if (!((_e = (_d = response.jsonData) === null || _d === void 0 ? void 0 : _d["channel"]) === null || _e === void 0 ? void 0 : _e["id"]) ||
            !((_g = (_f = response.jsonData) === null || _f === void 0 ? void 0 : _f["channel"]) === null || _g === void 0 ? void 0 : _g["name"])) {
            logger.error("Invalid response from Slack API:", createChannelLogAttributes);
            logger.error(response.jsonData, createChannelLogAttributes);
            throw new Error("Invalid response");
        }
        const channel = {
            id: response.jsonData["channel"]["id"],
            name: response.jsonData["channel"]["name"],
            workspaceType: WorkspaceType.Slack,
        };
        logger.debug("Channel created successfully:", createChannelLogAttributes);
        logger.debug(channel, createChannelLogAttributes);
        // Cache the created channel
        try {
            const localCache = {};
            localCache[data.channelName] = {
                id: channel.id,
                name: channel.name,
                workspaceType: WorkspaceType.Slack,
                lastUpdated: OneUptimeDate.toString(OneUptimeDate.getCurrentDate()),
            };
            await this.updateChannelsInCache({
                projectId: data.projectId,
                channelCache: localCache,
            });
        }
        catch (error) {
            logger.error("Error caching created channel:", createChannelLogAttributes);
            logger.error(error, createChannelLogAttributes);
            // Don't fail the creation if caching fails
        }
        return channel;
    }
    static getHeaderBlock(data) {
        logger.debug("Getting header block with data:", {});
        logger.debug(data, {});
        const headerBlock = {
            type: "header",
            text: {
                type: "plain_text",
                text: data.payloadHeaderBlock.text,
            },
        };
        logger.debug("Header block generated:", {});
        logger.debug(headerBlock, {});
        return headerBlock;
    }
    static getCheckboxBlock(data) {
        logger.debug("Getting checkbox block with data:", {});
        logger.debug(data, {});
        const checkboxBlock = {
            type: "input",
            element: {
                type: "checkboxes",
                action_id: data.payloadCheckboxBlock.blockId,
                options: [
                    {
                        text: {
                            type: "plain_text",
                            text: data.payloadCheckboxBlock.label,
                        },
                        value: "value",
                    },
                ],
                initial_options: data.payloadCheckboxBlock.initialValue
                    ? [
                        {
                            text: {
                                type: "plain_text",
                                text: data.payloadCheckboxBlock.label,
                            },
                            value: "value",
                        },
                    ]
                    : undefined,
            },
            label: {
                type: "plain_text",
                text: data.payloadCheckboxBlock.label,
            },
        };
        // if description then add hint.
        if (data.payloadCheckboxBlock.description) {
            checkboxBlock["hint"] = {
                type: "plain_text",
                text: data.payloadCheckboxBlock.description,
            };
        }
        logger.debug("Checkbox block generated:", {});
        logger.debug(checkboxBlock, {});
        return checkboxBlock;
    }
    static getDateTimePickerBlock(data) {
        logger.debug("Getting date time picker block with data:", {});
        logger.debug(data, {});
        const dateTimePickerBlock = {
            type: "input",
            element: {
                type: "datetimepicker",
                action_id: data.payloadDateTimePickerBlock.blockId,
                initial_date: data.payloadDateTimePickerBlock.initialValue,
            },
            label: {
                type: "plain_text",
                text: data.payloadDateTimePickerBlock.label,
            },
        };
        logger.debug("Date time picker block generated:", {});
        logger.debug(dateTimePickerBlock, {});
        return dateTimePickerBlock;
    }
    static getTextAreaBlock(data) {
        logger.debug("Getting text area block with data:", {});
        logger.debug(data, {});
        const optional = data.payloadTextAreaBlock.optional || false;
        const textAreaBlock = {
            type: "input",
            optional: optional,
            element: {
                type: "plain_text_input",
                multiline: true,
                action_id: data.payloadTextAreaBlock.blockId,
                placeholder: {
                    type: "plain_text",
                    text: data.payloadTextAreaBlock.placeholder,
                },
                initial_value: data.payloadTextAreaBlock.initialValue,
            },
            label: {
                type: "plain_text",
                text: data.payloadTextAreaBlock.label,
            },
        };
        // if description then add hint.
        if (data.payloadTextAreaBlock.description) {
            textAreaBlock["hint"] = {
                type: "plain_text",
                text: data.payloadTextAreaBlock.description,
            };
        }
        logger.debug("Text area block generated:", {});
        logger.debug(textAreaBlock, {});
        return textAreaBlock;
    }
    static getTextBoxBlock(data) {
        logger.debug("Getting text box block with data:", {});
        logger.debug(data, {});
        const optional = data.payloadTextBoxBlock.optional || false;
        const textBoxBlock = {
            type: "input",
            optional: optional,
            element: {
                type: "plain_text_input",
                action_id: data.payloadTextBoxBlock.blockId,
                placeholder: {
                    type: "plain_text",
                    text: data.payloadTextBoxBlock.placeholder,
                },
                initial_value: data.payloadTextBoxBlock.initialValue,
            },
            label: {
                type: "plain_text",
                text: data.payloadTextBoxBlock.label,
            },
        };
        // if description then add hint.
        if (data.payloadTextBoxBlock.description) {
            textBoxBlock["hint"] = {
                type: "plain_text",
                text: data.payloadTextBoxBlock.description,
            };
        }
        logger.debug("Text box block generated:", {});
        logger.debug(textBoxBlock, {});
        return textBoxBlock;
    }
    static getImageBlock(data) {
        logger.debug("Getting image block with data:", {});
        logger.debug(data, {});
        const imageBlock = {
            type: "image",
            image_url: data.payloadImageBlock.imageUrl.toString(),
            alt_text: data.payloadImageBlock.altText,
        };
        logger.debug("Image block generated:", {});
        logger.debug(imageBlock, {});
        return imageBlock;
    }
    static getDropdownBlock(data) {
        logger.debug("Getting dropdown block with data:", {});
        logger.debug(data, {});
        const optional = data.payloadDropdownBlock.optional || false;
        const isMiltiSelect = data.payloadDropdownBlock.multiSelect || false;
        const dropdownBlock = {
            type: "input",
            optional: optional,
            element: {
                type: isMiltiSelect ? "multi_static_select" : "static_select",
                action_id: data.payloadDropdownBlock.blockId,
                placeholder: {
                    type: "plain_text",
                    text: data.payloadDropdownBlock.placeholder,
                },
                options: data.payloadDropdownBlock.options.map((option) => {
                    return {
                        text: {
                            type: "plain_text",
                            text: option.label,
                        },
                        value: option.value,
                    };
                }),
                initial_option: data.payloadDropdownBlock.initialValue
                    ? {
                        text: {
                            type: "plain_text",
                            text: data.payloadDropdownBlock.initialValue,
                        },
                        value: data.payloadDropdownBlock.initialValue,
                    }
                    : undefined,
            },
            label: {
                type: "plain_text",
                text: data.payloadDropdownBlock.label,
            },
        };
        // if description then add hint.
        if (data.payloadDropdownBlock.description) {
            dropdownBlock["hint"] = {
                type: "plain_text",
                text: data.payloadDropdownBlock.description,
            };
        }
        logger.debug("Dropdown block generated:", {});
        logger.debug(dropdownBlock, {});
        return dropdownBlock;
    }
    static getModalBlock(data) {
        logger.debug("Getting modal block with data:", {});
        logger.debug(data, {});
        const modalBlock = {
            type: "modal",
            title: {
                type: "plain_text",
                text: data.payloadModalBlock.title,
            },
            callback_id: data.payloadModalBlock.actionId,
            private_metadata: data.payloadModalBlock.actionValue,
            submit: {
                type: "plain_text",
                text: data.payloadModalBlock.submitButtonTitle,
            },
            close: {
                type: "plain_text",
                text: data.payloadModalBlock.cancelButtonTitle,
            },
            blocks: this.getBlocksFromWorkspaceMessagePayload({
                messageBlocks: data.payloadModalBlock.blocks,
            }),
        };
        logger.debug("Modal block generated:", {});
        logger.debug(modalBlock, {});
        return modalBlock;
    }
    static getMarkdownBlock(data) {
        logger.debug("Getting markdown block with data:", {});
        logger.debug(data, {});
        const markdownBlock = {
            type: "section",
            text: {
                type: "mrkdwn",
                text: data.payloadMarkdownBlock.text
                    ? SlackifyMarkdown(data.payloadMarkdownBlock.text)
                    : "",
            },
        };
        logger.debug("Markdown block generated:", {});
        logger.debug(markdownBlock, {});
        return markdownBlock;
    }
    static async isUserInDirectMessageChannel(data) {
        var _a, _b, _c;
        // check of the user id is in the direct message channel id
        const response = await API.post({
            url: URL.fromString("https://slack.com/api/conversations.info"),
            data: {
                channel: data.directMessageChannelId,
            },
            headers: {
                Authorization: `Bearer ${data.authToken}`,
                ["Content-Type"]: "application/x-www-form-urlencoded",
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        if (response instanceof HTTPErrorResponse) {
            logger.error("Error response from Slack API:", {
                channelId: data.directMessageChannelId,
            });
            logger.error(response, {
                channelId: data.directMessageChannelId,
            });
            throw response;
        }
        // check for ok response
        if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
            logger.error("Invalid response from Slack API:", {
                channelId: data.directMessageChannelId,
            });
            logger.error(response.jsonData, {
                channelId: data.directMessageChannelId,
            });
            const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
            throw new BadRequestException("Error from Slack " + messageFromSlack);
        }
        // check if the user is in the channel
        const user = response.jsonData["channel"]["user"];
        if (((_c = user === null || user === void 0 ? void 0 : user["user_id"]) === null || _c === void 0 ? void 0 : _c.toString()) === data.userId.toString()) {
            return true;
        }
        return false;
    }
    static async isUserInChannel(data) {
        var _a, _b, _c;
        const members = [];
        const isInChannelLogAttributes = {
            channelId: data.channelId,
        };
        logger.debug("Checking if user is in channel with data:", isInChannelLogAttributes);
        logger.debug(data, isInChannelLogAttributes);
        let cursor = undefined;
        do {
            // check if the user is in the channel, return true if they are, false if they are not
            const requestBody = {
                channel: data.channelId,
                limit: 999,
            };
            if (cursor) {
                requestBody["cursor"] = cursor;
            }
            const response = await API.post({
                url: URL.fromString("https://slack.com/api/conversations.members"),
                data: requestBody,
                headers: {
                    Authorization: `Bearer ${data.authToken}`,
                    ["Content-Type"]: "application/x-www-form-urlencoded",
                },
                options: {
                    retries: 3,
                    exponentialBackoff: true,
                },
            });
            logger.debug("Response from Slack API for getting channel members:", isInChannelLogAttributes);
            logger.debug(response, isInChannelLogAttributes);
            if (response instanceof HTTPErrorResponse) {
                logger.error("Error response from Slack API:", isInChannelLogAttributes);
                logger.error(response, isInChannelLogAttributes);
                throw response;
            }
            // check for ok response
            if (((_a = response.jsonData) === null || _a === void 0 ? void 0 : _a["ok"]) !== true) {
                logger.error("Invalid response from Slack API:", isInChannelLogAttributes);
                logger.error(response.jsonData, isInChannelLogAttributes);
                const messageFromSlack = (_b = response.jsonData) === null || _b === void 0 ? void 0 : _b["error"];
                throw new BadRequestException("Error from Slack " + messageFromSlack);
            }
            // check if the user is in the channel
            const membersOnThisPage = response.jsonData["members"];
            members.push(...membersOnThisPage);
            cursor = (_c = response.jsonData["response_metadata"]) === null || _c === void 0 ? void 0 : _c["next_cursor"];
        } while (cursor);
        if (members.includes(data.userId)) {
            return true;
        }
        return false;
    }
    static getButtonBlock(data) {
        logger.debug("Getting button block with data:", {});
        logger.debug(data, {});
        const buttonBlock = {
            type: "button",
            text: {
                type: "plain_text",
                text: data.payloadButtonBlock.title,
                emoji: true,
            },
            value: data.payloadButtonBlock.value,
            action_id: data.payloadButtonBlock.actionId,
            url: data.payloadButtonBlock.url
                ? data.payloadButtonBlock.url.toString()
                : undefined,
        };
        logger.debug("Button block generated:", {});
        logger.debug(buttonBlock, {});
        return buttonBlock;
    }
    static async sendMessageToChannelViaIncomingWebhook(data) {
        logger.debug("Sending message to channel via incoming webhook with data:", {});
        logger.debug(data, {});
        const apiResult = await API.post({
            url: data.url,
            data: {
                blocks: [
                    {
                        type: "section",
                        text: {
                            type: "mrkdwn",
                            text: `${data.text}`,
                        },
                    },
                ],
            },
            options: {
                retries: 3,
                exponentialBackoff: true,
            },
        });
        logger.debug("Response from Slack API for sending message via webhook:", {});
        logger.debug(apiResult, {});
        return apiResult;
    }
    /**
     * Converts markdown tables to a Slack-friendly format.
     * Since Slack's mrkdwn doesn't support tables, we convert them to
     * a row-by-row format with bold headers.
     */
    static convertMarkdownTablesToSlackFormat(markdown) {
        // Regular expression to match markdown tables
        const tableRegex = /(?:^|\n)((?:\|[^\n]+\|\n)+(?:\|[-:\s|]+\|\n)(?:\|[^\n]+\|\n?)+)/g;
        return markdown.replace(tableRegex, (_match, table) => {
            const lines = table.trim().split("\n");
            if (lines.length < 2) {
                return table;
            }
            // Parse header row
            const headerLine = lines[0] || "";
            const headers = headerLine
                .split("|")
                .map((cell) => {
                return cell.trim();
            })
                .filter((cell) => {
                return cell.length > 0;
            });
            /*
             * Skip separator line (line with dashes)
             * Find data rows (skip header and separator)
             */
            const dataRows = lines.slice(2);
            const formattedRows = [];
            for (let rowIndex = 0; rowIndex < dataRows.length; rowIndex++) {
                const row = dataRows[rowIndex] || "";
                const cells = row
                    .split("|")
                    .map((cell) => {
                    return cell.trim();
                })
                    .filter((cell) => {
                    return cell.length > 0;
                });
                if (cells.length === 0) {
                    continue;
                }
                const rowParts = [];
                for (let cellIndex = 0; cellIndex < cells.length; cellIndex++) {
                    const header = headers[cellIndex] || `Column ${cellIndex + 1}`;
                    const value = cells[cellIndex] || "";
                    rowParts.push(`*${header}:* ${value}`);
                }
                if (dataRows.length > 1) {
                    formattedRows.push(`_Row ${rowIndex + 1}_\n${rowParts.join("\n")}`);
                }
                else {
                    formattedRows.push(rowParts.join("\n"));
                }
            }
            return "\n" + formattedRows.join("\n\n") + "\n";
        });
    }
    static convertMarkdownToSlackRichText(markdown) {
        // First convert tables to Slack-friendly format
        const markdownWithConvertedTables = this.convertMarkdownTablesToSlackFormat(markdown);
        return SlackifyMarkdown(markdownWithConvertedTables);
    }
    static async getChannelMessages(params) {
        var _a;
        const messages = [];
        let cursor = undefined;
        const maxMessages = params.limit || 1000;
        const maxPages = 10;
        let pageCount = 0;
        do {
            const requestData = {
                channel: params.channelId,
                limit: Math.min(200, maxMessages - messages.length),
            };
            if (cursor) {
                requestData["cursor"] = cursor;
            }
            if (params.oldestTimestamp) {
                requestData["oldest"] = (params.oldestTimestamp.getTime() / 1000).toString();
            }
            const response = await API.post({
                url: URL.fromString("https://slack.com/api/conversations.history"),
                data: requestData,
                headers: {
                    Authorization: `Bearer ${params.authToken}`,
                    "Content-Type": "application/x-www-form-urlencoded",
                },
                options: {
                    retries: 3,
                    exponentialBackoff: true,
                },
            });
            if (response instanceof HTTPErrorResponse) {
                logger.error("Error response from Slack API for channel history:", {
                    channelId: params.channelId,
                });
                logger.error(response, {
                    channelId: params.channelId,
                });
                break;
            }
            const jsonData = response.jsonData;
            if (jsonData["ok"] !== true) {
                logger.error("Invalid response from Slack API for channel history:", {
                    channelId: params.channelId,
                });
                logger.error(jsonData, {
                    channelId: params.channelId,
                });
                break;
            }
            const slackMessages = jsonData["messages"] || [];
            for (const msg of slackMessages) {
                // Skip bot messages if they're from the OneUptime bot (app messages)
                const isBot = Boolean(msg["bot_id"]) || msg["subtype"] === "bot_message";
                // Extract text, handling attachments and blocks
                let text = msg["text"] || "";
                // If there are attachments, append their text
                const attachments = msg["attachments"];
                if (attachments && Array.isArray(attachments)) {
                    for (const attachment of attachments) {
                        if (attachment && attachment["text"]) {
                            text += "\n" + attachment["text"];
                        }
                        if (attachment && attachment["fallback"]) {
                            text += "\n" + attachment["fallback"];
                        }
                    }
                }
                // Skip empty messages
                if (!text.trim()) {
                    continue;
                }
                const timestamp = msg["ts"]
                    ? new Date(parseFloat(msg["ts"]) * 1000)
                    : new Date();
                messages.push({
                    messageId: msg["ts"],
                    text: text,
                    userId: msg["user"],
                    username: msg["username"],
                    timestamp: timestamp,
                    isBot: isBot,
                });
            }
            cursor = (_a = jsonData["response_metadata"]) === null || _a === void 0 ? void 0 : _a["next_cursor"];
            pageCount++;
        } while (cursor && messages.length < maxMessages && pageCount < maxPages);
        logger.debug(`Retrieved ${messages.length} messages from Slack channel ${params.channelId}`, { channelId: params.channelId });
        // Reverse to get chronological order (Slack returns newest first)
        messages.reverse();
        return messages;
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getUsernameFromUserId", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "showModalToUser", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "sendEphemeralMessageToChannel", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "sendDirectMessageToUser", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "archiveChannels", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "joinChannel", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "inviteUserToChannelByChannelId", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "inviteUserToChannelByChannelName", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "createChannelsIfDoesNotExist", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getWorkspaceChannelFromChannelName", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getWorkspaceChannelFromChannelId", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getAllWorkspaceChannels", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getChannelFromCache", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "updateChannelCache", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getWorkspaceChannelByName", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Object)
], SlackUtil, "getDividerBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getValuesFromView", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "doesChannelExist", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "sendMessage", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "sendPayloadBlocksToChannel", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "sendMessageToThread", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getMessageByTimestamp", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getButtonsBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "createChannel", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getHeaderBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getCheckboxBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getDateTimePickerBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getTextAreaBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getTextBoxBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getImageBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getDropdownBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getModalBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getMarkdownBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "isUserInDirectMessageChannel", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "isUserInChannel", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Object)
], SlackUtil, "getButtonBlock", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "sendMessageToChannelViaIncomingWebhook", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], SlackUtil, "convertMarkdownToSlackRichText", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackUtil, "getChannelMessages", null);
//# sourceMappingURL=Slack.js.map