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 @@
-
+
-
+