diff --git a/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs b/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs index ad7ff546b..1f7df9cfc 100644 --- a/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs +++ b/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs @@ -28,37 +28,52 @@ public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Long URL format: //// https://teams.microsoft.com/l/meetup-join/19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype/1509579179399?context={"Tid":"72f988bf-86f1-41af-91ab-2d7cd011db47","Oid":"550fae72-d251-43ec-868c-373732c2704f","MessageId":"1536978844957"} var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); - if (!match.Success) + if (match.Success) { - throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + { + var ctxt = (Context)new DataContractJsonSerializer(typeof(Context)).ReadObject(stream); + var chatInfo = new ChatInfo + { + ThreadId = match.Groups["thread"].Value, + MessageId = match.Groups["message"].Value, + ReplyChainMessageId = ctxt.MessageId, + }; + + var meetingInfo = new OrganizerMeetingInfo + { + Organizer = new IdentitySet + { + User = new Identity { Id = ctxt.Oid }, + }, + }; + + // meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); + return (chatInfo, meetingInfo); + } } - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + //// Short URL format: + //// https://teams.microsoft.com/meet/2414128301281?p=NzhDLMLT8b07DrkwkE + var shortUrlRegex = new Regex("https://teams\\.microsoft\\.com/meet/(?[^?]+)\\?p=(?.+)"); + var shortUrlMatch = shortUrlRegex.Match(decodedURL); + if (shortUrlMatch.Success) { - var ctxt = (Context)new DataContractJsonSerializer(typeof(Context)).ReadObject(stream); - var chatInfo = new ChatInfo + var meetingInfo = new JoinMeetingIdMeetingInfo { - ThreadId = match.Groups["thread"].Value, - MessageId = match.Groups["message"].Value, - ReplyChainMessageId = ctxt.MessageId, + JoinMeetingId = shortUrlMatch.Groups["meetingId"].Value, + Passcode = shortUrlMatch.Groups["passcode"].Value, }; - var meetingInfo = new OrganizerMeetingInfo - { - Organizer = new IdentitySet - { - User = new Identity { Id = ctxt.Oid }, - }, - }; - - // meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); - return (chatInfo, meetingInfo); + return (new ChatInfo(), meetingInfo); } + + throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); } /// diff --git a/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs b/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs index da5d39316..3d3b8fa42 100644 --- a/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs +++ b/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs @@ -28,37 +28,52 @@ public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Long URL format: //// https://teams.microsoft.com/l/meetup-join/19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype/1509579179399?context={"Tid":"72f988bf-86f1-41af-91ab-2d7cd011db47","Oid":"550fae72-d251-43ec-868c-373732c2704f","MessageId":"1536978844957"} var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); - if (!match.Success) + if (match.Success) { - throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + { + var ctxt = (Context)new DataContractJsonSerializer(typeof(Context)).ReadObject(stream); + var chatInfo = new ChatInfo + { + ThreadId = match.Groups["thread"].Value, + MessageId = match.Groups["message"].Value, + ReplyChainMessageId = ctxt.MessageId, + }; + + var meetingInfo = new OrganizerMeetingInfo + { + Organizer = new IdentitySet + { + User = new Identity { Id = ctxt.Oid }, + }, + }; + + // meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); + return (chatInfo, meetingInfo); + } } - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + //// Short URL format: + //// https://teams.microsoft.com/meet/2414128301281?p=NzhDLMLT8b07DrkwkE + var shortUrlRegex = new Regex("https://teams\\.microsoft\\.com/meet/(?[^?]+)\\?p=(?.+)"); + var shortUrlMatch = shortUrlRegex.Match(decodedURL); + if (shortUrlMatch.Success) { - var ctxt = (Context)new DataContractJsonSerializer(typeof(Context)).ReadObject(stream); - var chatInfo = new ChatInfo + var meetingInfo = new JoinMeetingIdMeetingInfo { - ThreadId = match.Groups["thread"].Value, - MessageId = match.Groups["message"].Value, - ReplyChainMessageId = ctxt.MessageId, + JoinMeetingId = shortUrlMatch.Groups["meetingId"].Value, + Passcode = shortUrlMatch.Groups["passcode"].Value, }; - var meetingInfo = new OrganizerMeetingInfo - { - Organizer = new IdentitySet - { - User = new Identity { Id = ctxt.Oid }, - }, - }; - - // meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); - return (chatInfo, meetingInfo); + return (new ChatInfo(), meetingInfo); } + + throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); } /// diff --git a/Samples/Common/Sample.Common/Meetings/JoinInfo.cs b/Samples/Common/Sample.Common/Meetings/JoinInfo.cs index c43df2d95..bc52e37ee 100644 --- a/Samples/Common/Sample.Common/Meetings/JoinInfo.cs +++ b/Samples/Common/Sample.Common/Meetings/JoinInfo.cs @@ -28,37 +28,52 @@ public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Long URL format: //// https://teams.microsoft.com/l/meetup-join/19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype/1509579179399?context={"Tid":"72f988bf-86f1-41af-91ab-2d7cd011db47","Oid":"550fae72-d251-43ec-868c-373732c2704f","MessageId":"1536978844957"} var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); - if (!match.Success) + if (match.Success) { - throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + { + var ctxt = (Context)new DataContractJsonSerializer(typeof(Context)).ReadObject(stream); + var chatInfo = new ChatInfo + { + ThreadId = match.Groups["thread"].Value, + MessageId = match.Groups["message"].Value, + ReplyChainMessageId = ctxt.MessageId, + }; + + var meetingInfo = new OrganizerMeetingInfo + { + Organizer = new IdentitySet + { + User = new Identity { Id = ctxt.Oid }, + }, + }; + meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); + + return (chatInfo, meetingInfo); + } } - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + //// Short URL format: + //// https://teams.microsoft.com/meet/2414128301281?p=NzhDLMLT8b07DrkwkE + var shortUrlRegex = new Regex("https://teams\\.microsoft\\.com/meet/(?[^?]+)\\?p=(?.+)"); + var shortUrlMatch = shortUrlRegex.Match(decodedURL); + if (shortUrlMatch.Success) { - var ctxt = (Context)new DataContractJsonSerializer(typeof(Context)).ReadObject(stream); - var chatInfo = new ChatInfo + var meetingInfo = new JoinMeetingIdMeetingInfo { - ThreadId = match.Groups["thread"].Value, - MessageId = match.Groups["message"].Value, - ReplyChainMessageId = ctxt.MessageId, + JoinMeetingId = shortUrlMatch.Groups["meetingId"].Value, + Passcode = shortUrlMatch.Groups["passcode"].Value, }; - var meetingInfo = new OrganizerMeetingInfo - { - Organizer = new IdentitySet - { - User = new Identity { Id = ctxt.Oid }, - }, - }; - meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); - - return (chatInfo, meetingInfo); + return (new ChatInfo(), meetingInfo); } + + throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); } /// diff --git a/Samples/PublicSamples/EchoBot/src/EchoBot/Bot/BotService.cs b/Samples/PublicSamples/EchoBot/src/EchoBot/Bot/BotService.cs index aa6a3a147..5c29de2e7 100644 --- a/Samples/PublicSamples/EchoBot/src/EchoBot/Bot/BotService.cs +++ b/Samples/PublicSamples/EchoBot/src/EchoBot/Bot/BotService.cs @@ -194,7 +194,17 @@ public async Task JoinCallAsync(JoinCallBody joinCallBody) var (chatInfo, meetingInfo) = JoinInfo.ParseJoinURL(joinCallBody.JoinUrl); - var tenantId = (meetingInfo as OrganizerMeetingInfo).Organizer.GetPrimaryIdentity().GetTenantId(); + var tenantId = + joinCallBody.TenantId ?? + (meetingInfo as OrganizerMeetingInfo)?.Organizer?.GetPrimaryIdentity()?.GetTenantId(); + + if (string.IsNullOrWhiteSpace(tenantId)) + { + throw new HttpRequestException( + "TenantId could not be resolved from the join URL or request body.", + null, + HttpStatusCode.BadRequest); + } var mediaSession = this.CreateLocalMediaSession(); var joinParams = new JoinMeetingParameters(chatInfo, meetingInfo, mediaSession) diff --git a/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinCallBody.cs b/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinCallBody.cs index 0897eec4f..526b2838a 100644 --- a/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinCallBody.cs +++ b/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinCallBody.cs @@ -24,6 +24,14 @@ public class JoinCallBody /// The join URL. public string JoinUrl { get; set; } + /// + /// Gets or sets the tenant id. + /// Required when using short meeting URLs (e.g. https://teams.microsoft.com/meet/...). + /// The tenant id cannot be inferred from short URLs and must be provided separately. + /// + /// The tenant id. + public string? TenantId { get; set; } + /// /// Gets or sets the display name. /// Teams client does not allow changing of ones own display name. diff --git a/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs b/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs index c4e6da7d2..ab19e8213 100644 --- a/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs +++ b/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs @@ -43,40 +43,55 @@ public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) var decodedURL = WebUtility.UrlDecode(joinURL); + //// Long URL format: var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); - if (!match.Success) + if (match.Success) { - throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); - } + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + { + var ctxt = (Meeting)new DataContractJsonSerializer(typeof(Meeting)).ReadObject(stream); - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) - { - var ctxt = (Meeting)new DataContractJsonSerializer(typeof(Meeting)).ReadObject(stream); + if (string.IsNullOrEmpty(ctxt.Tid)) + { + throw new ArgumentException("Join URL is invalid: missing Tid", nameof(joinURL)); + } - if (string.IsNullOrEmpty(ctxt.Tid)) - { - throw new ArgumentException("Join URL is invalid: missing Tid", nameof(joinURL)); - } + var chatInfo = new ChatInfo + { + ThreadId = match.Groups["thread"].Value, + MessageId = match.Groups["message"].Value, + ReplyChainMessageId = ctxt.MessageId, + }; - var chatInfo = new ChatInfo - { - ThreadId = match.Groups["thread"].Value, - MessageId = match.Groups["message"].Value, - ReplyChainMessageId = ctxt.MessageId, - }; + var meetingInfo = new OrganizerMeetingInfo + { + Organizer = new IdentitySet + { + User = new Identity { Id = ctxt.Oid }, + }, + }; + meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); + + return (chatInfo, meetingInfo); + } + } - var meetingInfo = new OrganizerMeetingInfo + //// Short URL format: https://teams.microsoft.com/meet/?p= + var shortUrlRegex = new Regex("https://teams\\.microsoft\\.com/meet/(?[^?]+)\\?p=(?.+)"); + var shortUrlMatch = shortUrlRegex.Match(decodedURL); + if (shortUrlMatch.Success) + { + var meetingInfo = new JoinMeetingIdMeetingInfo { - Organizer = new IdentitySet - { - User = new Identity { Id = ctxt.Oid }, - }, + JoinMeetingId = shortUrlMatch.Groups["meetingId"].Value, + Passcode = shortUrlMatch.Groups["passcode"].Value, }; - meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); - return (chatInfo, meetingInfo); + return (new ChatInfo(), meetingInfo); } + + throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); } } } diff --git a/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Model/Models/JoinCallBody.cs b/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Model/Models/JoinCallBody.cs index 6435119a3..34415ce79 100644 --- a/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Model/Models/JoinCallBody.cs +++ b/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Model/Models/JoinCallBody.cs @@ -16,6 +16,14 @@ public class JoinCallBody /// The join URL. public string JoinURL { get; set; } + /// + /// Gets or sets the tenant id. + /// Required when using short meeting URLs (e.g. https://teams.microsoft.com/meet/...). + /// The tenant id cannot be inferred from short URLs and must be provided separately. + /// + /// The tenant id. + public string TenantId { get; set; } + /// /// Gets or sets the display name. /// Teams client does not allow changing of ones own display name. diff --git a/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Service/Bot/BotService.cs b/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Service/Bot/BotService.cs index 7c5bc2ab4..a2348150f 100644 --- a/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Service/Bot/BotService.cs +++ b/Samples/PublicSamples/PsiBot/PsiBot/PsiBot.Service/Bot/BotService.cs @@ -141,7 +141,16 @@ public async Task JoinCallAsync(JoinCallBody joinCallBody) var (chatInfo, meetingInfo) = ParseJoinURL(joinCallBody.JoinURL); - var tenantId = (meetingInfo as OrganizerMeetingInfo).Organizer.GetPrimaryIdentity().GetTenantId(); + var tenantId = + joinCallBody.TenantId ?? + (meetingInfo as OrganizerMeetingInfo)?.Organizer.GetPrimaryIdentity()?.GetTenantId(); + + if (string.IsNullOrWhiteSpace(tenantId)) + { + throw new InvalidOperationException( + "TenantId is required to join the meeting. " + + "Ensure JoinCallBody.TenantId is provided or the meeting URL includes organizer tenant information."); + } var mediaSession = this.CreateLocalMediaSession(); var joinParams = new JoinMeetingParameters(chatInfo, meetingInfo, mediaSession) @@ -338,43 +347,57 @@ private CallHandler GetHandlerOrThrow(string callLegId) var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Long URL format: //// https://teams.microsoft.com/l/meetup-join/19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype/1509579179399?context={"Tid":"72f988bf-86f1-41af-91ab-2d7cd011db47","Oid":"550fae72-d251-43ec-868c-373732c2704f","MessageId":"1536978844957"} var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); - if (!match.Success) + if (match.Success) { - throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); - } + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + { + var ctxt = (Meeting)new DataContractJsonSerializer(typeof(Meeting)).ReadObject(stream); - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) - { - var ctxt = (Meeting)new DataContractJsonSerializer(typeof(Meeting)).ReadObject(stream); + if (string.IsNullOrEmpty(ctxt.Tid)) + { + throw new ArgumentException("Join URL is invalid: missing Tid", nameof(joinURL)); + } - if (string.IsNullOrEmpty(ctxt.Tid)) - { - throw new ArgumentException("Join URL is invalid: missing Tid", nameof(joinURL)); - } + var chatInfo = new ChatInfo + { + ThreadId = match.Groups["thread"].Value, + MessageId = match.Groups["message"].Value, + ReplyChainMessageId = ctxt.MessageId, + }; - var chatInfo = new ChatInfo - { - ThreadId = match.Groups["thread"].Value, - MessageId = match.Groups["message"].Value, - ReplyChainMessageId = ctxt.MessageId, - }; + var meetingInfo = new OrganizerMeetingInfo + { + Organizer = new IdentitySet + { + User = new Identity { Id = ctxt.Oid }, + }, + }; + meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); + + return (chatInfo, meetingInfo); + } + } - var meetingInfo = new OrganizerMeetingInfo + //// Short URL format: https://teams.microsoft.com/meet/?p= + var shortUrlRegex = new Regex("https://teams\\.microsoft\\.com/meet/(?[^?]+)\\?p=(?.+)"); + var shortUrlMatch = shortUrlRegex.Match(decodedURL); + if (shortUrlMatch.Success) + { + var meetingInfo = new JoinMeetingIdMeetingInfo { - Organizer = new IdentitySet - { - User = new Identity { Id = ctxt.Oid }, - }, + JoinMeetingId = shortUrlMatch.Groups["meetingId"].Value, + Passcode = shortUrlMatch.Groups["passcode"].Value, }; - meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); - return (chatInfo, meetingInfo); + return (new ChatInfo(), meetingInfo); } + + throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); } } } diff --git a/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Model/Models/JoinCallBody.cs b/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Model/Models/JoinCallBody.cs index 2a5bb533d..9e0c9e083 100644 --- a/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Model/Models/JoinCallBody.cs +++ b/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Model/Models/JoinCallBody.cs @@ -24,6 +24,14 @@ public class JoinCallBody /// The join URL. public string JoinURL { get; set; } + /// + /// Gets or sets the tenant id. + /// Required when using short meeting URLs (e.g. https://teams.microsoft.com/meet/...). + /// The tenant id cannot be inferred from short URLs and must be provided separately. + /// + /// The tenant id. + public string TenantId { get; set; } + /// /// Gets or sets the display name. /// Teams client does not allow changing of ones own display name. diff --git a/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Bot/BotService.cs b/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Bot/BotService.cs index 36ec997f5..6ea9fa4ba 100644 --- a/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Bot/BotService.cs +++ b/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Bot/BotService.cs @@ -151,7 +151,16 @@ public async Task JoinCallAsync(JoinCallBody joinCallBody) var (chatInfo, meetingInfo) = JoinInfo.ParseJoinURL(joinCallBody.JoinURL); - var tenantId = (meetingInfo as OrganizerMeetingInfo).Organizer.GetPrimaryIdentity().GetTenantId(); + var tenantId = + joinCallBody.TenantId ?? + (meetingInfo as OrganizerMeetingInfo)?.Organizer.GetPrimaryIdentity()?.GetTenantId(); + + if (string.IsNullOrWhiteSpace(tenantId)) + { + throw new InvalidOperationException( + "TenantId is required to join the call. " + + "Ensure that JoinCallBody.TenantId is set or the meeting URL contains organizer tenant information."); + } var mediaSession = this.CreateLocalMediaSession(); var joinParams = new JoinMeetingParameters(chatInfo, meetingInfo, mediaSession) diff --git a/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Util/JoinInfo.cs b/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Util/JoinInfo.cs index 37e776f80..15455208f 100644 --- a/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Util/JoinInfo.cs +++ b/Samples/V1.0Samples/AksSamples(Deprecated)/teams-recording-bot/src/RecordingBot.Services/Util/JoinInfo.cs @@ -44,43 +44,57 @@ public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Long URL format: //// https://teams.microsoft.com/l/meetup-join/19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype/1509579179399?context={"Tid":"72f988bf-86f1-41af-91ab-2d7cd011db47","Oid":"550fae72-d251-43ec-868c-373732c2704f","MessageId":"1536978844957"} var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); - if (!match.Success) + if (match.Success) { - throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); - } + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) + { + var ctxt = (Meeting)new DataContractJsonSerializer(typeof(Meeting)).ReadObject(stream); - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(match.Groups["context"].Value))) - { - var ctxt = (Meeting)new DataContractJsonSerializer(typeof(Meeting)).ReadObject(stream); + if (string.IsNullOrEmpty(ctxt.Tid)) + { + throw new ArgumentException("Join URL is invalid: missing Tid", nameof(joinURL)); + } - if (string.IsNullOrEmpty(ctxt.Tid)) - { - throw new ArgumentException("Join URL is invalid: missing Tid", nameof(joinURL)); - } + var chatInfo = new ChatInfo + { + ThreadId = match.Groups["thread"].Value, + MessageId = match.Groups["message"].Value, + ReplyChainMessageId = ctxt.MessageId, + }; - var chatInfo = new ChatInfo - { - ThreadId = match.Groups["thread"].Value, - MessageId = match.Groups["message"].Value, - ReplyChainMessageId = ctxt.MessageId, - }; + var meetingInfo = new OrganizerMeetingInfo + { + Organizer = new IdentitySet + { + User = new Identity { Id = ctxt.Oid }, + }, + }; + meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); + + return (chatInfo, meetingInfo); + } + } - var meetingInfo = new OrganizerMeetingInfo + //// Short URL format: https://teams.microsoft.com/meet/?p= + var shortUrlRegex = new Regex("https://teams\\.microsoft\\.com/meet/(?[^?]+)\\?p=(?.+)"); + var shortUrlMatch = shortUrlRegex.Match(decodedURL); + if (shortUrlMatch.Success) + { + var meetingInfo = new JoinMeetingIdMeetingInfo { - Organizer = new IdentitySet - { - User = new Identity { Id = ctxt.Oid }, - }, + JoinMeetingId = shortUrlMatch.Groups["meetingId"].Value, + Passcode = shortUrlMatch.Groups["passcode"].Value, }; - meetingInfo.Organizer.User.SetTenantId(ctxt.Tid); - return (chatInfo, meetingInfo); + return (new ChatInfo(), meetingInfo); } + + throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); } } }