Skip to main content
Glama
users.ts4.74 kB
import type { GraphService } from "../services/graph.js"; import type { User } from "../types/graph.js"; export interface UserInfo { id: string; displayName: string; userPrincipalName?: string; } /** * Search for users by display name or email */ export async function searchUsers( graphService: GraphService, query: string, limit = 10 ): Promise<UserInfo[]> { try { const client = await graphService.getClient(); // Use filter query to search users by displayName or userPrincipalName const searchQuery = `$filter=startswith(displayName,'${query}') or startswith(userPrincipalName,'${query}')&$top=${limit}&$select=id,displayName,userPrincipalName`; const response = await client.api(`/users?${searchQuery}`).get(); if (!response?.value?.length) { return []; } return response.value.map((user: User) => ({ id: user.id || "", displayName: user.displayName || "Unknown User", userPrincipalName: user.userPrincipalName || undefined, })); } catch (error) { console.error("Error searching users:", error); return []; } } /** * Get user by exact email or UPN */ export async function getUserByEmail( graphService: GraphService, email: string ): Promise<UserInfo | null> { try { const client = await graphService.getClient(); const response = await client.api(`/users/${email}`).get(); return { id: response.id, displayName: response.displayName || "Unknown User", userPrincipalName: response.userPrincipalName, }; } catch (_error) { // User not found or access denied return null; } } /** * Get user by ID */ export async function getUserById( graphService: GraphService, userId: string ): Promise<UserInfo | null> { try { const client = await graphService.getClient(); const response = await client .api(`/users/${userId}`) .select("id,displayName,userPrincipalName") .get(); return { id: response.id, displayName: response.displayName || "Unknown User", userPrincipalName: response.userPrincipalName, }; } catch (_error) { // User not found or access denied return null; } } /** * Parse @mentions from text and return user lookup suggestions * @param text - Message text containing @mentions * @param graphService - Graph service instance * @returns Array of mention patterns found and suggested users */ export async function parseMentions( text: string, graphService: GraphService ): Promise<Array<{ mention: string; users: UserInfo[] }>> { // Match @mentions in the format @username, @email@domain.com, or @"User Name" const mentionRegex = /@(?:"([^"]+)"|([^\s@]+(?:@[^\s@]+\.[^\s@]+)?|[^\s@]+))/g; const mentions: Array<{ mention: string; users: UserInfo[] }> = []; let match: RegExpExecArray | null = mentionRegex.exec(text); while (match !== null) { const mentionText = match[1] || match[2]; // Quoted name or unquoted let users: UserInfo[] = []; // If it looks like an email, try exact lookup first if (mentionText.includes("@") && mentionText.includes(".")) { const user = await getUserByEmail(graphService, mentionText); if (user) { users = [user]; } } // If no exact match found, search by name if (users.length === 0) { users = await searchUsers(graphService, mentionText, 5); } mentions.push({ mention: mentionText, users, }); match = mentionRegex.exec(text); } return mentions; } /** * Generate HTML content with @mentions converted to proper format */ export function processMentionsInHtml( html: string, mentionMappings: Array<{ mention: string; userId: string; displayName: string }> ): { content: string; mentions: Array<{ id: number; mentionText: string; mentioned: { user: { id: string } } }>; } { let processedContent = html; const mentions: Array<{ id: number; mentionText: string; mentioned: { user: { id: string } } }> = []; mentionMappings.forEach((mapping, index) => { // Replace @mention with HTML mention format const mentionRegex = new RegExp( `@(?:"${escapeRegex(mapping.mention)}"|${escapeRegex(mapping.mention)})`, "g" ); const mentionId = index; processedContent = processedContent.replace( mentionRegex, `<at id="${mentionId}">${mapping.displayName}</at>` ); mentions.push({ id: mentionId, mentionText: mapping.displayName, mentioned: { user: { id: mapping.userId, }, }, }); }); return { content: processedContent, mentions }; } function escapeRegex(text: string): string { return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }

Implementation Reference

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