refactor: centralize slack threading helpers
This commit is contained in:
@@ -58,7 +58,13 @@ import type { RuntimeEnv } from "../runtime.js";
|
||||
import { resolveSlackAccount } from "./accounts.js";
|
||||
import { reactSlackMessage } from "./actions.js";
|
||||
import { sendMessageSlack } from "./send.js";
|
||||
import { resolveSlackThreadTargets } from "./threading.js";
|
||||
import { resolveSlackAppToken, resolveSlackBotToken } from "./token.js";
|
||||
import type {
|
||||
SlackAppMentionEvent,
|
||||
SlackFile,
|
||||
SlackMessageEvent,
|
||||
} from "./types.js";
|
||||
|
||||
export type MonitorSlackOpts = {
|
||||
botToken?: string;
|
||||
@@ -71,45 +77,6 @@ export type MonitorSlackOpts = {
|
||||
slashCommand?: SlackSlashCommandConfig;
|
||||
};
|
||||
|
||||
type SlackFile = {
|
||||
id?: string;
|
||||
name?: string;
|
||||
mimetype?: string;
|
||||
size?: number;
|
||||
url_private?: string;
|
||||
url_private_download?: string;
|
||||
};
|
||||
|
||||
type SlackMessageEvent = {
|
||||
type: "message";
|
||||
user?: string;
|
||||
bot_id?: string;
|
||||
subtype?: string;
|
||||
username?: string;
|
||||
text?: string;
|
||||
ts?: string;
|
||||
thread_ts?: string;
|
||||
event_ts?: string;
|
||||
parent_user_id?: string;
|
||||
channel: string;
|
||||
channel_type?: "im" | "mpim" | "channel" | "group";
|
||||
files?: SlackFile[];
|
||||
};
|
||||
|
||||
type SlackAppMentionEvent = {
|
||||
type: "app_mention";
|
||||
user?: string;
|
||||
bot_id?: string;
|
||||
username?: string;
|
||||
text?: string;
|
||||
ts?: string;
|
||||
thread_ts?: string;
|
||||
event_ts?: string;
|
||||
parent_user_id?: string;
|
||||
channel: string;
|
||||
channel_type?: "im" | "mpim" | "channel" | "group";
|
||||
};
|
||||
|
||||
type SlackReactionEvent = {
|
||||
type: "reaction_added" | "reaction_removed";
|
||||
user?: string;
|
||||
@@ -1102,12 +1069,10 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
);
|
||||
}
|
||||
|
||||
const incomingThreadTs = message.thread_ts;
|
||||
const eventTs = message.event_ts;
|
||||
const messageTs = message.ts ?? eventTs;
|
||||
const replyThreadTs =
|
||||
incomingThreadTs ?? (replyToMode === "all" ? messageTs : undefined);
|
||||
const statusThreadTs = replyThreadTs ?? messageTs;
|
||||
const { replyThreadTs, statusThreadTs } = resolveSlackThreadTargets({
|
||||
message,
|
||||
replyToMode,
|
||||
});
|
||||
let didSetStatus = false;
|
||||
const onReplyStart = async () => {
|
||||
didSetStatus = true;
|
||||
|
||||
48
src/slack/threading.test.ts
Normal file
48
src/slack/threading.test.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { resolveSlackThreadTargets } from "./threading.js";
|
||||
|
||||
describe("resolveSlackThreadTargets", () => {
|
||||
it("threads replies when message is already threaded", () => {
|
||||
const { replyThreadTs, statusThreadTs } = resolveSlackThreadTargets({
|
||||
replyToMode: "off",
|
||||
message: {
|
||||
type: "message",
|
||||
channel: "C1",
|
||||
ts: "123",
|
||||
thread_ts: "456",
|
||||
},
|
||||
});
|
||||
|
||||
expect(replyThreadTs).toBe("456");
|
||||
expect(statusThreadTs).toBe("456");
|
||||
});
|
||||
|
||||
it("threads top-level replies when mode is all", () => {
|
||||
const { replyThreadTs, statusThreadTs } = resolveSlackThreadTargets({
|
||||
replyToMode: "all",
|
||||
message: {
|
||||
type: "message",
|
||||
channel: "C1",
|
||||
ts: "123",
|
||||
},
|
||||
});
|
||||
|
||||
expect(replyThreadTs).toBe("123");
|
||||
expect(statusThreadTs).toBe("123");
|
||||
});
|
||||
|
||||
it("keeps status threading even when reply threading is off", () => {
|
||||
const { replyThreadTs, statusThreadTs } = resolveSlackThreadTargets({
|
||||
replyToMode: "off",
|
||||
message: {
|
||||
type: "message",
|
||||
channel: "C1",
|
||||
ts: "123",
|
||||
},
|
||||
});
|
||||
|
||||
expect(replyThreadTs).toBeUndefined();
|
||||
expect(statusThreadTs).toBe("123");
|
||||
});
|
||||
});
|
||||
15
src/slack/threading.ts
Normal file
15
src/slack/threading.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { ReplyToMode } from "../config/types.js";
|
||||
import type { SlackAppMentionEvent, SlackMessageEvent } from "./types.js";
|
||||
|
||||
export function resolveSlackThreadTargets(params: {
|
||||
message: SlackMessageEvent | SlackAppMentionEvent;
|
||||
replyToMode: ReplyToMode;
|
||||
}) {
|
||||
const incomingThreadTs = params.message.thread_ts;
|
||||
const eventTs = params.message.event_ts;
|
||||
const messageTs = params.message.ts ?? eventTs;
|
||||
const replyThreadTs =
|
||||
incomingThreadTs ?? (params.replyToMode === "all" ? messageTs : undefined);
|
||||
const statusThreadTs = replyThreadTs ?? messageTs;
|
||||
return { replyThreadTs, statusThreadTs };
|
||||
}
|
||||
38
src/slack/types.ts
Normal file
38
src/slack/types.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export type SlackFile = {
|
||||
id?: string;
|
||||
name?: string;
|
||||
mimetype?: string;
|
||||
size?: number;
|
||||
url_private?: string;
|
||||
url_private_download?: string;
|
||||
};
|
||||
|
||||
export type SlackMessageEvent = {
|
||||
type: "message";
|
||||
user?: string;
|
||||
bot_id?: string;
|
||||
subtype?: string;
|
||||
username?: string;
|
||||
text?: string;
|
||||
ts?: string;
|
||||
thread_ts?: string;
|
||||
event_ts?: string;
|
||||
parent_user_id?: string;
|
||||
channel: string;
|
||||
channel_type?: "im" | "mpim" | "channel" | "group";
|
||||
files?: SlackFile[];
|
||||
};
|
||||
|
||||
export type SlackAppMentionEvent = {
|
||||
type: "app_mention";
|
||||
user?: string;
|
||||
bot_id?: string;
|
||||
username?: string;
|
||||
text?: string;
|
||||
ts?: string;
|
||||
thread_ts?: string;
|
||||
event_ts?: string;
|
||||
parent_user_id?: string;
|
||||
channel: string;
|
||||
channel_type?: "im" | "mpim" | "channel" | "group";
|
||||
};
|
||||
Reference in New Issue
Block a user