/**
* MIME type detection and filename extraction for MSTeams media attachments .
*/
import path from "node:path" ;
import {
detectMime,
extensionForMime,
extractOriginalFilename,
getFileExtension,
} from "../runtime-api.js" ;
/**
* Detect MIME type from URL extension or data URL .
* Uses shared MIME detection for consistency with core handling .
*/
export async function getMimeType(url: string): Promise<string> {
// Handle data URLs: data:image/png;base64,...
if (url.startsWith("data:" )) {
const match = url.match(/^data:([^;,]+)/);
if (match?.[1 ]) {
return match[1 ];
}
}
// Use shared MIME detection (extension-based for URLs)
const detected = await detectMime({ filePath: url });
return detected ?? "application/octet-stream" ;
}
/**
* Extract filename from URL or local path .
* For local paths , extracts original filename if stored with embedded name pattern .
* Falls back to deriving the extension from MIME type when no extension present .
*/
export async function extractFilename(url: string): Promise<string> {
// Handle data URLs: derive extension from MIME
if (url.startsWith("data:" )) {
const mime = await getMimeType(url);
const ext = extensionForMime(mime) ?? ".bin" ;
const prefix = mime.startsWith("image/" ) ? "image" : "file" ;
return `${prefix}${ext}`;
}
// Try to extract from URL pathname
try {
const pathname = new URL(url).pathname;
const basename = path.basename(pathname);
const existingExt = getFileExtension(pathname);
if (basename && existingExt) {
return basename;
}
// No extension in URL, derive from MIME
const mime = await getMimeType(url);
const ext = extensionForMime(mime) ?? ".bin" ;
const prefix = mime.startsWith("image/" ) ? "image" : "file" ;
return basename ? `${basename}${ext}` : `${prefix}${ext}`;
} catch {
// Local paths - use extractOriginalFilename to extract embedded original name
return extractOriginalFilename(url);
}
}
/**
* Check if a URL refers to a local file path .
*/
export function isLocalPath(url: string): boolean {
if (url.startsWith("file://") || url.startsWith("/") || url.startsWith("~")) {
return true ;
}
// Windows rooted path on current drive (e.g. \tmp\file.txt)
if (url.startsWith("\\" ) && !url.startsWith("\\\\" )) {
return true ;
}
// Windows drive-letter absolute path (e.g. C:\foo\bar.txt or C:/foo/bar.txt)
if (/^[a-zA-Z]:[\\/]/.test(url)) {
return true ;
}
// Windows UNC path (e.g. \\server\share\file.txt)
if (url.startsWith("\\\\" )) {
return true ;
}
return false ;
}
/**
* Extract the message ID from a Bot Framework response .
*/
export function extractMessageId(response: unknown): string | null {
if (!response || typeof response !== "object" ) {
return null ;
}
if (!("id" in response)) {
return null ;
}
const { id } = response as { id?: unknown };
if (typeof id !== "string" || !id) {
return null ;
}
return id;
}
Messung V0.5 in Prozent C=96 H=97 G=96
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland