fix(mattermost): land #30891 route private channels as group (@BlueBirdBack)
Landed from contributor PR #30891 by @BlueBirdBack. Co-authored-by: BlueBirdBack <BlueBirdBack@users.noreply.github.com>
This commit is contained in:
@@ -112,6 +112,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Mattermost/Private channel policy routing: map Mattermost private channel type `P` to group chat type so `groupPolicy`/`groupAllowFrom` gates apply correctly instead of being treated as open public channels. Landed from contributor PR #30891 by @BlueBirdBack. Thanks @BlueBirdBack.
|
||||
- Models/Custom provider keys: trim custom provider map keys during normalization so image-capable models remain discoverable when provider keys are configured with leading/trailing whitespace. Landed from contributor PR #31202 by @stakeswky. Thanks @stakeswky.
|
||||
- Discord/Agent component interactions: accept Components v2 `cid` payloads alongside legacy `componentId`, and safely decode percent-encoded IDs without throwing on malformed `%` sequences. Landed from contributor PR #29013 by @Jacky1n7. Thanks @Jacky1n7.
|
||||
- Matrix/Directory room IDs: preserve original room-ID casing for direct `!roomId` group lookups (without `:server`) so allowlist checks do not fail on case-sensitive IDs. Landed from contributor PR #31201 by @williamos-dev. Thanks @williamos-dev.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { mapMattermostChannelTypeToChatType } from "./monitor.js";
|
||||
|
||||
describe("mapMattermostChannelTypeToChatType", () => {
|
||||
it("maps direct and group dm channel types", () => {
|
||||
expect(mapMattermostChannelTypeToChatType("D")).toBe("direct");
|
||||
expect(mapMattermostChannelTypeToChatType("g")).toBe("group");
|
||||
});
|
||||
|
||||
it("maps private channels to group", () => {
|
||||
expect(mapMattermostChannelTypeToChatType("P")).toBe("group");
|
||||
expect(mapMattermostChannelTypeToChatType(" p ")).toBe("group");
|
||||
});
|
||||
|
||||
it("keeps public channels and unknown values as channel", () => {
|
||||
expect(mapMattermostChannelTypeToChatType("O")).toBe("channel");
|
||||
expect(mapMattermostChannelTypeToChatType("x")).toBe("channel");
|
||||
expect(mapMattermostChannelTypeToChatType(undefined)).toBe("channel");
|
||||
});
|
||||
});
|
||||
@@ -110,10 +110,11 @@ function isSystemPost(post: MattermostPost): boolean {
|
||||
return Boolean(type);
|
||||
}
|
||||
|
||||
function channelKind(channelType?: string | null): ChatType {
|
||||
export function mapMattermostChannelTypeToChatType(channelType?: string | null): ChatType {
|
||||
if (!channelType) {
|
||||
return "channel";
|
||||
}
|
||||
// Mattermost channel types: D=direct, G=group DM, O=public channel, P=private channel.
|
||||
const normalized = channelType.trim().toUpperCase();
|
||||
if (normalized === "D") {
|
||||
return "direct";
|
||||
@@ -121,6 +122,12 @@ function channelKind(channelType?: string | null): ChatType {
|
||||
if (normalized === "G") {
|
||||
return "group";
|
||||
}
|
||||
if (normalized === "P") {
|
||||
// Private channels are invitation-restricted spaces; route as "group" so
|
||||
// groupPolicy / groupAllowFrom can gate access separately from open public
|
||||
// channels (type "O"), and the From prefix becomes mattermost:group:<id>.
|
||||
return "group";
|
||||
}
|
||||
return "channel";
|
||||
}
|
||||
|
||||
@@ -352,7 +359,7 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {}
|
||||
|
||||
const channelInfo = await resolveChannelInfo(channelId);
|
||||
const channelType = payload.data?.channel_type ?? channelInfo?.type ?? undefined;
|
||||
const kind = channelKind(channelType);
|
||||
const kind = mapMattermostChannelTypeToChatType(channelType);
|
||||
const chatType = channelChatType(kind);
|
||||
|
||||
const senderName =
|
||||
@@ -863,7 +870,7 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {}
|
||||
logVerboseMessage(`mattermost: drop reaction (cannot resolve channel type for ${channelId})`);
|
||||
return;
|
||||
}
|
||||
const kind = channelKind(channelInfo.type);
|
||||
const kind = mapMattermostChannelTypeToChatType(channelInfo.type);
|
||||
|
||||
// Enforce DM/group policy and allowlist checks (same as normal messages)
|
||||
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
||||
|
||||
Reference in New Issue
Block a user