Skip to main content
Glama
attachments.ts3.45 kB
import type { GraphService } from "../services/graph.js"; export interface ImageAttachment { id: string; contentType: string; contentUrl?: string; name?: string; thumbnailUrl?: string; } export interface HostedContent { "@microsoft.graph.temporaryId": string; contentBytes: string; contentType: string; } /** * Upload image as hosted content for Teams messages * This creates a temporary hosted content that can be referenced in message attachments */ export async function uploadImageAsHostedContent( graphService: GraphService, teamId: string, channelId: string, imageData: Buffer | string, contentType: string, fileName?: string ): Promise<{ hostedContentId: string; attachment: ImageAttachment } | null> { try { const client = await graphService.getClient(); // Convert Buffer to base64 if needed const contentBytes = typeof imageData === "string" ? imageData : imageData.toString("base64"); // Create hosted content const hostedContent: HostedContent = { "@microsoft.graph.temporaryId": `temp_${Date.now()}_${Math.random().toString(36).substring(7)}`, contentBytes, contentType, }; // Upload hosted content const response = await client .api(`/teams/${teamId}/channels/${channelId}/messages/hostedContents`) .post(hostedContent); const hostedContentId = response.id; // Create attachment reference const attachment: ImageAttachment = { id: hostedContentId, contentType, contentUrl: `https://graph.microsoft.com/v1.0/teams/${teamId}/channels/${channelId}/messages/hostedContents/${hostedContentId}/$value`, name: fileName || `image.${getFileExtensionFromMimeType(contentType)}`, }; return { hostedContentId, attachment }; } catch (error) { console.error("Error uploading image as hosted content:", error); return null; } } /** * Validate image content type */ export function isValidImageType(contentType: string): boolean { const validTypes = [ "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp", "image/bmp", "image/svg+xml", ]; return validTypes.includes(contentType.toLowerCase()); } /** * Get file extension from MIME type */ export function getFileExtensionFromMimeType(mimeType: string): string { const extensions: Record<string, string> = { "image/jpeg": "jpg", "image/jpg": "jpg", "image/png": "png", "image/gif": "gif", "image/webp": "webp", "image/bmp": "bmp", "image/svg+xml": "svg", }; return extensions[mimeType.toLowerCase()] || "img"; } /** * Convert image URL to base64 for upload */ export async function imageUrlToBase64( imageUrl: string ): Promise<{ data: string; contentType: string } | null> { try { const response = await fetch(imageUrl); if (!response.ok) { throw new Error(`Failed to fetch image: ${response.statusText}`); } const contentType = response.headers.get("content-type") || "image/jpeg"; if (!isValidImageType(contentType)) { throw new Error(`Unsupported image type: ${contentType}`); } const arrayBuffer = await response.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); const base64Data = buffer.toString("base64"); return { data: base64Data, contentType, }; } catch (error) { console.error("Error converting image URL to base64:", error); return null; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/floriscornel/teams-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server