Skip to content

Commit

Permalink
Add external contacts endpoints (#385)
Browse files Browse the repository at this point in the history
* Add external contacts endpoints

* Remove extra string interpolation operator

* Rename new methods

---------

Co-authored-by: P. Gritsenko <[email protected]>
Co-authored-by: Jericho <[email protected]>
Co-authored-by: Ivan Pavlik <[email protected]>
  • Loading branch information
4 people authored Jan 13, 2025
1 parent df3987b commit 8def4c0
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 18 deletions.
5 changes: 5 additions & 0 deletions Source/ZoomNet/IZoomClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public interface IZoomClient
[Obsolete("The Data Compliance API is deprecated")]
IDataCompliance DataCompliance { get; }

/// <summary>
/// Gets the resource which allows you to handle Zoom phone external contacts.
/// </summary>
IExternalContacts ExternalContacts { get; }

/// <summary>
/// Gets the resource that allows you to manage groups.
/// </summary>
Expand Down
6 changes: 4 additions & 2 deletions Source/ZoomNet/Json/ZoomNetJsonSerializerContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ namespace ZoomNet.Json
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.CustomHoursChildSubsettings), TypeInfoPropertyName = "CallHandlingSettingsCustomHoursChildSubsettings")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.CustomHoursSubsettings), TypeInfoPropertyName = "CallHandlingSettingsCustomHoursSubsettings")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.CustomHoursType), TypeInfoPropertyName = "CallHandlingSettingsCustomHoursType")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.ExternalContact), TypeInfoPropertyName = "CallHandlingSettingsExternalContact")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.HolidaySubsettings), TypeInfoPropertyName = "CallHandlingSettingsHolidaySubsettings")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.RingModeType), TypeInfoPropertyName = "CallHandlingSettingsRingModeType")]
[JsonSerializable(typeof(ZoomNet.Models.CallingPlan))]
Expand Down Expand Up @@ -113,6 +112,8 @@ namespace ZoomNet.Json
[JsonSerializable(typeof(ZoomNet.Models.EmailNotificationUserSettings))]
[JsonSerializable(typeof(ZoomNet.Models.EmergencyAddress))]
[JsonSerializable(typeof(ZoomNet.Models.EncryptionType))]
[JsonSerializable(typeof(ZoomNet.Models.ExternalContact))]
[JsonSerializable(typeof(ZoomNet.Models.ExternalContactDetails))]
[JsonSerializable(typeof(ZoomNet.Models.FeatureUserSettings))]
[JsonSerializable(typeof(ZoomNet.Models.ImMetric))]
[JsonSerializable(typeof(ZoomNet.Models.InstantMeeting))]
Expand Down Expand Up @@ -353,7 +354,6 @@ namespace ZoomNet.Json
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.CustomHoursChildSubsettings[]), TypeInfoPropertyName = "CallHandlingSettingsCustomHoursChildSubsettingsArray")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.CustomHoursSubsettings[]), TypeInfoPropertyName = "CallHandlingSettingsCustomHoursSubsettingsArray")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.CustomHoursType[]), TypeInfoPropertyName = "CallHandlingSettingsCustomHoursTypeArray")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.ExternalContact[]), TypeInfoPropertyName = "CallHandlingSettingsExternalContactArray")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.HolidaySubsettings[]), TypeInfoPropertyName = "CallHandlingSettingsHolidaySubsettingsArray")]
[JsonSerializable(typeof(ZoomNet.Models.CallHandlingSettings.RingModeType[]), TypeInfoPropertyName = "CallHandlingSettingsRingModeTypeArray")]
[JsonSerializable(typeof(ZoomNet.Models.CallingPlan[]))]
Expand Down Expand Up @@ -432,6 +432,8 @@ namespace ZoomNet.Json
[JsonSerializable(typeof(ZoomNet.Models.EmailNotificationUserSettings[]))]
[JsonSerializable(typeof(ZoomNet.Models.EmergencyAddress[]))]
[JsonSerializable(typeof(ZoomNet.Models.EncryptionType[]))]
[JsonSerializable(typeof(ZoomNet.Models.ExternalContact[]))]
[JsonSerializable(typeof(ZoomNet.Models.ExternalContactDetails[]))]
[JsonSerializable(typeof(ZoomNet.Models.FeatureUserSettings[]))]
[JsonSerializable(typeof(ZoomNet.Models.ImMetric[]))]
[JsonSerializable(typeof(ZoomNet.Models.InstantMeeting[]))]
Expand Down
16 changes: 0 additions & 16 deletions Source/ZoomNet/Models/CallHandlingSettings/ExternalContact.cs

This file was deleted.

23 changes: 23 additions & 0 deletions Source/ZoomNet/Models/ExternalContact.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Text.Json.Serialization;

namespace ZoomNet.Models
{
/// <summary>
/// Zoom phone external contact model.
/// </summary>
public class ExternalContact
{
/// <summary>
/// Gets or sets the Zoom-generated external contact Id.
/// Don't set it on external contact creation, it will be generated automatically.
/// </summary>
[JsonPropertyName("external_contact_id")]
public string ExternalContactId { get; set; }

/// <summary>
/// Gets or sets the external contact's username or extension display name.
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; }
}
}
54 changes: 54 additions & 0 deletions Source/ZoomNet/Models/ExternalContactDetails.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace ZoomNet.Models
{
/// <summary>
/// Zoom phone external contact details model.
/// </summary>
public class ExternalContactDetails : ExternalContact
{
/// <summary>
/// Gets or sets the external contact's description.
/// </summary>
[JsonPropertyName("description")]
public string Description { get; set; }

/// <summary>
/// Gets or sets the external contact's email address.
/// </summary>
[JsonPropertyName("email")]
public string Email { get; set; }

/// <summary>
/// Gets or sets the external contact's extension number.
/// </summary>
[JsonPropertyName("extension_number")]
public string ExtensionNumber { get; set; }

/// <summary>
/// Gets or sets the customer-configured external contact ID.
/// If it is not set id will be generated automatically.
/// </summary>
[JsonPropertyName("id")]
public string Id { get; set; }

/// <summary>
/// Gets or sets the external contact's phone numbers.
/// </summary>
[JsonPropertyName("phone_numbers")]
public List<string> PhoneNumbers { get; set; }

/// <summary>
/// Gets or sets the external contact's SIP group, to define the call routing path. This is for customers that use SIP trunking.
/// </summary>
[JsonPropertyName("routing_path")]
public string RoutingPath { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to allow the automatic call recording.
/// </summary>
[JsonPropertyName("auto_call_recorded")]
public bool AutoCallRecorded { get; set; }
}
}
94 changes: 94 additions & 0 deletions Source/ZoomNet/Resources/ExternalContacts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Pathoschild.Http.Client;
using System;
using System.Threading;
using System.Threading.Tasks;
using ZoomNet;
using ZoomNet.Models;

namespace ZoomNet.Resources
{
/// <inheritdoc/>
public class ExternalContacts : IExternalContacts
{
private readonly IClient _client;

/// <summary>
/// Initializes a new instance of the <see cref="ExternalContacts" /> class.
/// </summary>
/// <param name="client">The HTTP client.</param>
internal ExternalContacts(IClient client)
{
_client = client;
}

/// <inheritdoc/>
public Task<PaginatedResponseWithToken<ExternalContactDetails>> GetAllAsync(int pageSize = 30, string nextPageToken = null, CancellationToken cancellationToken = default)
{
if (pageSize < 1 || pageSize > 300)
{
throw new ArgumentOutOfRangeException(nameof(pageSize), "Page size must be between 1 and 300");
}

return _client
.GetAsync("phone/external_contacts")
.WithArgument("page_size", pageSize)
.WithArgument("next_page_token", nextPageToken)
.WithCancellationToken(cancellationToken)
.AsPaginatedResponseWithToken<ExternalContactDetails>("external_contacts");
}

/// <inheritdoc/>
public Task<ExternalContactDetails> GetDetailsAsync(string externalContactId, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(externalContactId))
{
throw new ArgumentException(nameof(externalContactId), "External contact id is not set.");
}

return _client
.GetAsync($"phone/external_contacts/{externalContactId}")
.WithCancellationToken(cancellationToken)
.AsObject<ExternalContactDetails>();
}

/// <inheritdoc/>
public Task<ExternalContact> AddAsync(ExternalContactDetails externalContact, CancellationToken cancellationToken = default)
{
return _client
.PostAsync("phone/external_contacts")
.WithJsonBody(externalContact)
.WithCancellationToken(cancellationToken)
.AsObject<ExternalContact>();
}

/// <inheritdoc/>
public Task DeleteAsync(string externalContactId, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(externalContactId))
{
throw new ArgumentException(nameof(externalContactId), "External contact id is not set.");
}

return _client
.DeleteAsync($"phone/external_contacts/{externalContactId}")
.WithCancellationToken(cancellationToken)
.AsMessage();
}

/// <inheritdoc/>
public Task UpdateAsync(
ExternalContactDetails externalContact, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(externalContact.ExternalContactId))
{
throw new ArgumentException(nameof(externalContact.ExternalContactId), "External contact id is not set.");
}

return _client
.PatchAsync($"phone/external_contacts/{externalContact.ExternalContactId}")
.WithJsonBody(externalContact)
.WithCancellationToken(cancellationToken)
.AsMessage();
}
}
}
69 changes: 69 additions & 0 deletions Source/ZoomNet/Resources/IExternalContacts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System.Threading;
using System.Threading.Tasks;
using ZoomNet.Models;

namespace ZoomNet.Resources
{
/// <summary>
/// Allows you to access Zoom Phone API endpoints responsible for setting and retrieving data of external contacts.
/// </summary>
/// <remarks>
/// See <a href="https://developers.zoom.us/docs/api/rest/reference/phone/methods/#tag/External-Contacts">
/// Zoom API documentation</a> for more information.
/// </remarks>
public interface IExternalContacts
{
/// <summary>
/// Retrieves a list of all of an account's external contacts.
/// </summary>
/// <param name="pageSize">The number of records returned from a single API call. Default is 30.</param>
/// <param name="nextPageToken">
/// The next page token paginates through a large set of results.
/// A next page token is returned whenever the set of available results exceeds the current page size.
/// </param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
/// <returns>
/// A task representing the asynchronous operation. The task result contains an array of external contacts in type of <see cref="ExternalContact"/>.
/// </returns>
Task<PaginatedResponseWithToken<ExternalContactDetails>> GetAllAsync(
int pageSize = 30,
string nextPageToken = null,
CancellationToken cancellationToken = default);

/// <summary>
/// Gets an external contact's information.
/// </summary>
/// <param name="externalContactId">The external contact id.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
/// <returns>A task representing the asynchronous operation. The task result contains external contact details.</returns>
Task<ExternalContactDetails> GetDetailsAsync(
string externalContactId, CancellationToken cancellationToken = default);

/// <summary>
/// Adds an external contact.
/// </summary>
/// <param name="externalContact">The external contact information.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
/// <returns>A task representing the asynchronous operation. The task result contains external contact details.</returns>
Task<ExternalContact> AddAsync(
ExternalContactDetails externalContact, CancellationToken cancellationToken = default);

/// <summary>
/// Removes an external contact.
/// </summary>
/// <param name="externalContactId">The external contact id.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
/// <returns>A task representing the asynchronous operation.</returns>
Task DeleteAsync(
string externalContactId, CancellationToken cancellationToken = default);

/// <summary>
/// Update an external contact information by <see cref="ExternalContact.ExternalContactId"/>.
/// </summary>
/// <param name="externalContact">External contact information.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
/// <returns>A task representing the asynchronous operation.</returns>
Task UpdateAsync(
ExternalContactDetails externalContact, CancellationToken cancellationToken = default);
}
}
4 changes: 4 additions & 0 deletions Source/ZoomNet/ZoomClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public static string Version
[Obsolete("The Data Compliance API is deprecated")]
public IDataCompliance DataCompliance { get; private set; }

/// <inheritdoc/>
public IExternalContacts ExternalContacts { get; private set; }

/// <inheritdoc/>
public IGroups Groups { get; private set; }

Expand Down Expand Up @@ -219,6 +222,7 @@ private ZoomClient(IConnectionInfo connectionInfo, HttpClient httpClient, bool d
Contacts = new Contacts(_fluentClient);
Dashboards = new Dashboards(_fluentClient);
DataCompliance = new DataCompliance(_fluentClient);
ExternalContacts = new ExternalContacts(_fluentClient);
Groups = new Groups(_fluentClient);
Meetings = new Meetings(_fluentClient);
PastMeetings = new PastMeetings(_fluentClient);
Expand Down

0 comments on commit 8def4c0

Please sign in to comment.