From 8a180f1d6a0cb3afb84516f1e2ae9bb3728c5152 Mon Sep 17 00:00:00 2001 From: Jericho Date: Sat, 26 Oct 2024 15:21:52 -0400 Subject: [PATCH 01/11] Sort the properties on IZoomClient and ZoomClient alphabetically --- Source/ZoomNet/IZoomClient.cs | 87 ++++++++++++----------------------- Source/ZoomNet/ZoomClient.cs | 48 +++++++++---------- 2 files changed, 54 insertions(+), 81 deletions(-) diff --git a/Source/ZoomNet/IZoomClient.cs b/Source/ZoomNet/IZoomClient.cs index 42cc97d9..d38f20cc 100644 --- a/Source/ZoomNet/IZoomClient.cs +++ b/Source/ZoomNet/IZoomClient.cs @@ -11,19 +11,23 @@ public interface IZoomClient /// /// Gets the resource which allows you to manage sub accounts. /// - /// - /// The accounts resource. - /// IAccounts Accounts { get; } + /// + /// Gets the resource which allows you to manage call logs. + /// + ICallLogs CallLogs { get; } + /// /// Gets the resource which allows you to manage chat channels, messages, etc. /// - /// - /// The chat resource. - /// IChat Chat { get; } + /// + /// Gets the resource which allows you to manage chatbot messages. + /// + IChatbot Chatbot { get; } + /// /// Gets the resource which allows you to manage cloud recordings. /// @@ -40,68 +44,42 @@ public interface IZoomClient /// IContacts Contacts { get; } + /// + /// Gets the resource which allows you to view metrics. + /// + IDashboards Dashboards { get; } + /// /// Gets the resource which allows you to notify Zoom that you comply with the policy which requires /// you to handle user's data in accordance to the user's preference after the user uninstalls your app. /// - /// - /// The data compliance resource. - /// [Obsolete("The Data Compliance API is deprecated")] IDataCompliance DataCompliance { get; } + /// + /// Gets the resource that allows you to manage groups. + /// + IGroups Groups { get; } + /// /// Gets the resource which allows you to manage meetings. /// - /// - /// The meetings resource. - /// IMeetings Meetings { get; } /// /// Gets the resource which allows you to manage meetings that occured in the past. /// - /// - /// The past meetings resource. - /// IPastMeetings PastMeetings { get; } /// /// Gets the resource which allows you to manage webinars that occured in the past. /// - /// - /// The past webinars resource. - /// IPastWebinars PastWebinars { get; } /// - /// Gets the resource which allows you to manage roles. - /// - /// - /// The roles resource. - /// - IRoles Roles { get; } - - /// - /// Gets the resource which allows you to manage users. - /// - /// - /// The users resource. - /// - IUsers Users { get; } - - /// - /// Gets the resource which allows you to manage webinars. - /// - /// - /// The webinars resource. - /// - IWebinars Webinars { get; } - - /// - /// Gets the resource which allows you to view metrics. + /// Gets the resource which allows you to access Zoom Phone API endpoints. /// - IDashboards Dashboards { get; } + IPhone Phone { get; } /// /// Gets the resource which allows you to view reports. @@ -109,28 +87,23 @@ public interface IZoomClient IReports Reports { get; } /// - /// Gets the resource which allows you to manage call logs. - /// - ICallLogs CallLogs { get; } - - /// - /// Gets the resource which allows you to manage chatbot messages. + /// Gets the resource which allows you to manage roles. /// - IChatbot Chatbot { get; } + IRoles Roles { get; } /// - /// Gets the resource which allows you to access Zoom Phone API endpoints. + /// Gets the resource which allows you to manage SMS messages and sessions. /// - IPhone Phone { get; } + ISms Sms { get; } /// - /// Gets the resource which allows you to manage SMS messages and sessions. + /// Gets the resource which allows you to manage users. /// - ISms Sms { get; } + IUsers Users { get; } /// - /// Gets the resource that allows you to manage groups. + /// Gets the resource which allows you to manage webinars. /// - IGroups Groups { get; } + IWebinars Webinars { get; } } } diff --git a/Source/ZoomNet/ZoomClient.cs b/Source/ZoomNet/ZoomClient.cs index 7b65b1cd..46bd7213 100644 --- a/Source/ZoomNet/ZoomClient.cs +++ b/Source/ZoomNet/ZoomClient.cs @@ -67,19 +67,31 @@ public static string Version /// public IAccounts Accounts { get; private set; } + /// + public ICallLogs CallLogs { get; private set; } + /// public IChat Chat { get; private set; } + /// + public IChatbot Chatbot { get; private set; } + /// public ICloudRecordings CloudRecordings { get; private set; } /// public IContacts Contacts { get; private set; } + /// + public IDashboards Dashboards { get; private set; } + /// [Obsolete("The Data Compliance API is deprecated")] public IDataCompliance DataCompliance { get; private set; } + /// + public IGroups Groups { get; private set; } + /// public IMeetings Meetings { get; private set; } @@ -90,34 +102,22 @@ public static string Version public IPastWebinars PastWebinars { get; private set; } /// - public IRoles Roles { get; private set; } - - /// - public IUsers Users { get; private set; } - - /// - public IWebinars Webinars { get; private set; } - - /// - public IDashboards Dashboards { get; private set; } + public IPhone Phone { get; private set; } /// public IReports Reports { get; private set; } /// - public ICallLogs CallLogs { get; private set; } - - /// - public IChatbot Chatbot { get; private set; } + public IRoles Roles { get; private set; } /// - public IPhone Phone { get; private set; } + public ISms Sms { get; private set; } /// - public ISms Sms { get; private set; } + public IUsers Users { get; private set; } /// - public IGroups Groups { get; private set; } + public IWebinars Webinars { get; private set; } #endregion @@ -210,23 +210,23 @@ private ZoomClient(IConnectionInfo connectionInfo, HttpClient httpClient, bool d _fluentClient.Filters.Add(new ZoomErrorHandler()); Accounts = new Accounts(_fluentClient); + CallLogs = new CallLogs(_fluentClient); Chat = new Chat(_fluentClient); + Chatbot = new Chatbot(_fluentClient); CloudRecordings = new CloudRecordings(_fluentClient); Contacts = new Contacts(_fluentClient); + Dashboards = new Dashboards(_fluentClient); DataCompliance = new DataCompliance(_fluentClient); + Groups = new Groups(_fluentClient); Meetings = new Meetings(_fluentClient); PastMeetings = new PastMeetings(_fluentClient); PastWebinars = new PastWebinars(_fluentClient); + Phone = new Phone(_fluentClient); + Reports = new Reports(_fluentClient); Roles = new Roles(_fluentClient); + Sms = new Sms(_fluentClient); Users = new Users(_fluentClient); Webinars = new Webinars(_fluentClient); - Dashboards = new Dashboards(_fluentClient); - Reports = new Reports(_fluentClient); - CallLogs = new CallLogs(_fluentClient); - Chatbot = new Chatbot(_fluentClient); - Phone = new Phone(_fluentClient); - Sms = new Sms(_fluentClient); - Groups = new Groups(_fluentClient); } /// From 496309018af0ad6accadd9e39dfd8dcc2686972b Mon Sep 17 00:00:00 2001 From: Jericho Date: Mon, 28 Oct 2024 09:09:42 -0400 Subject: [PATCH 02/11] Add two new MeetingListType values Resolves #372 --- .../Tests/Meetings.cs | 19 +++++++++++++------ Source/ZoomNet/Models/MeetingListType.cs | 19 ++++++++++++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs index 12f97718..8e4c101e 100644 --- a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs +++ b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs @@ -26,22 +26,29 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie var paginatedUpcomingMeetings = await client.Meetings.GetAllAsync(myUser.Id, MeetingListType.Upcoming, 100, null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"There are {paginatedUpcomingMeetings.TotalRecords} upcoming meetings").ConfigureAwait(false); + var paginatedUpcomingMeetingsMeetings = await client.Meetings.GetAllAsync(myUser.Id, MeetingListType.UpcomingMeetings, 100, null, cancellationToken).ConfigureAwait(false); + await log.WriteLineAsync($"There are {paginatedUpcomingMeetingsMeetings.TotalRecords} UpcomingMeetings meetings").ConfigureAwait(false); + + var paginatedPreviousMeetings = await client.Meetings.GetAllAsync(myUser.Id, MeetingListType.PreviousMeetings, 100, null, cancellationToken).ConfigureAwait(false); + await log.WriteLineAsync($"There are {paginatedPreviousMeetings.TotalRecords} previous meetings").ConfigureAwait(false); + // CLEANUP PREVIOUS INTEGRATION TESTS THAT MIGHT HAVE BEEN INTERRUPTED BEFORE THEY HAD TIME TO CLEANUP AFTER THEMSELVES var cleanUpTasks = paginatedScheduledMeetings.Records .Union(paginatedLiveMeetings.Records) .Union(paginatedUpcomingMeetings.Records) + .Union(paginatedUpcomingMeetingsMeetings.Records) + .Union(paginatedPreviousMeetings.Records) .Where(m => m.Topic.StartsWith("ZoomNet Integration Testing:")) - .Select(async oldMeeting => + .GroupBy(m => m.Id) + .Select(async grp => { - await client.Meetings.DeleteAsync(oldMeeting.Id, null, false, false, cancellationToken).ConfigureAwait(false); - await log.WriteLineAsync($"Meeting {oldMeeting.Id} deleted").ConfigureAwait(false); + await client.Meetings.DeleteAsync(grp.Key, null, false, false, cancellationToken).ConfigureAwait(false); + await log.WriteLineAsync($"Meeting {grp.Key} deleted").ConfigureAwait(false); await Task.Delay(250, cancellationToken).ConfigureAwait(false); // Brief pause to ensure Zoom has time to catch up }); await Task.WhenAll(cleanUpTasks).ConfigureAwait(false); - // For an unknown reason, using myUser.Id to retrieve meeting templates causes an "Invalid token" exception. - // That's why I use "me" on the following line: - var templates = await client.Meetings.GetTemplatesAsync("me", cancellationToken).ConfigureAwait(false); + var templates = await client.Meetings.GetTemplatesAsync(myUser.Id, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Retrieved {templates.Length} meeting templates").ConfigureAwait(false); var settings = new MeetingSettings() diff --git a/Source/ZoomNet/Models/MeetingListType.cs b/Source/ZoomNet/Models/MeetingListType.cs index 233e0a99..5db5c972 100644 --- a/Source/ZoomNet/Models/MeetingListType.cs +++ b/Source/ZoomNet/Models/MeetingListType.cs @@ -8,21 +8,34 @@ namespace ZoomNet.Models public enum MeetingListType { /// - /// Scheduled. + /// All valid previous (unexpired) meetings, live meetings, and upcoming scheduled meetings. /// [EnumMember(Value = "scheduled")] Scheduled, /// - /// Live. + /// All the ongoing meetings. /// [EnumMember(Value = "live")] Live, /// - /// Upcoming. + /// All upcoming meetings, including live meetings. /// [EnumMember(Value = "upcoming")] Upcoming, + + /// + /// All upcoming meetings, including live meetings. + /// + /// What is the distinction between "upcoming" and "upcoming_meetings??? + [EnumMember(Value = "upcoming_meetings")] + UpcomingMeetings, + + /// + /// All the previous meetings. + /// + [EnumMember(Value = "previous_meetings")] + PreviousMeetings, } } From 650d260dc09c50ec5281a6cc939a3b95c4c39593 Mon Sep 17 00:00:00 2001 From: Jericho Date: Mon, 28 Oct 2024 10:24:07 -0400 Subject: [PATCH 03/11] Fix Meetings integration test. --- .../Tests/Meetings.cs | 85 ++++++++++--------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs index 8e4c101e..d350fc3f 100644 --- a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs +++ b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs @@ -95,53 +95,54 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie var scheduledMeeting = (ScheduledMeeting)await client.Meetings.GetAsync(newScheduledMeeting.Id, null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Scheduled meeting {scheduledMeeting.Id} retrieved").ConfigureAwait(false); - var requiredFields = new[] - { - RegistrationField.PurchasingTimeFrame, - RegistrationField.RoleInPurchaseProcess - }; - var optionalFields = new[] - { - RegistrationField.Address, - RegistrationField.City, - RegistrationField.Country, - RegistrationField.PostalCode, - RegistrationField.State, - RegistrationField.Phone, - RegistrationField.Industry, - RegistrationField.Organization, - RegistrationField.JobTitle, - RegistrationField.NumberOfEmployees, - RegistrationField.Comments - }; - var customQuestions = new[] + + if (myUser.Type == UserType.Licensed) { - new RegistrationCustomQuestionForMeeting + var requiredFields = new[] { - Title = "Are you happy?", - Type = RegistrationCustomQuestionTypeForMeeting.Single, - IsRequired = true, - Answers = new[] { "Yes", "No", "Maybe", "I don't know" } - }, - new RegistrationCustomQuestionForMeeting + RegistrationField.PurchasingTimeFrame, + RegistrationField.RoleInPurchaseProcess + }; + var optionalFields = new[] { - Title = "Tell us about yourself", - Type = RegistrationCustomQuestionTypeForMeeting.Short, - IsRequired = false - } - }; - await client.Meetings.UpdateRegistrationQuestionsAsync(newScheduledMeeting.Id, requiredFields, optionalFields, customQuestions, cancellationToken).ConfigureAwait(false); - await log.WriteLineAsync($"Added {customQuestions.Length} custom registration questions to this meeting.").ConfigureAwait(false); + RegistrationField.Address, + RegistrationField.City, + RegistrationField.Country, + RegistrationField.PostalCode, + RegistrationField.State, + RegistrationField.Phone, + RegistrationField.Industry, + RegistrationField.Organization, + RegistrationField.JobTitle, + RegistrationField.NumberOfEmployees, + RegistrationField.Comments + }; + var customQuestions = new[] + { + new RegistrationCustomQuestionForMeeting + { + Title = "Are you happy?", + Type = RegistrationCustomQuestionTypeForMeeting.Single, + IsRequired = true, + Answers = new[] { "Yes", "No", "Maybe", "I don't know" } + }, + new RegistrationCustomQuestionForMeeting + { + Title = "Tell us about yourself", + Type = RegistrationCustomQuestionTypeForMeeting.Short, + IsRequired = false + } + }; + await client.Meetings.UpdateRegistrationQuestionsAsync(newScheduledMeeting.Id, requiredFields, optionalFields, customQuestions, cancellationToken).ConfigureAwait(false); + await log.WriteLineAsync($"Added {customQuestions.Length} custom registration questions to this meeting.").ConfigureAwait(false); - var registrationQuestions = await client.Meetings.GetRegistrationQuestionsAsync(newScheduledMeeting.Id, cancellationToken).ConfigureAwait(false); - await log.WriteLineAsync($"Here's a quick summary of the registration form for meeting {newScheduledMeeting.Id}:").ConfigureAwait(false); - await log.WriteLineAsync($" - there are {registrationQuestions.RequiredFields.Length} required fields.").ConfigureAwait(false); - await log.WriteLineAsync($" - there are {registrationQuestions.OptionalFields.Length} optional fields.").ConfigureAwait(false); - await log.WriteLineAsync($" - there are {registrationQuestions.Questions.Count(q => q.IsRequired)} required custom questions.").ConfigureAwait(false); - await log.WriteLineAsync($" - there are {registrationQuestions.Questions.Count(q => !q.IsRequired)} optional custom questions.").ConfigureAwait(false); + var registrationQuestions = await client.Meetings.GetRegistrationQuestionsAsync(newScheduledMeeting.Id, cancellationToken).ConfigureAwait(false); + await log.WriteLineAsync($"Here's a quick summary of the registration form for meeting {newScheduledMeeting.Id}:").ConfigureAwait(false); + await log.WriteLineAsync($" - there are {registrationQuestions.RequiredFields.Length} required fields.").ConfigureAwait(false); + await log.WriteLineAsync($" - there are {registrationQuestions.OptionalFields.Length} optional fields.").ConfigureAwait(false); + await log.WriteLineAsync($" - there are {registrationQuestions.Questions.Count(q => q.IsRequired)} required custom questions.").ConfigureAwait(false); + await log.WriteLineAsync($" - there are {registrationQuestions.Questions.Count(q => !q.IsRequired)} optional custom questions.").ConfigureAwait(false); - if (myUser.Type == UserType.Licensed) - { var registrants = new List { new BatchRegistrant { Email = "firstBatchRegistrant@example.com", FirstName = "Mariful", LastName = "Maruf" }, From 0c9addbc954125edbc46215159bbba32a109cc15 Mon Sep 17 00:00:00 2001 From: Maxwell <136101+mxswd@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:50:14 +1000 Subject: [PATCH 04/11] Added default_password param to CreateMeeting APIs (#280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added default_password * Fixed interface * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Add two new MeetingListType values Resolves #372 * Fix Meetings integration test. * added default_password * Fixed interface * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/IMeetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Update Source/ZoomNet/Resources/Meetings.cs * Add the generatePassword parameter when creting instant meetings * Fix integration test * Throw an exception if developer specifies a custom password and also requests a randomly generated password. --------- Co-authored-by: Jericho <112710+Jericho@users.noreply.github.com> Co-authored-by: Jericho --- .../Tests/Meetings.cs | 8 +++---- Source/ZoomNet/Resources/IMeetings.cs | 9 +++++--- Source/ZoomNet/Resources/Meetings.cs | 21 +++++++++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs index d350fc3f..0911fd42 100644 --- a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs +++ b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs @@ -67,7 +67,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie }; // Instant meeting - var newInstantMeeting = await client.Meetings.CreateInstantMeetingAsync(myUser.Id, "ZoomNet Integration Testing: instant meeting", "The agenda", "p@ss!w0rd", settings, trackingFields, null, cancellationToken).ConfigureAwait(false); + var newInstantMeeting = await client.Meetings.CreateInstantMeetingAsync(myUser.Id, "ZoomNet Integration Testing: instant meeting", "The agenda", null, true, settings, trackingFields, null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Instant meeting {newInstantMeeting.Id} created").ConfigureAwait(false); var instantMeeting = (InstantMeeting)await client.Meetings.GetAsync(newInstantMeeting.Id, null, cancellationToken).ConfigureAwait(false); @@ -85,7 +85,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie // Scheduled meeting var start = DateTime.UtcNow.AddMonths(1); var duration = 30; - var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, "p@ss!w0rd", settings, trackingFields, null, cancellationToken).ConfigureAwait(false); + var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, null, true, settings, trackingFields, null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Scheduled meeting {newScheduledMeeting.Id} created").ConfigureAwait(false); var updatedSettings = new MeetingSettings() { Audio = AudioType.Voip }; @@ -247,7 +247,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie WeeklyDays = new[] { DayOfWeek.Monday, DayOfWeek.Friday }, Type = RecurrenceType.Weekly }; - var newRecurringMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting", "The agenda", start, duration, recurrenceInfo, TimeZones.UTC, "p@ss!w0rd", settings, trackingFields, null, cancellationToken).ConfigureAwait(false); + var newRecurringMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting", "The agenda", start, duration, recurrenceInfo, TimeZones.UTC, "p@ss!w0rd", false, settings, trackingFields, null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Recurring meeting {newRecurringMeeting.Id} created").ConfigureAwait(false); await client.Meetings.UpdateRecurringMeetingAsync(newRecurringMeeting.Id, topic: "ZoomNet Integration Testing: UPDATED recurring meeting", cancellationToken: cancellationToken).ConfigureAwait(false); @@ -267,7 +267,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie await log.WriteLineAsync($"Recurring meeting {newRecurringMeeting.Id} deleted").ConfigureAwait(false); // Recurring meeting with no fixed time - var newRecurringNoFixTimeMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting with no fixed time", "The agenda", start, duration, null, TimeZones.UTC, "p@ss!w0rd", settings, null, null, cancellationToken).ConfigureAwait(false); + var newRecurringNoFixTimeMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting with no fixed time", "The agenda", start, duration, null, TimeZones.UTC, "p@ss!w0rd", false, settings, null, null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Recurring meeting with no fixed time {newRecurringNoFixTimeMeeting.Id} created").ConfigureAwait(false); await client.Meetings.DeleteAsync(newRecurringNoFixTimeMeeting.Id, null, false, false, cancellationToken).ConfigureAwait(false); diff --git a/Source/ZoomNet/Resources/IMeetings.cs b/Source/ZoomNet/Resources/IMeetings.cs index 286c75df..357bb525 100644 --- a/Source/ZoomNet/Resources/IMeetings.cs +++ b/Source/ZoomNet/Resources/IMeetings.cs @@ -54,6 +54,7 @@ public interface IMeetings /// Meeting topic. /// Meeting description. /// Password to join the meeting. Password may only contain the following characters: [a-z A-Z 0-9 @ - _ *]. Max of 10 characters. + /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Meeting settings. /// Tracking fields. /// Template Identifer. @@ -62,7 +63,7 @@ public interface IMeetings /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateInstantMeetingAsync(string userId, string topic, string agenda, string password = null, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); + Task CreateInstantMeetingAsync(string userId, string topic, string agenda, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); /// /// Create a scheduled meeting for a user. @@ -74,6 +75,7 @@ public interface IMeetings /// Meeting duration (minutes). /// The time zone for start time. /// Password to join the meeting. Password may only contain the following characters: [a-z A-Z 0-9 @ - _ *]. Max of 10 characters. + /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Meeting settings. /// Tracking fields. /// Template Identifer. @@ -82,7 +84,7 @@ public interface IMeetings /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateScheduledMeetingAsync(string userId, string topic, string agenda, DateTime start, int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); + Task CreateScheduledMeetingAsync(string userId, string topic, string agenda, DateTime start, int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); /// /// Create a recurring meeting for a user. @@ -95,6 +97,7 @@ public interface IMeetings /// Recurrence information. /// The time zone for start time. /// Password to join the meeting. Password may only contain the following characters: [a-z A-Z 0-9 @ - _ *]. Max of 10 characters. + /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Meeting settings. /// Tracking fields. /// Template Identifer. @@ -103,7 +106,7 @@ public interface IMeetings /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateRecurringMeetingAsync(string userId, string topic, string agenda, DateTime? start, int duration, RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); + Task CreateRecurringMeetingAsync(string userId, string topic, string agenda, DateTime? start, int duration, RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); /// /// Update the details of a meeting occurrence. diff --git a/Source/ZoomNet/Resources/Meetings.cs b/Source/ZoomNet/Resources/Meetings.cs index cc066aa2..e49f515f 100644 --- a/Source/ZoomNet/Resources/Meetings.cs +++ b/Source/ZoomNet/Resources/Meetings.cs @@ -64,16 +64,23 @@ public Task CreateInstantMeetingAsync( string topic, string agenda, string password = null, + bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default) { + if (generatePassword && !string.IsNullOrEmpty(password)) + { + throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); + } + var data = new JsonObject { { "type", 1 }, { "topic", topic }, { "password", password }, + { "default_password", generatePassword }, { "agenda", agenda }, { "settings", settings }, { "tracking_fields", trackingFields?.Select(tf => new JsonObject { { "field", tf.Key }, { "value", tf.Value } }).ToArray() }, @@ -96,16 +103,23 @@ public Task CreateScheduledMeetingAsync( int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, + bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default) { + if (generatePassword && !string.IsNullOrEmpty(password)) + { + throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); + } + var data = new JsonObject { { "type", 2 }, { "topic", topic }, { "password", password }, + { "default_password", generatePassword }, { "agenda", agenda }, { "start_time", start.ToZoomFormat(timeZone) }, { "duration", duration }, @@ -132,16 +146,23 @@ public Task CreateRecurringMeetingAsync( RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, + bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default) { + if (generatePassword && !string.IsNullOrEmpty(password)) + { + throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); + } + var data = new JsonObject { { "type", recurrence == null ? MeetingType.RecurringNoFixedTime : MeetingType.RecurringFixedTime }, { "topic", topic }, { "password", password }, + { "default_password", generatePassword }, { "agenda", agenda }, { "start_time", start.ToZoomFormat(timeZone) }, { "duration", duration }, From 669f238bf1d053d0b01abf39ae32edfd31e9b26a Mon Sep 17 00:00:00 2001 From: Jericho Date: Mon, 28 Oct 2024 12:54:16 -0400 Subject: [PATCH 05/11] Use enums rather than hardcoded values --- Source/ZoomNet/Resources/Meetings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ZoomNet/Resources/Meetings.cs b/Source/ZoomNet/Resources/Meetings.cs index e49f515f..906abd46 100644 --- a/Source/ZoomNet/Resources/Meetings.cs +++ b/Source/ZoomNet/Resources/Meetings.cs @@ -77,7 +77,7 @@ public Task CreateInstantMeetingAsync( var data = new JsonObject { - { "type", 1 }, + { "type", MeetingType.Instant }, { "topic", topic }, { "password", password }, { "default_password", generatePassword }, @@ -116,7 +116,7 @@ public Task CreateScheduledMeetingAsync( var data = new JsonObject { - { "type", 2 }, + { "type", MeetingType.Scheduled }, { "topic", topic }, { "password", password }, { "default_password", generatePassword }, From a973dc9179e9af4ceaaaca547b29c609385571a5 Mon Sep 17 00:00:00 2001 From: Jericho Date: Tue, 29 Oct 2024 13:47:42 -0400 Subject: [PATCH 06/11] Add the preSchedule parameter to CreateScheduledMeetingAsync and CreateRecurringMeetingAsync Resolves #373 --- Source/ZoomNet.IntegrationTests/Tests/Meetings.cs | 6 +++--- Source/ZoomNet/Resources/IMeetings.cs | 6 ++++-- Source/ZoomNet/Resources/Meetings.cs | 9 +++++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs index 0911fd42..1a162900 100644 --- a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs +++ b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs @@ -85,7 +85,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie // Scheduled meeting var start = DateTime.UtcNow.AddMonths(1); var duration = 30; - var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, null, true, settings, trackingFields, null, cancellationToken).ConfigureAwait(false); + var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, null, true, settings, trackingFields, null, false, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Scheduled meeting {newScheduledMeeting.Id} created").ConfigureAwait(false); var updatedSettings = new MeetingSettings() { Audio = AudioType.Voip }; @@ -247,7 +247,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie WeeklyDays = new[] { DayOfWeek.Monday, DayOfWeek.Friday }, Type = RecurrenceType.Weekly }; - var newRecurringMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting", "The agenda", start, duration, recurrenceInfo, TimeZones.UTC, "p@ss!w0rd", false, settings, trackingFields, null, cancellationToken).ConfigureAwait(false); + var newRecurringMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting", "The agenda", start, duration, recurrenceInfo, TimeZones.UTC, "p@ss!w0rd", false, settings, trackingFields, null, false, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Recurring meeting {newRecurringMeeting.Id} created").ConfigureAwait(false); await client.Meetings.UpdateRecurringMeetingAsync(newRecurringMeeting.Id, topic: "ZoomNet Integration Testing: UPDATED recurring meeting", cancellationToken: cancellationToken).ConfigureAwait(false); @@ -267,7 +267,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie await log.WriteLineAsync($"Recurring meeting {newRecurringMeeting.Id} deleted").ConfigureAwait(false); // Recurring meeting with no fixed time - var newRecurringNoFixTimeMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting with no fixed time", "The agenda", start, duration, null, TimeZones.UTC, "p@ss!w0rd", false, settings, null, null, cancellationToken).ConfigureAwait(false); + var newRecurringNoFixTimeMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting with no fixed time", "The agenda", start, duration, null, TimeZones.UTC, "p@ss!w0rd", false, settings, null, null, false, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Recurring meeting with no fixed time {newRecurringNoFixTimeMeeting.Id} created").ConfigureAwait(false); await client.Meetings.DeleteAsync(newRecurringNoFixTimeMeeting.Id, null, false, false, cancellationToken).ConfigureAwait(false); diff --git a/Source/ZoomNet/Resources/IMeetings.cs b/Source/ZoomNet/Resources/IMeetings.cs index 357bb525..78964bc5 100644 --- a/Source/ZoomNet/Resources/IMeetings.cs +++ b/Source/ZoomNet/Resources/IMeetings.cs @@ -79,12 +79,13 @@ public interface IMeetings /// Meeting settings. /// Tracking fields. /// Template Identifer. + /// Whether to create a prescheduled meeting via the GSuite app. /// The cancellation token. /// /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateScheduledMeetingAsync(string userId, string topic, string agenda, DateTime start, int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); + Task CreateScheduledMeetingAsync(string userId, string topic, string agenda, DateTime start, int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, bool preSchedule = false, CancellationToken cancellationToken = default); /// /// Create a recurring meeting for a user. @@ -101,12 +102,13 @@ public interface IMeetings /// Meeting settings. /// Tracking fields. /// Template Identifer. + /// Whether to create a prescheduled meeting via the GSuite app. This only applies to recurring meetings with no fixed time. /// The cancellation token. /// /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateRecurringMeetingAsync(string userId, string topic, string agenda, DateTime? start, int duration, RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); + Task CreateRecurringMeetingAsync(string userId, string topic, string agenda, DateTime? start, int duration, RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, bool preSchedule = false, CancellationToken cancellationToken = default); /// /// Update the details of a meeting occurrence. diff --git a/Source/ZoomNet/Resources/Meetings.cs b/Source/ZoomNet/Resources/Meetings.cs index 906abd46..c8ce787f 100644 --- a/Source/ZoomNet/Resources/Meetings.cs +++ b/Source/ZoomNet/Resources/Meetings.cs @@ -107,6 +107,7 @@ public Task CreateScheduledMeetingAsync( MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, + bool preSchedule = false, CancellationToken cancellationToken = default) { if (generatePassword && !string.IsNullOrEmpty(password)) @@ -126,7 +127,8 @@ public Task CreateScheduledMeetingAsync( { "timezone", timeZone }, { "settings", settings }, { "tracking_fields", trackingFields?.Select(tf => new JsonObject { { "field", tf.Key }, { "value", tf.Value } }).ToArray() }, - { "template_id", templateId } + { "template_id", templateId }, + { "pre_schedule", preSchedule }, }; return _client @@ -150,12 +152,14 @@ public Task CreateRecurringMeetingAsync( MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, + bool preSchedule = false, CancellationToken cancellationToken = default) { if (generatePassword && !string.IsNullOrEmpty(password)) { throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); } + if (preSchedule && recurrence != null) throw new ArgumentException($"{nameof(preSchedule)} can be set to true only when {nameof(recurrence)} is null.", nameof(preSchedule)); var data = new JsonObject { @@ -170,7 +174,8 @@ public Task CreateRecurringMeetingAsync( { "timezone", timeZone }, { "settings", settings }, { "tracking_fields", trackingFields?.Select(tf => new JsonObject { { "field", tf.Key }, { "value", tf.Value } }).ToArray() }, - { "template_id", templateId } + { "template_id", templateId }, + { "pre_schedule", preSchedule }, }; return _client From 8a8d689a8bf017f5723b494cf28884ec2337ed31 Mon Sep 17 00:00:00 2001 From: Jericho Date: Tue, 29 Oct 2024 13:48:08 -0400 Subject: [PATCH 07/11] Formatting --- Source/ZoomNet/Resources/Meetings.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Source/ZoomNet/Resources/Meetings.cs b/Source/ZoomNet/Resources/Meetings.cs index c8ce787f..75bac44e 100644 --- a/Source/ZoomNet/Resources/Meetings.cs +++ b/Source/ZoomNet/Resources/Meetings.cs @@ -70,10 +70,7 @@ public Task CreateInstantMeetingAsync( string templateId = null, CancellationToken cancellationToken = default) { - if (generatePassword && !string.IsNullOrEmpty(password)) - { - throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); - } + if (generatePassword && !string.IsNullOrEmpty(password)) throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); var data = new JsonObject { @@ -110,10 +107,7 @@ public Task CreateScheduledMeetingAsync( bool preSchedule = false, CancellationToken cancellationToken = default) { - if (generatePassword && !string.IsNullOrEmpty(password)) - { - throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); - } + if (generatePassword && !string.IsNullOrEmpty(password)) throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); var data = new JsonObject { @@ -155,10 +149,7 @@ public Task CreateRecurringMeetingAsync( bool preSchedule = false, CancellationToken cancellationToken = default) { - if (generatePassword && !string.IsNullOrEmpty(password)) - { - throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); - } + if (generatePassword && !string.IsNullOrEmpty(password)) throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); if (preSchedule && recurrence != null) throw new ArgumentException($"{nameof(preSchedule)} can be set to true only when {nameof(recurrence)} is null.", nameof(preSchedule)); var data = new JsonObject From 8223ba7216bc13da777bb4b3ad63be6834c119c8 Mon Sep 17 00:00:00 2001 From: Jericho Date: Tue, 29 Oct 2024 14:57:12 -0400 Subject: [PATCH 08/11] Move the generatePassword towards the end of the method signature. I am hoping this will reduce the likelihood of developers getting "cannot convert from ... to ..." and if they do, it should increase the likelihood it will be "cannot convert from 'System.Threading.CancellationToken' to 'bool'" --- Source/ZoomNet.IntegrationTests/Tests/Meetings.cs | 9 ++++----- Source/ZoomNet/Resources/IMeetings.cs | 12 ++++++------ Source/ZoomNet/Resources/Meetings.cs | 14 +++++++------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs index 1a162900..7ea128a7 100644 --- a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs +++ b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs @@ -67,7 +67,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie }; // Instant meeting - var newInstantMeeting = await client.Meetings.CreateInstantMeetingAsync(myUser.Id, "ZoomNet Integration Testing: instant meeting", "The agenda", null, true, settings, trackingFields, null, cancellationToken).ConfigureAwait(false); + var newInstantMeeting = await client.Meetings.CreateInstantMeetingAsync(myUser.Id, "ZoomNet Integration Testing: instant meeting", "The agenda", null, settings, trackingFields, null, true, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Instant meeting {newInstantMeeting.Id} created").ConfigureAwait(false); var instantMeeting = (InstantMeeting)await client.Meetings.GetAsync(newInstantMeeting.Id, null, cancellationToken).ConfigureAwait(false); @@ -85,7 +85,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie // Scheduled meeting var start = DateTime.UtcNow.AddMonths(1); var duration = 30; - var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, null, true, settings, trackingFields, null, false, cancellationToken).ConfigureAwait(false); + var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, null, settings, trackingFields, null, true, false, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Scheduled meeting {newScheduledMeeting.Id} created").ConfigureAwait(false); var updatedSettings = new MeetingSettings() { Audio = AudioType.Voip }; @@ -95,7 +95,6 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie var scheduledMeeting = (ScheduledMeeting)await client.Meetings.GetAsync(newScheduledMeeting.Id, null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Scheduled meeting {scheduledMeeting.Id} retrieved").ConfigureAwait(false); - if (myUser.Type == UserType.Licensed) { var requiredFields = new[] @@ -247,7 +246,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie WeeklyDays = new[] { DayOfWeek.Monday, DayOfWeek.Friday }, Type = RecurrenceType.Weekly }; - var newRecurringMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting", "The agenda", start, duration, recurrenceInfo, TimeZones.UTC, "p@ss!w0rd", false, settings, trackingFields, null, false, cancellationToken).ConfigureAwait(false); + var newRecurringMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting", "The agenda", start, duration, recurrenceInfo, TimeZones.UTC, "p@ss!w0rd", settings, trackingFields, null, false, false, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Recurring meeting {newRecurringMeeting.Id} created").ConfigureAwait(false); await client.Meetings.UpdateRecurringMeetingAsync(newRecurringMeeting.Id, topic: "ZoomNet Integration Testing: UPDATED recurring meeting", cancellationToken: cancellationToken).ConfigureAwait(false); @@ -267,7 +266,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie await log.WriteLineAsync($"Recurring meeting {newRecurringMeeting.Id} deleted").ConfigureAwait(false); // Recurring meeting with no fixed time - var newRecurringNoFixTimeMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting with no fixed time", "The agenda", start, duration, null, TimeZones.UTC, "p@ss!w0rd", false, settings, null, null, false, cancellationToken).ConfigureAwait(false); + var newRecurringNoFixTimeMeeting = await client.Meetings.CreateRecurringMeetingAsync(myUser.Id, "ZoomNet Integration Testing: recurring meeting with no fixed time", "The agenda", start, duration, null, TimeZones.UTC, "p@ss!w0rd", settings, null, null, false, false, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Recurring meeting with no fixed time {newRecurringNoFixTimeMeeting.Id} created").ConfigureAwait(false); await client.Meetings.DeleteAsync(newRecurringNoFixTimeMeeting.Id, null, false, false, cancellationToken).ConfigureAwait(false); diff --git a/Source/ZoomNet/Resources/IMeetings.cs b/Source/ZoomNet/Resources/IMeetings.cs index 78964bc5..7ca520c7 100644 --- a/Source/ZoomNet/Resources/IMeetings.cs +++ b/Source/ZoomNet/Resources/IMeetings.cs @@ -54,16 +54,16 @@ public interface IMeetings /// Meeting topic. /// Meeting description. /// Password to join the meeting. Password may only contain the following characters: [a-z A-Z 0-9 @ - _ *]. Max of 10 characters. - /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Meeting settings. /// Tracking fields. /// Template Identifer. + /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// The cancellation token. /// /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateInstantMeetingAsync(string userId, string topic, string agenda, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, CancellationToken cancellationToken = default); + Task CreateInstantMeetingAsync(string userId, string topic, string agenda, string password = null, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, bool generatePassword = false, CancellationToken cancellationToken = default); /// /// Create a scheduled meeting for a user. @@ -75,17 +75,17 @@ public interface IMeetings /// Meeting duration (minutes). /// The time zone for start time. /// Password to join the meeting. Password may only contain the following characters: [a-z A-Z 0-9 @ - _ *]. Max of 10 characters. - /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Meeting settings. /// Tracking fields. /// Template Identifer. + /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Whether to create a prescheduled meeting via the GSuite app. /// The cancellation token. /// /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateScheduledMeetingAsync(string userId, string topic, string agenda, DateTime start, int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, bool preSchedule = false, CancellationToken cancellationToken = default); + Task CreateScheduledMeetingAsync(string userId, string topic, string agenda, DateTime start, int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, bool generatePassword = false, bool preSchedule = false, CancellationToken cancellationToken = default); /// /// Create a recurring meeting for a user. @@ -98,17 +98,17 @@ public interface IMeetings /// Recurrence information. /// The time zone for start time. /// Password to join the meeting. Password may only contain the following characters: [a-z A-Z 0-9 @ - _ *]. Max of 10 characters. - /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Meeting settings. /// Tracking fields. /// Template Identifer. + /// Whether to generate a default passcode using the user's settings. If this value is true and the user has the PMI setting enabled with a passcode, then the user's meetings will use the PMI passcode. /// Whether to create a prescheduled meeting via the GSuite app. This only applies to recurring meetings with no fixed time. /// The cancellation token. /// /// The new meeting. /// /// Thrown when an exception occured while creating the meeting. - Task CreateRecurringMeetingAsync(string userId, string topic, string agenda, DateTime? start, int duration, RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, bool preSchedule = false, CancellationToken cancellationToken = default); + Task CreateRecurringMeetingAsync(string userId, string topic, string agenda, DateTime? start, int duration, RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, bool generatePassword = false, bool preSchedule = false, CancellationToken cancellationToken = default); /// /// Update the details of a meeting occurrence. diff --git a/Source/ZoomNet/Resources/Meetings.cs b/Source/ZoomNet/Resources/Meetings.cs index 75bac44e..78087b86 100644 --- a/Source/ZoomNet/Resources/Meetings.cs +++ b/Source/ZoomNet/Resources/Meetings.cs @@ -64,10 +64,10 @@ public Task CreateInstantMeetingAsync( string topic, string agenda, string password = null, - bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, + bool generatePassword = false, CancellationToken cancellationToken = default) { if (generatePassword && !string.IsNullOrEmpty(password)) throw new ArgumentException($"{nameof(generatePassword)} and {nameof(password)} are mutually exclusive. Either specify a password and set {nameof(generatePassword)} to false or set {nameof(password)} to null and set {nameof(generatePassword)} to true."); @@ -77,11 +77,11 @@ public Task CreateInstantMeetingAsync( { "type", MeetingType.Instant }, { "topic", topic }, { "password", password }, - { "default_password", generatePassword }, { "agenda", agenda }, { "settings", settings }, { "tracking_fields", trackingFields?.Select(tf => new JsonObject { { "field", tf.Key }, { "value", tf.Value } }).ToArray() }, - { "template_id", templateId } + { "template_id", templateId }, + { "default_password", generatePassword }, }; return _client @@ -100,10 +100,10 @@ public Task CreateScheduledMeetingAsync( int duration, TimeZones? timeZone = TimeZones.UTC, string password = null, - bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, + bool generatePassword = false, bool preSchedule = false, CancellationToken cancellationToken = default) { @@ -114,7 +114,6 @@ public Task CreateScheduledMeetingAsync( { "type", MeetingType.Scheduled }, { "topic", topic }, { "password", password }, - { "default_password", generatePassword }, { "agenda", agenda }, { "start_time", start.ToZoomFormat(timeZone) }, { "duration", duration }, @@ -122,6 +121,7 @@ public Task CreateScheduledMeetingAsync( { "settings", settings }, { "tracking_fields", trackingFields?.Select(tf => new JsonObject { { "field", tf.Key }, { "value", tf.Value } }).ToArray() }, { "template_id", templateId }, + { "default_password", generatePassword }, { "pre_schedule", preSchedule }, }; @@ -142,10 +142,10 @@ public Task CreateRecurringMeetingAsync( RecurrenceInfo recurrence, TimeZones? timeZone = TimeZones.UTC, string password = null, - bool generatePassword = false, MeetingSettings settings = null, IDictionary trackingFields = null, string templateId = null, + bool generatePassword = false, bool preSchedule = false, CancellationToken cancellationToken = default) { @@ -157,7 +157,6 @@ public Task CreateRecurringMeetingAsync( { "type", recurrence == null ? MeetingType.RecurringNoFixedTime : MeetingType.RecurringFixedTime }, { "topic", topic }, { "password", password }, - { "default_password", generatePassword }, { "agenda", agenda }, { "start_time", start.ToZoomFormat(timeZone) }, { "duration", duration }, @@ -166,6 +165,7 @@ public Task CreateRecurringMeetingAsync( { "settings", settings }, { "tracking_fields", trackingFields?.Select(tf => new JsonObject { { "field", tf.Key }, { "value", tf.Value } }).ToArray() }, { "template_id", templateId }, + { "default_password", generatePassword }, { "pre_schedule", preSchedule }, }; From e1b9958fe36f9b4a6becea80357e416b6f802564 Mon Sep 17 00:00:00 2001 From: Jericho Date: Fri, 1 Nov 2024 10:35:04 -0400 Subject: [PATCH 09/11] XML comment mus end with a period --- Source/ZoomNet/Models/MeetingListType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ZoomNet/Models/MeetingListType.cs b/Source/ZoomNet/Models/MeetingListType.cs index 5db5c972..a4ed2492 100644 --- a/Source/ZoomNet/Models/MeetingListType.cs +++ b/Source/ZoomNet/Models/MeetingListType.cs @@ -28,7 +28,7 @@ public enum MeetingListType /// /// All upcoming meetings, including live meetings. /// - /// What is the distinction between "upcoming" and "upcoming_meetings??? + /// I don't know what the distinction between "upcoming" and "upcoming_meetings is. [EnumMember(Value = "upcoming_meetings")] UpcomingMeetings, From f4939111793c408e42654e2a4ac5d35f3d461883 Mon Sep 17 00:00:00 2001 From: Jericho Date: Fri, 1 Nov 2024 10:35:43 -0400 Subject: [PATCH 10/11] Fix integration test --- Source/ZoomNet.IntegrationTests/Tests/Meetings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs index 7ea128a7..211c0903 100644 --- a/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs +++ b/Source/ZoomNet.IntegrationTests/Tests/Meetings.cs @@ -85,7 +85,7 @@ public async Task RunAsync(User myUser, string[] myPermissions, IZoomClient clie // Scheduled meeting var start = DateTime.UtcNow.AddMonths(1); var duration = 30; - var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, null, settings, trackingFields, null, true, false, cancellationToken).ConfigureAwait(false); + var newScheduledMeeting = await client.Meetings.CreateScheduledMeetingAsync(myUser.Id, "ZoomNet Integration Testing: scheduled meeting", "The agenda", start, duration, TimeZones.UTC, "pass@word!", settings, trackingFields, null, true, false, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"Scheduled meeting {newScheduledMeeting.Id} created").ConfigureAwait(false); var updatedSettings = new MeetingSettings() { Audio = AudioType.Voip }; From ed1351154c91b0fae6aa4036a92a3d16268eb1e4 Mon Sep 17 00:00:00 2001 From: Jericho Date: Fri, 1 Nov 2024 10:36:56 -0400 Subject: [PATCH 11/11] Refresh build script --- build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cake b/build.cake index 71596964..f2ca8ae3 100644 --- a/build.cake +++ b/build.cake @@ -1,5 +1,5 @@ // Install tools. -#tool dotnet:?package=GitVersion.Tool&version=6.0.3 +#tool dotnet:?package=GitVersion.Tool&version=6.0.4 #tool dotnet:?package=coveralls.net&version=4.0.1 #tool nuget:https://f.feedz.io/jericho/jericho/nuget/?package=GitReleaseManager&version=0.17.0-collaborators0008 #tool nuget:?package=ReportGenerator&version=5.3.11