Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Libraries/Microsoft.Teams.Api/Account.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,49 @@ public class Account
public Dictionary<string, object>? Properties { get; set; }
}

/// <summary>
/// Represents a Teams channel account, extending the basic channel account with Teams-specific properties.
/// This is used to represent a user or bot in Microsoft Teams conversations.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.bot.schema.teams.teamschannelaccount"/>
public class TeamsChannelAccount : Account
{
/// <summary>
/// Given name (first name) of the user.
/// </summary>
[JsonPropertyName("givenName")]
[JsonPropertyOrder(6)]
public string? GivenName { get; set; }

/// <summary>
/// Surname (last name) of the user.
/// </summary>
[JsonPropertyName("surname")]
[JsonPropertyOrder(7)]
public string? Surname { get; set; }

/// <summary>
/// Email address of the user.
/// </summary>
[JsonPropertyName("email")]
[JsonPropertyOrder(8)]
public string? Email { get; set; }

/// <summary>
/// Unique User Principal Name (UPN) for the user in AAD.
/// </summary>
[JsonPropertyName("userPrincipalName")]
[JsonPropertyOrder(9)]
public string? UserPrincipalName { get; set; }

/// <summary>
/// Unique identifier for the user's Azure AD tenant.
/// </summary>
[JsonPropertyName("tenantId")]
[JsonPropertyOrder(10)]
public string? TenantId { get; set; }
}

[JsonConverter(typeof(JsonConverter<Role>))]
public class Role(string value) : StringEnum(value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class Member
/// </summary>
[JsonPropertyName("user")]
[JsonPropertyOrder(0)]
public required Account User { get; set; }
public required TeamsChannelAccount User { get; set; }

/// <summary>
/// The participants info.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class Member
/// </summary>
[JsonPropertyName("user")]
[JsonPropertyOrder(0)]
public required Account User { get; set; }
public required TeamsChannelAccount User { get; set; }

/// <summary>
/// The participants info.
Expand Down
2 changes: 1 addition & 1 deletion Libraries/Microsoft.Teams.Api/Clients/MeetingClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public class MeetingParticipant
/// </summary>
[JsonPropertyName("user")]
[JsonPropertyOrder(1)]
public Account? User { get; set; }
public TeamsChannelAccount? User { get; set; }

/// <summary>
/// The participant's role in the meeting
Expand Down
8 changes: 4 additions & 4 deletions Libraries/Microsoft.Teams.Api/Clients/MemberClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ public MemberClient(string serviceUrl, IHttpClientFactory factory, CancellationT
ServiceUrl = serviceUrl;
}

public async Task<List<Account>> GetAsync(string conversationId)
public async Task<List<TeamsChannelAccount>> GetAsync(string conversationId)
{
var request = HttpRequest.Get($"{ServiceUrl}v3/conversations/{conversationId}/members");
var response = await _http.SendAsync<List<Account>>(request, _cancellationToken);
var response = await _http.SendAsync<List<TeamsChannelAccount>>(request, _cancellationToken);
return response.Body;
}

public async Task<Account> GetByIdAsync(string conversationId, string memberId)
public async Task<TeamsChannelAccount> GetByIdAsync(string conversationId, string memberId)
{
var request = HttpRequest.Get($"{ServiceUrl}v3/conversations/{conversationId}/members/{memberId}");
var response = await _http.SendAsync<Account>(request, _cancellationToken);
var response = await _http.SendAsync<TeamsChannelAccount>(request, _cancellationToken);
return response.Body;
}

Expand Down
2 changes: 1 addition & 1 deletion Libraries/Microsoft.Teams.Api/Meetings/Meeting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ public class Meeting
/// </summary>
[JsonPropertyName("organizer")]
[JsonPropertyOrder(3)]
public Account? Organizer { get; set; }
public TeamsChannelAccount? Organizer { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public MeetingParticipantJoinActivity SetupMeetingParticipantJoinActivity()
Members = new List<Member>() {
new Member()
{
User = new Account()
User = new TeamsChannelAccount()
{
Id = "userId",
Name = "userName"
Expand All @@ -39,7 +39,7 @@ public MeetingParticipantJoinActivity SetupMeetingParticipantJoinActivity()
},
new Member()
{
User = new Account()
User = new TeamsChannelAccount()
{
Id = "botId",
Name = "BotUser"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public MeetingParticipantLeaveActivity SetupMeetingParticipantLeaveActivity()
Members = new List<Member>() {
new Member()
{
User = new Account()
User = new TeamsChannelAccount()
{
Id = "userId",
Name = "userName"
Expand All @@ -39,7 +39,7 @@ public MeetingParticipantLeaveActivity SetupMeetingParticipantLeaveActivity()
},
new Member()
{
User = new Account()
User = new TeamsChannelAccount()
{
Id = "botId",
Name = "BotUser"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public async Task MeetingClient_GetParticipantAsync()
Body = new MeetingParticipant
{
Id = "participant1",
User = new Account { Id = "user1", Name = "John Doe" },
User = new TeamsChannelAccount { Id = "user1", Name = "John Doe" },
Role = "Presenter",
IsOrganizer = true,
JoinTime = DateTime.UtcNow
Expand Down
20 changes: 10 additions & 10 deletions Tests/Microsoft.Teams.Api.Tests/Clients/MemberClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public async Task MemberClient_GetAsync()
responseMessage.Headers.Add("Custom-Header", "HeaderValue");
var mockHandler = new Mock<IHttpClient>();
mockHandler
.Setup(handler => handler.SendAsync<List<Account>>(It.IsAny<IHttpRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new HttpResponse<List<Account>>()
.Setup(handler => handler.SendAsync<List<TeamsChannelAccount>>(It.IsAny<IHttpRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new HttpResponse<List<TeamsChannelAccount>>()
{
Headers = responseMessage.Headers,
StatusCode = HttpStatusCode.OK,
Body = new List<Account>
Body = new List<TeamsChannelAccount>
{
new Account { Id = "member1", Name = "User 1" },
new Account { Id = "member2", Name = "User 2" }
new TeamsChannelAccount { Id = "member1", Name = "User 1" },
new TeamsChannelAccount { Id = "member2", Name = "User 2" }
}
});

Expand All @@ -39,7 +39,7 @@ public async Task MemberClient_GetAsync()

string expectedUrl = "https://serviceurl.com/v3/conversations/conv123/members";
HttpMethod expectedMethod = HttpMethod.Get;
mockHandler.Verify(x => x.SendAsync<List<Account>>(
mockHandler.Verify(x => x.SendAsync<List<TeamsChannelAccount>>(
It.Is<IHttpRequest>(arg => arg.Url == expectedUrl && arg.Method == expectedMethod),
It.IsAny<CancellationToken>()),
Times.Once);
Expand All @@ -52,12 +52,12 @@ public async Task MemberClient_GetByIdAsync()
responseMessage.Headers.Add("Custom-Header", "HeaderValue");
var mockHandler = new Mock<IHttpClient>();
mockHandler
.Setup(handler => handler.SendAsync<Account>(It.IsAny<IHttpRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new HttpResponse<Account>()
.Setup(handler => handler.SendAsync<TeamsChannelAccount>(It.IsAny<IHttpRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new HttpResponse<TeamsChannelAccount>()
{
Headers = responseMessage.Headers,
StatusCode = HttpStatusCode.OK,
Body = new Account { Id = "member1", Name = "User 1" }
Body = new TeamsChannelAccount { Id = "member1", Name = "User 1" }
});

string serviceUrl = "https://serviceurl.com/";
Expand All @@ -72,7 +72,7 @@ public async Task MemberClient_GetByIdAsync()

string expectedUrl = "https://serviceurl.com/v3/conversations/conv123/members/member1";
HttpMethod expectedMethod = HttpMethod.Get;
mockHandler.Verify(x => x.SendAsync<Account>(
mockHandler.Verify(x => x.SendAsync<TeamsChannelAccount>(
It.Is<IHttpRequest>(arg => arg.Url == expectedUrl && arg.Method == expectedMethod),
It.IsAny<CancellationToken>()),
Times.Once);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task Should_CallHandler_OnMeetingJoinEvent()
{
new MeetingParticipantJoinActivityValue.Member
{
User = new Account { Id = "user1", Name = "Test User" },
User = new TeamsChannelAccount { Id = "user1", Name = "Test User" },
Meeting = new MeetingParticipantJoinActivityValue.Meeting
{
InMeeting = true,
Expand Down Expand Up @@ -103,7 +103,7 @@ public void MeetingJoinAttribute_Select_ReturnsTrueForMeetingJoinActivity()
{
new MeetingParticipantJoinActivityValue.Member
{
User = new Account { Id = "user1", Name = "Test User" },
User = new TeamsChannelAccount { Id = "user1", Name = "Test User" },
Meeting = new MeetingParticipantJoinActivityValue.Meeting
{
InMeeting = true,
Expand Down Expand Up @@ -148,7 +148,7 @@ public async Task MeetingJoinAttribute_Controller_Call()
{
new MeetingParticipantJoinActivityValue.Member
{
User = new Account { Id = "user1", Name = "Test User" },
User = new TeamsChannelAccount { Id = "user1", Name = "Test User" },
Meeting = new MeetingParticipantJoinActivityValue.Meeting
{
InMeeting = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public async Task Should_CallHandler_OnMeetingLeaveEvent()
{
new MeetingParticipantLeaveActivityValue.Member
{
User = new Account { Id = "user1", Name = "Test User" },
User = new TeamsChannelAccount { Id = "user1", Name = "Test User" },
Meeting = new MeetingParticipantLeaveActivityValue.Meeting
{
InMeeting = true,
Expand Down Expand Up @@ -105,7 +105,7 @@ public void MeetingLeaveAttribute_Select_ReturnsTrueForMeetingLeaveActivity()
{
new MeetingParticipantLeaveActivityValue.Member
{
User = new Account { Id = "user1", Name = "Test User" },
User = new TeamsChannelAccount { Id = "user1", Name = "Test User" },
Meeting = new MeetingParticipantLeaveActivityValue.Meeting
{
InMeeting = true,
Expand Down Expand Up @@ -150,7 +150,7 @@ public async Task MeetingLeaveAttribute_Controller_Call()
{
new MeetingParticipantLeaveActivityValue.Member
{
User = new Account { Id = "user1", Name = "Test User" },
User = new TeamsChannelAccount { Id = "user1", Name = "Test User" },
Meeting = new MeetingParticipantLeaveActivityValue.Meeting
{
InMeeting = true,
Expand Down
Loading