* Resolves a channel name or ID to a channel object within the given team.
( accessToken: string, teamId: string, channelInput: string )
| 161 | * Resolves a channel name or ID to a channel object within the given team. |
| 162 | */ |
| 163 | async function resolveChannel( |
| 164 | accessToken: string, |
| 165 | teamId: string, |
| 166 | channelInput: string |
| 167 | ): Promise<TeamsChannel | null> { |
| 168 | const trimmed = channelInput.trim() |
| 169 | |
| 170 | // Fetch all channels for the team |
| 171 | let nextLink: string | undefined |
| 172 | // $select avoids the expensive `email` property per Graph perf guidance. |
| 173 | const initialPath = `/teams/${encodeURIComponent(teamId)}/channels?$select=id,displayName,description` |
| 174 | let currentUrl: string = initialPath |
| 175 | |
| 176 | do { |
| 177 | const data = await graphApiGet<TeamsChannelsResponse>(currentUrl, accessToken) |
| 178 | const channels = data.value || [] |
| 179 | |
| 180 | // Try matching by ID first, then by display name (case-insensitive) |
| 181 | const match = channels.find( |
| 182 | (ch) => ch.id === trimmed || ch.displayName.toLowerCase() === trimmed.toLowerCase() |
| 183 | ) |
| 184 | if (match) return match |
| 185 | |
| 186 | nextLink = data['@odata.nextLink'] |
| 187 | if (nextLink) { |
| 188 | currentUrl = nextLink |
| 189 | } |
| 190 | } while (nextLink) |
| 191 | |
| 192 | return null |
| 193 | } |
| 194 | |
| 195 | export const microsoftTeamsConnector: ConnectorConfig = { |
| 196 | ...microsoftTeamsConnectorMeta, |