mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 17:51:22 +00:00
refactor: dedupe msteams lowercase helpers
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import { fetchWithSsrFGuard, type SsrFPolicy } from "../../runtime-api.js";
|
||||
import { getMSTeamsRuntime } from "../runtime.js";
|
||||
import { ensureUserAgentHeader } from "../user-agent.js";
|
||||
@@ -46,7 +50,7 @@ export function buildMSTeamsGraphMessageUrls(params: {
|
||||
conversationMessageId?: string | null;
|
||||
channelData?: unknown;
|
||||
}): string[] {
|
||||
const conversationType = params.conversationType?.trim().toLowerCase() ?? "";
|
||||
const conversationType = normalizeLowercaseStringOrEmpty(params.conversationType ?? "");
|
||||
const messageIdCandidates = new Set<string>();
|
||||
const pushCandidate = (value: string | null | undefined) => {
|
||||
const trimmed = typeof value === "string" ? value.trim() : "";
|
||||
@@ -382,7 +386,7 @@ export async function downloadMSTeamsGraphMedia(params: {
|
||||
const filteredAttachments =
|
||||
sharePointMedia.length > 0
|
||||
? normalizedAttachments.filter((att) => {
|
||||
const contentType = att.contentType?.toLowerCase();
|
||||
const contentType = normalizeOptionalLowercaseString(att.contentType);
|
||||
if (contentType !== "reference") {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,11 @@ import {
|
||||
normalizeHostnameSuffixAllowlist,
|
||||
type SsrFPolicy,
|
||||
} from "openclaw/plugin-sdk/ssrf-policy";
|
||||
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
isRecord,
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { MSTeamsAttachmentLike } from "./types.js";
|
||||
|
||||
type InlineImageCandidate =
|
||||
@@ -119,9 +123,9 @@ export function inferPlaceholder(params: {
|
||||
fileName?: string;
|
||||
fileType?: string;
|
||||
}): string {
|
||||
const mime = params.contentType?.toLowerCase() ?? "";
|
||||
const name = params.fileName?.toLowerCase() ?? "";
|
||||
const fileType = params.fileType?.toLowerCase() ?? "";
|
||||
const mime = normalizeLowercaseStringOrEmpty(params.contentType ?? "");
|
||||
const name = normalizeLowercaseStringOrEmpty(params.fileName ?? "");
|
||||
const fileType = normalizeLowercaseStringOrEmpty(params.fileType ?? "");
|
||||
|
||||
const looksLikeImage =
|
||||
mime.startsWith("image/") || IMAGE_EXT_RE.test(name) || IMAGE_EXT_RE.test(`x.${fileType}`);
|
||||
@@ -232,7 +236,7 @@ function decodeDataImageWithLimits(
|
||||
if (!match) {
|
||||
return { candidate: null, estimatedBytes: 0 };
|
||||
}
|
||||
const contentType = match[1]?.toLowerCase();
|
||||
const contentType = normalizeLowercaseStringOrEmpty(match[1] ?? "");
|
||||
const isBase64 = Boolean(match[2]);
|
||||
if (!isBase64) {
|
||||
return { candidate: null, estimatedBytes: 0 };
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* 6. Optionally sends a proactive follow-up to the user
|
||||
*/
|
||||
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
dispatchReplyFromConfigWithSettledDispatcher,
|
||||
type OpenClawConfig,
|
||||
@@ -241,7 +242,9 @@ export async function runFeedbackReflection(params: RunFeedbackReflectionParams)
|
||||
log.debug?.("failed to store reflection learning", { error: formatUnknownError(err) });
|
||||
}
|
||||
|
||||
const conversationType = params.conversationRef.conversation?.conversationType?.toLowerCase();
|
||||
const conversationType = normalizeOptionalLowercaseString(
|
||||
params.conversationRef.conversation?.conversationType,
|
||||
);
|
||||
const shouldNotify =
|
||||
conversationType === "personal" &&
|
||||
parsedReflection.followUp &&
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* and messenger.ts (reply path) to avoid duplication.
|
||||
*/
|
||||
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { buildFileConsentCard } from "./file-consent.js";
|
||||
import { storePendingUpload } from "./pending-uploads.js";
|
||||
|
||||
@@ -66,7 +67,7 @@ export function requiresFileConsent(params: {
|
||||
bufferSize: number;
|
||||
thresholdBytes: number;
|
||||
}): boolean {
|
||||
const isPersonal = params.conversationType?.toLowerCase() === "personal";
|
||||
const isPersonal = normalizeOptionalLowercaseString(params.conversationType) === "personal";
|
||||
const isImage = params.contentType?.startsWith("image/") ?? false;
|
||||
const isLargeFile = params.bufferSize >= params.thresholdBytes;
|
||||
return isPersonal && (isLargeFile || !isImage);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
createChannelReplyPipeline,
|
||||
logTypingFailure,
|
||||
@@ -47,7 +48,9 @@ export function createMSTeamsReplyDispatcher(params: {
|
||||
}) {
|
||||
const core = getMSTeamsRuntime();
|
||||
const msteamsCfg = params.cfg.channels?.msteams;
|
||||
const conversationType = params.conversationRef.conversation?.conversationType?.toLowerCase();
|
||||
const conversationType = normalizeOptionalLowercaseString(
|
||||
params.conversationRef.conversation?.conversationType,
|
||||
);
|
||||
const isTypingSupported = conversationType === "personal" || conversationType === "groupchat";
|
||||
|
||||
const sendTypingIndicator = isTypingSupported
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { ReplyPayload } from "../runtime-api.js";
|
||||
import { formatUnknownError } from "./errors.js";
|
||||
import type { MSTeamsMonitorLogger } from "./monitor-types.js";
|
||||
@@ -23,7 +24,7 @@ export function createTeamsReplyStreamController(params: {
|
||||
log: MSTeamsMonitorLogger;
|
||||
random?: () => number;
|
||||
}) {
|
||||
const isPersonal = params.conversationType?.toLowerCase() === "personal";
|
||||
const isPersonal = normalizeOptionalLowercaseString(params.conversationType) === "personal";
|
||||
const stream = isPersonal
|
||||
? new TeamsHttpStream({
|
||||
sendActivity: (activity) => params.context.sendActivity(activity),
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { mapAllowlistResolutionInputs } from "openclaw/plugin-sdk/allow-from";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import { searchGraphUsers } from "./graph-users.js";
|
||||
import {
|
||||
listChannelsForTeam,
|
||||
@@ -135,7 +139,9 @@ export async function resolveMSTeamsChannelAllowlist(params: {
|
||||
} catch {
|
||||
// API failure (rate limit, network error) — fall back to Graph GUID as team key
|
||||
}
|
||||
const generalChannel = teamChannels.find((ch) => ch.displayName?.toLowerCase() === "general");
|
||||
const generalChannel = teamChannels.find(
|
||||
(ch) => normalizeOptionalLowercaseString(ch.displayName) === "general",
|
||||
);
|
||||
// Use the General channel's conversation ID as the team key — this
|
||||
// matches what Bot Framework sends at runtime. Fall back to the Graph
|
||||
// GUID if the General channel isn't found (renamed or deleted).
|
||||
@@ -150,11 +156,14 @@ export async function resolveMSTeamsChannelAllowlist(params: {
|
||||
};
|
||||
}
|
||||
// Reuse teamChannels — already fetched above
|
||||
const normalizedChannel = normalizeOptionalLowercaseString(channel);
|
||||
const channelMatch =
|
||||
teamChannels.find((item) => item.id === channel) ??
|
||||
teamChannels.find((item) => item.displayName?.toLowerCase() === channel.toLowerCase()) ??
|
||||
teamChannels.find(
|
||||
(item) => normalizeOptionalLowercaseString(item.displayName) === normalizedChannel,
|
||||
) ??
|
||||
teamChannels.find((item) =>
|
||||
item.displayName?.toLowerCase().includes(channel.toLowerCase() ?? ""),
|
||||
normalizeLowercaseStringOrEmpty(item.displayName ?? "").includes(normalizedChannel ?? ""),
|
||||
);
|
||||
if (!channelMatch?.id) {
|
||||
return { input, resolved: false, note: "channel not found" };
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
stripTargetKindPrefix,
|
||||
type ChannelOutboundSessionRouteParams,
|
||||
} from "openclaw/plugin-sdk/core";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
export function resolveMSTeamsOutboundSessionRoute(params: ChannelOutboundSessionRouteParams) {
|
||||
let trimmed = stripChannelTargetPrefix(params.target, "msteams", "teams");
|
||||
@@ -11,7 +12,7 @@ export function resolveMSTeamsOutboundSessionRoute(params: ChannelOutboundSessio
|
||||
return null;
|
||||
}
|
||||
|
||||
const lower = trimmed.toLowerCase();
|
||||
const lower = normalizeLowercaseStringOrEmpty(trimmed);
|
||||
const isUser = lower.startsWith("user:");
|
||||
const rawId = stripTargetKindPrefix(trimmed);
|
||||
if (!rawId) {
|
||||
|
||||
Reference in New Issue
Block a user