• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Jericho / ZoomNet / 764

07 Aug 2024 03:41PM UTC coverage: 20.254% (+0.6%) from 19.667%
764

push

appveyor

Jericho
Merge branch 'release/0.80.0'

637 of 3145 relevant lines covered (20.25%)

11.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.04
/Source/ZoomNet/ZoomClient.cs
1
using Microsoft.Extensions.Logging;
2
using Microsoft.Extensions.Logging.Abstractions;
3
using Pathoschild.Http.Client;
4
using Pathoschild.Http.Client.Extensibility;
5
using System;
6
using System.Net;
7
using System.Net.Http;
8
using System.Reflection;
9
using ZoomNet.Json;
10
using ZoomNet.Resources;
11
using ZoomNet.Utilities;
12

13
namespace ZoomNet
14
{
15
        /// <summary>
16
        /// REST client for interacting with Zoom's API.
17
        /// </summary>
18
        /// <remarks>
19
        /// Don't be fooled by the fact that this class implements the IDisposable interface: it is not meant to be short-lived and instantiated with every request.
20
        /// It is meant to be long-lived and re-used throughout the life of an application.
21
        /// The reason is: we use Microsoft's HttpClient to dispatch requests which itself is meant to be long-lived and re-used.
22
        /// Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads and will result in SocketException errors.
23
        ///
24
        /// See <a href="https://github.com/Jericho/ZoomNet/issues/35">this discussion</a> for more information about managing the lifetime of your client instance.
25
        /// </remarks>
26
        public class ZoomClient : IZoomClient, IDisposable
27
        {
28
                #region FIELDS
29

30
                private const string ZOOM_V2_BASE_URI = "https://api.zoom.us/v2";
31

32
                private static string _version;
33

34
                private readonly bool _mustDisposeHttpClient;
35
                private readonly ZoomClientOptions _options;
36
                private readonly ILogger _logger;
37

38
                private HttpClient _httpClient;
39
                private Pathoschild.Http.Client.IClient _fluentClient;
40

41
                #endregion
42

43
                #region PROPERTIES
44

45
                /// <summary>
46
                /// Gets the Version.
47
                /// </summary>
48
                /// <value>
49
                /// The version.
50
                /// </value>
51
                public static string Version
52
                {
53
                        get
54
                        {
55
                                if (string.IsNullOrEmpty(_version))
4✔
56
                                {
57
                                        _version = typeof(ZoomClient).GetTypeInfo().Assembly.GetName().Version.ToString(3);
1✔
58
#if DEBUG
59
                                        _version = "DEBUG";
60
#endif
61
                                }
62

63
                                return _version;
4✔
64
                        }
65
                }
66

67
                /// <summary>
68
                /// Gets the resource which allows you to manage sub accounts.
69
                /// </summary>
70
                /// <value>
71
                /// The accounts resource.
72
                /// </value>
73
                public IAccounts Accounts { get; private set; }
74

75
                /// <summary>
76
                /// Gets the resource which allows you to manage chat channels, messages, etc.
77
                /// </summary>
78
                /// <value>
79
                /// The chat resource.
80
                /// </value>
81
                public IChat Chat { get; private set; }
82

83
                /// <summary>
84
                /// Gets the resource which allows you to manage cloud recordings.
85
                /// </summary>
86
                /// <value>
87
                /// The recordings resource.
88
                /// </value>
89
                public ICloudRecordings CloudRecordings { get; private set; }
90

91
                /// <summary>
92
                /// Gets the resource which allows you to manage contacts.
93
                /// </summary>
94
                /// <value>
95
                /// The contacts resource.
96
                /// </value>
97
                public IContacts Contacts { get; private set; }
98

99
                /// <summary>
100
                /// Gets the resource which allows you to notify Zoom that you comply with the policy which requires
101
                /// you to handle user's data in accordance to the user's preference after the user uninstalls your app.
102
                /// </summary>
103
                /// <value>
104
                /// The data compliance resource.
105
                /// </value>
106
                [Obsolete("The Data Compliance API is deprecated")]
107
                public IDataCompliance DataCompliance { get; private set; }
108

109
                /// <summary>
110
                /// Gets the resource which allows you to manage meetings.
111
                /// </summary>
112
                /// <value>
113
                /// The meetings resource.
114
                /// </value>
115
                public IMeetings Meetings { get; private set; }
116

117
                /// <summary>
118
                /// Gets the resource which allows you to manage meetings that occured in the past.
119
                /// </summary>
120
                /// <value>
121
                /// The past meetings resource.
122
                /// </value>
123
                public IPastMeetings PastMeetings { get; private set; }
124

125
                /// <summary>
126
                /// Gets the resource which allows you to manage webinars that occured in the past.
127
                /// </summary>
128
                /// <value>
129
                /// The past webinars resource.
130
                /// </value>
131
                public IPastWebinars PastWebinars { get; private set; }
132

133
                /// <summary>
134
                /// Gets the resource which allows you to manage roles.
135
                /// </summary>
136
                /// <value>
137
                /// The roles resource.
138
                /// </value>
139
                public IRoles Roles { get; private set; }
140

141
                /// <summary>
142
                /// Gets the resource which allows you to manage users.
143
                /// </summary>
144
                /// <value>
145
                /// The users resource.
146
                /// </value>
147
                public IUsers Users { get; private set; }
148

149
                /// <summary>
150
                /// Gets the resource which allows you to manage webinars.
151
                /// </summary>
152
                /// <value>
153
                /// The webinars resource.
154
                /// </value>
155
                public IWebinars Webinars { get; private set; }
156

157
                /// <summary>
158
                /// Gets the resource which allows you to view metrics.
159
                /// </summary>
160
                public IDashboards Dashboards { get; private set; }
161

162
                /// <summary>
163
                /// Gets the resource which allows you to view reports.
164
                /// </summary>
165
                public IReports Reports { get; private set; }
166

167
                /// <summary>
168
                /// Gets the resource which allows you to manage call logs.
169
                /// </summary>
170
                public ICallLogs CallLogs { get; private set; }
171

172
                /// <summary>
173
                /// Gets the resource which allows you to manage chatbot messages.
174
                /// </summary>
175
                public IChatbot Chatbot { get; private set; }
176

177
                /// <inheritdoc/>
178
                public IPhone Phone { get; private set; }
179

180
                /// <inheritdoc/>
181
                public ISms Sms { get; private set; }
182

183
                #endregion
184

185
                #region CTOR
186

187
                /// <summary>
188
                /// Initializes a new instance of the <see cref="ZoomClient"/> class.
189
                /// </summary>
190
                /// <param name="connectionInfo">Connection information.</param>
191
                /// <param name="options">Options for the Zoom client.</param>
192
                /// <param name="logger">Logger.</param>
193
                public ZoomClient(IConnectionInfo connectionInfo, ZoomClientOptions options = null, ILogger logger = null)
194
                        : this(connectionInfo, new HttpClient(), true, options, logger)
1✔
195
                {
196
                }
×
197

198
                /// <summary>
199
                /// Initializes a new instance of the <see cref="ZoomClient"/> class with a specific proxy.
200
                /// </summary>
201
                /// <param name="connectionInfo">Connection information.</param>
202
                /// <param name="proxy">Allows you to specify a proxy.</param>
203
                /// <param name="options">Options for the Zoom client.</param>
204
                /// <param name="logger">Logger.</param>
205
                public ZoomClient(IConnectionInfo connectionInfo, IWebProxy proxy, ZoomClientOptions options = null, ILogger logger = null)
206
                        : this(connectionInfo, new HttpClient(new HttpClientHandler { Proxy = proxy, UseProxy = proxy != null }), true, options, logger)
1✔
207
                {
208
                }
1✔
209

210
                /// <summary>
211
                /// Initializes a new instance of the <see cref="ZoomClient"/> class with a specific handler.
212
                /// </summary>
213
                /// <param name="connectionInfo">Connection information.</param>
214
                /// <param name="handler">TThe HTTP handler stack to use for sending requests.</param>
215
                /// <param name="options">Options for the Zoom client.</param>
216
                /// <param name="logger">Logger.</param>
217
                public ZoomClient(IConnectionInfo connectionInfo, HttpMessageHandler handler, ZoomClientOptions options = null, ILogger logger = null)
218
                        : this(connectionInfo, new HttpClient(handler), true, options, logger)
×
219
                {
220
                }
×
221

222
                /// <summary>
223
                /// Initializes a new instance of the <see cref="ZoomClient"/> class with a specific http client.
224
                /// </summary>
225
                /// <param name="connectionInfo">Connection information.</param>
226
                /// <param name="httpClient">Allows you to inject your own HttpClient. This is useful, for example, to setup the HtppClient with a proxy.</param>
227
                /// <param name="options">Options for the Zoom client.</param>
228
                /// <param name="logger">Logger.</param>
229
                public ZoomClient(IConnectionInfo connectionInfo, HttpClient httpClient, ZoomClientOptions options = null, ILogger logger = null)
230
                        : this(connectionInfo, httpClient, false, options, logger)
1✔
231
                {
232
                }
1✔
233

234
                private ZoomClient(IConnectionInfo connectionInfo, HttpClient httpClient, bool disposeClient, ZoomClientOptions options, ILogger logger = null)
235
                {
236
                        if (connectionInfo == null) throw new ArgumentNullException(nameof(connectionInfo));
3✔
237

238
                        _mustDisposeHttpClient = disposeClient;
3✔
239
                        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
3✔
240
                        _options = options ?? new();
3✔
241
                        _logger = logger ?? NullLogger.Instance;
3✔
242
                        _fluentClient = new FluentClient(new Uri(ZOOM_V2_BASE_URI), httpClient)
3✔
243
                                .SetUserAgent($"ZoomNet/{Version} (+https://github.com/Jericho/ZoomNet)");
3✔
244

245
                        _fluentClient.Filters.Remove<DefaultErrorFilter>();
3✔
246

247
                        // Remove all the built-in formatters and replace them with our custom JSON formatter
248
                        _fluentClient.Formatters.Clear();
3✔
249
                        _fluentClient.Formatters.Add(new JsonFormatter());
3✔
250

251
                        // Order is important: the token handler (either JWT or OAuth) must be first, followed by DiagnosticHandler and then by ErrorHandler.
252
                        if (connectionInfo is JwtConnectionInfo jwtConnectionInfo)
3✔
253
                        {
254
                                var tokenHandler = new JwtTokenHandler(jwtConnectionInfo);
2✔
255
                                _fluentClient.Filters.Add(tokenHandler);
1✔
256
                                _fluentClient.SetRequestCoordinator(new ZoomRetryCoordinator(new Http429RetryStrategy(), tokenHandler));
1✔
257
                        }
258
                        else if (connectionInfo is OAuthConnectionInfo oAuthConnectionInfo)
1✔
259
                        {
260
                                var tokenHandler = new OAuthTokenHandler(oAuthConnectionInfo, httpClient);
1✔
261
                                _fluentClient.Filters.Add(tokenHandler);
1✔
262
                                _fluentClient.SetRequestCoordinator(new ZoomRetryCoordinator(new Http429RetryStrategy(), tokenHandler));
1✔
263
                        }
264
                        else
265
                        {
266
                                throw new ZoomException($"{connectionInfo.GetType()} is an unknown connection type", null, null, null, null);
×
267
                        }
268

269
                        // The list of filters must be kept in sync with the filters in Utils.GetFluentClient in the unit testing project.
270
                        _fluentClient.Filters.Add(new DiagnosticHandler(_options.LogLevelSuccessfulCalls, _options.LogLevelFailedCalls, _logger));
2✔
271
                        _fluentClient.Filters.Add(new ZoomErrorHandler());
2✔
272

273
                        Accounts = new Accounts(_fluentClient);
2✔
274
                        Chat = new Chat(_fluentClient);
2✔
275
                        CloudRecordings = new CloudRecordings(_fluentClient);
2✔
276
                        Contacts = new Contacts(_fluentClient);
2✔
277
                        DataCompliance = new DataCompliance(_fluentClient);
2✔
278
                        Meetings = new Meetings(_fluentClient);
2✔
279
                        PastMeetings = new PastMeetings(_fluentClient);
2✔
280
                        PastWebinars = new PastWebinars(_fluentClient);
2✔
281
                        Roles = new Roles(_fluentClient);
2✔
282
                        Users = new Users(_fluentClient);
2✔
283
                        Webinars = new Webinars(_fluentClient);
2✔
284
                        Dashboards = new Dashboards(_fluentClient);
2✔
285
                        Reports = new Reports(_fluentClient);
2✔
286
                        CallLogs = new CallLogs(_fluentClient);
2✔
287
                        Chatbot = new Chatbot(_fluentClient);
2✔
288
                        Phone = new Phone(_fluentClient);
2✔
289
                        Sms = new Sms(_fluentClient);
2✔
290
                }
2✔
291

292
                /// <summary>
293
                /// Finalizes an instance of the <see cref="ZoomClient"/> class.
294
                /// </summary>
295
                ~ZoomClient()
296
                {
297
                        // The object went out of scope and finalized is called.
298
                        // Call 'Dispose' to release unmanaged resources
299
                        // Managed resources will be released when GC runs the next time.
300
                        Dispose(false);
×
301
                }
×
302

303
                #endregion
304

305
                #region PUBLIC METHODS
306

307
                /// <summary>
308
                /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
309
                /// </summary>
310
                public void Dispose()
311
                {
312
                        // Call 'Dispose' to release resources
313
                        Dispose(true);
1✔
314

315
                        // Tell the GC that we have done the cleanup and there is nothing left for the Finalizer to do
316
                        GC.SuppressFinalize(this);
1✔
317
                }
1✔
318

319
                /// <summary>
320
                /// Releases unmanaged and - optionally - managed resources.
321
                /// </summary>
322
                /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
323
                protected virtual void Dispose(bool disposing)
324
                {
325
                        if (disposing)
1✔
326
                        {
327
                                ReleaseManagedResources();
1✔
328
                        }
329
                        else
330
                        {
331
                                // The object went out of scope and the Finalizer has been called.
332
                                // The GC will take care of releasing managed resources, therefore there is nothing to do here.
333
                        }
334

335
                        ReleaseUnmanagedResources();
1✔
336
                }
1✔
337

338
                #endregion
339

340
                #region PRIVATE METHODS
341

342
                private void ReleaseManagedResources()
343
                {
344
                        if (_fluentClient != null)
1✔
345
                        {
346
                                _fluentClient.Dispose();
1✔
347
                                _fluentClient = null;
1✔
348
                        }
349

350
                        if (_httpClient != null && _mustDisposeHttpClient)
1✔
351
                        {
352
                                _httpClient.Dispose();
1✔
353
                                _httpClient = null;
1✔
354
                        }
355
                }
1✔
356

357
                private void ReleaseUnmanagedResources()
358
                {
359
                        // We do not hold references to unmanaged resources
360
                }
1✔
361

362
                #endregion
363
        }
364
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc