diff --git a/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs b/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs index ad7ff546b..be6402806 100644 --- a/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs +++ b/Samples/Common/Sample.Common.Beta/Meetings/JoinInfo.cs @@ -21,20 +21,42 @@ public class JoinInfo { /// /// Parse Join URL into its components. + /// NOTE: This method only works with the OLD Teams meeting URL format that includes a context parameter. + /// For NEW shorter Teams meeting URLs (introduced with MCnumber rollout), you should: + /// 1. Use the Graph API to query the OnlineMeeting by JoinWebUrl to get meeting details + /// 2. Use JoinMeetingIdMeetingInfo with the meeting ID and passcode from the API response + /// Example: var meeting = await graphClient.Communications.OnlineMeetings.Request().Filter($"JoinWebUrl eq '{encodedUrl}'").GetAsync(); /// /// Join URL from Team's meeting body. /// Parsed data. public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { + if (string.IsNullOrWhiteSpace(joinURL)) + { + throw new ArgumentException($"Join URL cannot be null, empty, or whitespace: {joinURL}", nameof(joinURL)); + } + var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Old URL format with context parameter: //// 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"} + //// New shorter URL format (not supported by this parser): + //// https://teams.microsoft.com/l/meetup-join/... var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); if (!match.Success) { + // Check if this is a new shorter URL format + if (decodedURL.Contains("teams.microsoft.com") && decodedURL.Contains("/meetup-join/") && !decodedURL.Contains("?context=")) + { + throw new NotSupportedException( + $"This appears to be a new shorter Teams meeting URL format which is not supported by this parser. " + + $"To join meetings with this URL format, please use the Graph API to resolve the meeting details:\n" + + $"1. Query: GET /communications/onlineMeetings?$filter=JoinWebUrl eq '{Uri.EscapeDataString(joinURL)}'\n" + + $"2. Use JoinMeetingIdMeetingInfo with the meeting.JoinMeetingIdSettings from the response.\n" + + $"See: https://learn.microsoft.com/graph/api/resources/joinmeetingidmeetinginfo"); + } throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); } diff --git a/Samples/Common/Sample.Common.Tests/HeartbeatHandlerTests.cs b/Samples/Common/Sample.Common.Tests/HeartbeatHandlerTests.cs index cebdb5eb6..126d4dd85 100644 --- a/Samples/Common/Sample.Common.Tests/HeartbeatHandlerTests.cs +++ b/Samples/Common/Sample.Common.Tests/HeartbeatHandlerTests.cs @@ -25,7 +25,7 @@ public class HeartbeatHandlerTests /// /// Gets or sets the test context. /// - public TestContext TestContext + public TestContext? TestContext { get; set; } @@ -73,7 +73,7 @@ public void HeartbeatShouldLogSuccess() onNext: @event => { Interlocked.Increment(ref loggerCount); - this.TestContext.WriteLine(formatter.Format(@event)); + this.TestContext!.WriteLine(formatter.Format(@event)); }, onError: @exception => { @@ -107,7 +107,7 @@ public void HeartbeatShouldLogFailure() onNext: @event => { Interlocked.Increment(ref errorCount); - this.TestContext.WriteLine(formatter.Format(@event)); + this.TestContext!.WriteLine(formatter.Format(@event)); }, onError: @exception => { diff --git a/Samples/Common/Sample.Common.Tests/Meetings/JoinInfoTests.cs b/Samples/Common/Sample.Common.Tests/Meetings/JoinInfoTests.cs new file mode 100644 index 000000000..378487b73 --- /dev/null +++ b/Samples/Common/Sample.Common.Tests/Meetings/JoinInfoTests.cs @@ -0,0 +1,187 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. +// + +namespace Samples.Common.Tests.Meetings +{ + using System; + using Microsoft.Graph; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Sample.Common.Meetings; + + /// + /// Unit tests for JoinInfo URL parsing. + /// + [TestClass] + public class JoinInfoTests + { + private const string OldFormatUrl = "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\"}"; + private const string OldFormatUrlEncoded = "https://teams.microsoft.com/l/meetup-join/19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype/1509579179399?context=%7B%22Tid%22%3A%2272f988bf-86f1-41af-91ab-2d7cd011db47%22%2C%22Oid%22%3A%22550fae72-d251-43ec-868c-373732c2704f%22%2C%22MessageId%22%3A%221536978844957%22%7D"; + private const string NewFormatUrlShort = "https://teams.microsoft.com/l/meetup-join/19:meeting_abc123def456@thread.v2/0"; + private const string NewFormatUrlWithoutContext = "https://teams.microsoft.com/l/meetup-join/19:meeting_YzY4NDFjZDUtZTdlOC00MDg3LWI3M2QtZTgzYzdiYzM0Yjk5@thread.skype/0"; + + /// + /// Gets or sets the test context. + /// + public TestContext? TestContext { get; set; } + + /// + /// Test that old format URL with context parameter parses successfully. + /// + [TestMethod] + public void ParseJoinURL_OldFormatWithContext_ParsesSuccessfully() + { + // Act + var (chatInfo, meetingInfo) = JoinInfo.ParseJoinURL(OldFormatUrl); + + // Assert + Assert.IsNotNull(chatInfo); + Assert.IsNotNull(meetingInfo); + Assert.AreEqual("19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype", chatInfo.ThreadId); + Assert.AreEqual("1509579179399", chatInfo.MessageId); + Assert.AreEqual("1536978844957", chatInfo.ReplyChainMessageId); + + Assert.IsInstanceOfType(meetingInfo, typeof(OrganizerMeetingInfo)); + var organizerInfo = (OrganizerMeetingInfo)meetingInfo; + Assert.IsNotNull(organizerInfo.Organizer); + Assert.IsNotNull(organizerInfo.Organizer.User); + Assert.AreEqual("550fae72-d251-43ec-868c-373732c2704f", organizerInfo.Organizer.User.Id); + } + + /// + /// Test that old format URL with encoded context parameter parses successfully. + /// + [TestMethod] + public void ParseJoinURL_OldFormatUrlEncoded_ParsesSuccessfully() + { + // Act + var (chatInfo, meetingInfo) = JoinInfo.ParseJoinURL(OldFormatUrlEncoded); + + // Assert + Assert.IsNotNull(chatInfo); + Assert.IsNotNull(meetingInfo); + Assert.AreEqual("19:cd9ce3da56624fe69c9d7cd026f9126d@thread.skype", chatInfo.ThreadId); + Assert.IsInstanceOfType(meetingInfo, typeof(OrganizerMeetingInfo)); + } + + /// + /// Test that new shorter URL format throws NotSupportedException. + /// + [TestMethod] + [ExpectedException(typeof(NotSupportedException))] + public void ParseJoinURL_NewShorterFormat_ThrowsNotSupportedException() + { + // Act + JoinInfo.ParseJoinURL(NewFormatUrlShort); + } + + /// + /// Test that new URL format without context throws NotSupportedException. + /// + [TestMethod] + [ExpectedException(typeof(NotSupportedException))] + public void ParseJoinURL_NewFormatWithoutContext_ThrowsNotSupportedException() + { + // Act + JoinInfo.ParseJoinURL(NewFormatUrlWithoutContext); + } + + /// + /// Test that new format URL exception message contains helpful guidance. + /// + [TestMethod] + public void ParseJoinURL_NewFormat_ExceptionContainsGuidance() + { + // Act & Assert + var exception = Assert.ThrowsException(() => + { + JoinInfo.ParseJoinURL(NewFormatUrlShort); + }); + + this.TestContext!.WriteLine($"Exception message: {exception.Message}"); + + // Verify the exception message contains helpful guidance + Assert.IsTrue(exception.Message.Contains("new shorter Teams meeting URL format")); + Assert.IsTrue(exception.Message.Contains("Graph API")); + Assert.IsTrue(exception.Message.Contains("JoinMeetingIdMeetingInfo")); + Assert.IsTrue(exception.Message.Contains("/communications/onlineMeetings")); + } + + /// + /// Test that null URL throws ArgumentException. + /// + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ParseJoinURL_NullUrl_ThrowsArgumentException() + { + // Act + JoinInfo.ParseJoinURL(null); + } + + /// + /// Test that empty URL throws ArgumentException. + /// + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ParseJoinURL_EmptyUrl_ThrowsArgumentException() + { + // Act + JoinInfo.ParseJoinURL(string.Empty); + } + + /// + /// Test that whitespace URL throws ArgumentException. + /// + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ParseJoinURL_WhitespaceUrl_ThrowsArgumentException() + { + // Act + JoinInfo.ParseJoinURL(" "); + } + + /// + /// Test that completely invalid URL throws ArgumentException. + /// + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ParseJoinURL_InvalidUrl_ThrowsArgumentException() + { + // Act + JoinInfo.ParseJoinURL("https://example.com/not-a-teams-url"); + } + + /// + /// Test that malformed Teams URL throws ArgumentException. + /// + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ParseJoinURL_MalformedTeamsUrl_ThrowsArgumentException() + { + // Act + JoinInfo.ParseJoinURL("https://teams.microsoft.com/malformed?context=invalid"); + } + + /// + /// Test that different thread formats are parsed correctly. + /// + [TestMethod] + public void ParseJoinURL_DifferentThreadFormats_ParsesCorrectly() + { + // Arrange + var threadSkypeUrl = "https://teams.microsoft.com/l/meetup-join/19:meeting_abc@thread.skype/0?context={\"Tid\":\"72f988bf-86f1-41af-91ab-2d7cd011db47\",\"Oid\":\"550fae72-d251-43ec-868c-373732c2704f\"}"; + var threadV2Url = "https://teams.microsoft.com/l/meetup-join/19:meeting_abc@thread.v2/0?context={\"Tid\":\"72f988bf-86f1-41af-91ab-2d7cd011db47\",\"Oid\":\"550fae72-d251-43ec-868c-373732c2704f\"}"; + + // Act + var (chatInfo1, meetingInfo1) = JoinInfo.ParseJoinURL(threadSkypeUrl); + var (chatInfo2, meetingInfo2) = JoinInfo.ParseJoinURL(threadV2Url); + + // Assert + Assert.AreEqual("19:meeting_abc@thread.skype", chatInfo1.ThreadId); + Assert.AreEqual("19:meeting_abc@thread.v2", chatInfo2.ThreadId); + Assert.IsNotNull(meetingInfo1); + Assert.IsNotNull(meetingInfo2); + } + } +} diff --git a/Samples/Common/Sample.Common.Tests/Sample.Common.Tests.csproj b/Samples/Common/Sample.Common.Tests/Sample.Common.Tests.csproj index 98c310c5b..ddf18a942 100644 --- a/Samples/Common/Sample.Common.Tests/Sample.Common.Tests.csproj +++ b/Samples/Common/Sample.Common.Tests/Sample.Common.Tests.csproj @@ -1,18 +1,18 @@ - netcoreapp2.2 - + net6.0 false + enable - - - - + + + + diff --git a/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs b/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs index da5d39316..29947aff8 100644 --- a/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs +++ b/Samples/Common/Sample.Common.V1/Meetings/JoinInfo.cs @@ -21,20 +21,42 @@ public class JoinInfo { /// /// Parse Join URL into its components. + /// NOTE: This method only works with the OLD Teams meeting URL format that includes a context parameter. + /// For NEW shorter Teams meeting URLs (introduced with MCnumber rollout), you should: + /// 1. Use the Graph API to query the OnlineMeeting by JoinWebUrl to get meeting details + /// 2. Use JoinMeetingIdMeetingInfo with the meeting ID and passcode from the API response + /// Example: var meeting = await graphClient.Communications.OnlineMeetings.Request().Filter($"JoinWebUrl eq '{encodedUrl}'").GetAsync(); /// /// Join URL from Team's meeting body. /// Parsed data. public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { + if (string.IsNullOrWhiteSpace(joinURL)) + { + throw new ArgumentException($"Join URL cannot be null, empty, or whitespace: {joinURL}", nameof(joinURL)); + } + var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Old URL format with context parameter: //// 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"} + //// New shorter URL format (not supported by this parser): + //// https://teams.microsoft.com/l/meetup-join/... var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); if (!match.Success) { + // Check if this is a new shorter URL format + if (decodedURL.Contains("teams.microsoft.com") && decodedURL.Contains("/meetup-join/") && !decodedURL.Contains("?context=")) + { + throw new NotSupportedException( + $"This appears to be a new shorter Teams meeting URL format which is not supported by this parser. " + + $"To join meetings with this URL format, please use the Graph API to resolve the meeting details:\n" + + $"1. Query: GET /communications/onlineMeetings?$filter=JoinWebUrl eq '{Uri.EscapeDataString(joinURL)}'\n" + + $"2. Use JoinMeetingIdMeetingInfo with the meeting.JoinMeetingIdSettings from the response.\n" + + $"See: https://learn.microsoft.com/graph/api/resources/joinmeetingidmeetinginfo"); + } 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..aeaf60e49 100644 --- a/Samples/Common/Sample.Common/Meetings/JoinInfo.cs +++ b/Samples/Common/Sample.Common/Meetings/JoinInfo.cs @@ -21,20 +21,43 @@ public class JoinInfo { /// /// Parse Join URL into its components. + /// NOTE: This method only works with the OLD Teams meeting URL format that includes a context parameter. + /// For NEW shorter Teams meeting URLs (introduced with MCnumber rollout), you should: + /// 1. Use the Graph API to query the OnlineMeeting by JoinWebUrl to get meeting details. + /// 2. Use JoinMeetingIdMeetingInfo with the meeting ID and passcode from the API response. + /// Example: var meeting = await graphClient.Communications.OnlineMeetings.Request().Filter($"JoinWebUrl eq '{encodedUrl}'").GetAsync(). /// /// Join URL from Team's meeting body. /// Parsed data. public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { + if (string.IsNullOrWhiteSpace(joinURL)) + { + throw new ArgumentException($"Join URL cannot be null, empty, or whitespace: {joinURL}", nameof(joinURL)); + } + var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Old URL format with context parameter: //// 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"} + //// New shorter URL format (not supported by this parser): + //// https://teams.microsoft.com/l/meetup-join/... var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); if (!match.Success) { + // Check if this is a new shorter URL format + if (decodedURL.Contains("teams.microsoft.com") && decodedURL.Contains("/meetup-join/") && !decodedURL.Contains("?context=")) + { + throw new NotSupportedException( + $"This appears to be a new shorter Teams meeting URL format which is not supported by this parser. " + + $"To join meetings with this URL format, please use the Graph API to resolve the meeting details:\n" + + $"1. Query: GET /communications/onlineMeetings?$filter=JoinWebUrl eq '{Uri.EscapeDataString(joinURL)}'\n" + + $"2. Use JoinMeetingIdMeetingInfo with the meeting.JoinMeetingIdSettings from the response.\n" + + $"See: https://learn.microsoft.com/graph/api/resources/joinmeetingidmeetinginfo"); + } + throw new ArgumentException($"Join URL cannot be parsed: {joinURL}.", nameof(joinURL)); } diff --git a/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs b/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs index c4e6da7d2..02a56b42c 100644 --- a/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs +++ b/Samples/PublicSamples/EchoBot/src/EchoBot/Models/JoinInfo.cs @@ -28,25 +28,46 @@ public class JoinInfo { /// /// Parse Join URL into its components. + /// NOTE: This method only works with the OLD Teams meeting URL format that includes a context parameter. + /// For NEW shorter Teams meeting URLs (introduced with MCnumber rollout), you should: + /// 1. Use the Graph API to query the OnlineMeeting by JoinWebUrl to get meeting details + /// 2. Use JoinMeetingIdMeetingInfo with the meeting ID and passcode from the API response + /// Example: var meeting = await graphClient.Communications.OnlineMeetings.Request().Filter($"JoinWebUrl eq '{encodedUrl}'").GetAsync(); /// /// Join URL from Team's meeting body. /// Parsed data. /// Join URL cannot be null or empty: {joinURL} - joinURL /// Join URL cannot be parsed: {joinURL} - joinURL + /// Join URL is in new shorter format - use Graph API /// Join URL is invalid: missing Tid - joinURL public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { - if (string.IsNullOrEmpty(joinURL)) + if (string.IsNullOrWhiteSpace(joinURL)) { - throw new ArgumentException($"Join URL cannot be null or empty: {joinURL}", nameof(joinURL)); + throw new ArgumentException($"Join URL cannot be null, empty, or whitespace: {joinURL}", nameof(joinURL)); } var decodedURL = WebUtility.UrlDecode(joinURL); + //// Old URL format with context parameter: + //// 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"} + //// New shorter URL format (not supported by this parser): + //// https://teams.microsoft.com/l/meetup-join/... + var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); if (!match.Success) { + // Check if this is a new shorter URL format + if (decodedURL.Contains("teams.microsoft.com") && decodedURL.Contains("/meetup-join/") && !decodedURL.Contains("?context=")) + { + throw new NotSupportedException( + $"This appears to be a new shorter Teams meeting URL format which is not supported by this parser. " + + $"To join meetings with this URL format, please use the Graph API to resolve the meeting details:\n" + + $"1. Query: GET /communications/onlineMeetings?$filter=JoinWebUrl eq '{Uri.EscapeDataString(joinURL)}'\n" + + $"2. Use JoinMeetingIdMeetingInfo with the meeting.JoinMeetingIdSettings from the response.\n" + + $"See: https://learn.microsoft.com/graph/api/resources/joinmeetingidmeetinginfo"); + } throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); } 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..a1042b3ee 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 @@ -29,28 +29,46 @@ public class JoinInfo { /// /// Parse Join URL into its components. + /// NOTE: This method only works with the OLD Teams meeting URL format that includes a context parameter. + /// For NEW shorter Teams meeting URLs (introduced with MCnumber rollout), you should: + /// 1. Use the Graph API to query the OnlineMeeting by JoinWebUrl to get meeting details + /// 2. Use JoinMeetingIdMeetingInfo with the meeting ID and passcode from the API response + /// Example: var meeting = await graphClient.Communications.OnlineMeetings.Request().Filter($"JoinWebUrl eq '{encodedUrl}'").GetAsync(); /// /// Join URL from Team's meeting body. /// Parsed data. /// Join URL cannot be null or empty: {joinURL} - joinURL /// Join URL cannot be parsed: {joinURL} - joinURL + /// Join URL is in new shorter format - use Graph API /// Join URL is invalid: missing Tid - joinURL public static (ChatInfo, MeetingInfo) ParseJoinURL(string joinURL) { - if (string.IsNullOrEmpty(joinURL)) + if (string.IsNullOrWhiteSpace(joinURL)) { - throw new ArgumentException($"Join URL cannot be null or empty: {joinURL}", nameof(joinURL)); + throw new ArgumentException($"Join URL cannot be null, empty, or whitespace: {joinURL}", nameof(joinURL)); } var decodedURL = WebUtility.UrlDecode(joinURL); - //// URL being needs to be in this format. + //// Old URL format with context parameter: //// 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"} + //// New shorter URL format (not supported by this parser): + //// https://teams.microsoft.com/l/meetup-join/... var regex = new Regex("https://teams\\.microsoft\\.com.*/(?[^/]+)/(?[^/]+)\\?context=(?{.*})"); var match = regex.Match(decodedURL); if (!match.Success) { + // Check if this is a new shorter URL format + if (decodedURL.Contains("teams.microsoft.com") && decodedURL.Contains("/meetup-join/") && !decodedURL.Contains("?context=")) + { + throw new NotSupportedException( + $"This appears to be a new shorter Teams meeting URL format which is not supported by this parser. " + + $"To join meetings with this URL format, please use the Graph API to resolve the meeting details:\n" + + $"1. Query: GET /communications/onlineMeetings?$filter=JoinWebUrl eq '{Uri.EscapeDataString(joinURL)}'\n" + + $"2. Use JoinMeetingIdMeetingInfo with the meeting.JoinMeetingIdSettings from the response.\n" + + $"See: https://learn.microsoft.com/graph/api/resources/joinmeetingidmeetinginfo"); + } throw new ArgumentException($"Join URL cannot be parsed: {joinURL}", nameof(joinURL)); } diff --git a/Samples/V1.0Samples/LocalMediaSamples/HueBot/HueBot/HueBot.csproj b/Samples/V1.0Samples/LocalMediaSamples/HueBot/HueBot/HueBot.csproj index e5afb0cfc..a08cd5953 100644 --- a/Samples/V1.0Samples/LocalMediaSamples/HueBot/HueBot/HueBot.csproj +++ b/Samples/V1.0Samples/LocalMediaSamples/HueBot/HueBot/HueBot.csproj @@ -13,9 +13,9 @@ - + - +