-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathIMattermostClient.cs
More file actions
474 lines (411 loc) · 21 KB
/
Copy pathIMattermostClient.cs
File metadata and controls
474 lines (411 loc) · 21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
using Mattermost.Constants;
using Mattermost.Enums;
using Mattermost.Events;
using Mattermost.Models;
using Mattermost.Models.Channels;
using Mattermost.Models.Dialogs;
using Mattermost.Models.Posts;
using Mattermost.Models.Responses;
using Mattermost.Models.Teams;
using Mattermost.Models.Users;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Mattermost
{
/// <summary>
/// Mattermost client interface.
/// </summary>
public interface IMattermostClient
{
/// <summary>
/// Specifies whether the client is connected to the server with WebSocket.
/// </summary>
bool IsConnected { get; }
/// <summary>
/// User information.
/// </summary>
User CurrentUserInfo { get; }
/// <summary>
/// Base server address.
/// </summary>
Uri ServerAddress { get; }
/// <summary>
/// Occurs when the WebSocket connection is successfully established.
/// </summary>
event EventHandler<ConnectionEventArgs>? OnConnected;
/// <summary>
/// Occurs when the WebSocket is disconnected, either by the client or the server.
/// </summary>
event EventHandler<DisconnectionEventArgs>? OnDisconnected;
/// <summary>
/// Event called in independent thread when new message received.
/// </summary>
event EventHandler<MessageEventArgs>? OnMessageReceived;
/// <summary>
/// Event callen in independent thread when log message created.
/// </summary>
event EventHandler<LogEventArgs>? OnLogMessage;
/// <summary>
/// Create receiver <see cref="Task"/> with websocket polling.
/// </summary>
/// <returns> Receiver task. </returns>
Task StartReceivingAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Stop receiving messages.
/// </summary>
Task StopReceivingAsync();
#region Posts
/// <summary>
/// Send message to specified channel using channel identifier.
/// </summary>
/// <param name="channelId"> Channel identifier. </param>
/// <param name="message"> Message text (Markdown supported). </param>
/// <param name="replyToPostId"> Reply to post (optional) </param>
/// <param name="priority"> Set message priority </param>
/// <param name="files"> Attach files to post. </param>
/// <param name="rawProps"> A general JSON property bag to attach to the post. </param>
/// <returns> Created post. </returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when message length exceed maximum limit of characters, see <see cref="MattermostApiLimits.MaxPostMessageLength"/>.</exception>
Task<Post> CreatePostWithRawPropsAsync(string channelId, string message = "", string replyToPostId = "",
MessagePriority priority = MessagePriority.Empty, IEnumerable<string>? files = null,
IDictionary<string, object>? rawProps = null);
/// <summary>
/// Send message to specified channel using channel identifier.
/// </summary>
/// <param name="channelId"> Channel identifier. </param>
/// <param name="message"> Message text (Markdown supported). </param>
/// <param name="replyToPostId"> Reply to post (optional) </param>
/// <param name="priority"> Set message priority </param>
/// <param name="files"> Attach files to post. </param>
/// <param name="props"> Props object to attach to the post. </param>
/// <returns> Created post. </returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when message length exceed maximum limit of characters, see <see cref="MattermostApiLimits.MaxPostMessageLength"/>.</exception>
Task<Post> CreatePostAsync(string channelId, string message = "", string replyToPostId = "",
MessagePriority priority = MessagePriority.Empty, IEnumerable<string>? files = null, PostProps? props = null);
/// <summary>
/// Get post by identifier.
/// </summary>
/// <param name="postId"> Post identifier. </param>
/// <returns> Post information. </returns>
Task<Post> GetPostAsync(string postId);
/// <summary>
/// Add current user's reaction to a post.
/// </summary>
/// <param name="postId"> Post identifier. </param>
/// <param name="emojiName"> Emoji name without surrounding colons. </param>
/// <returns> Created reaction information. </returns>
Task<Reaction> AddReactionAsync(string postId, string emojiName);
/// <summary>
/// Remove a reaction from a post.
/// </summary>
/// <param name="postId"> Post identifier. </param>
/// <param name="emojiName"> Emoji name without surrounding colons. </param>
/// <param name="userId"> User identifier. Defaults to current user. </param>
Task RemoveReactionAsync(string postId, string emojiName, string? userId = null);
/// <summary>
/// Get reactions for a post.
/// </summary>
/// <param name="postId"> Post identifier. </param>
/// <returns> Reactions for the post. </returns>
Task<IList<Reaction>> GetReactionsAsync(string postId);
/// <summary>
/// Pin a post to its channel.
/// </summary>
/// <param name="postId"> Post identifier. </param>
Task PinPostAsync(string postId);
/// <summary>
/// Unpin a post from its channel.
/// </summary>
/// <param name="postId"> Post identifier. </param>
Task UnpinPostAsync(string postId);
/// <summary>
/// Update message text for specified post identifier.
/// </summary>
/// <param name="postId"> Post identifier. </param>
/// <param name="newText"> New message text (Markdown supported). </param>
/// <param name="rawProps"> A general JSON property bag to attach to the post. </param>
/// <returns> Updated post. </returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when message length exceed maximum limit of characters, see <see cref="MattermostApiLimits.MaxPostMessageLength"/>.</exception>
Task<Post> UpdatePostWithRawPropsAsync(string postId, string newText, IDictionary<string, object>? rawProps = null);
/// <summary>
/// Update message text for specified post identifier.
/// </summary>
/// <param name="postId"> Post identifier. </param>
/// <param name="newText"> New message text (Markdown supported). </param>
/// <param name="props"> Props object to attach to the post. </param>
/// <returns> Updated post. </returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when message length exceed maximum limit of characters, see <see cref="MattermostApiLimits.MaxPostMessageLength"/>.</exception>
Task<Post> UpdatePostAsync(string postId, string newText, PostProps? props = null);
/// <summary>
/// Delete post with specified post identifier.
/// </summary>
/// <param name="postId"> Post identifier. </param>
/// <returns> True if deleted, otherwise false. </returns>
Task DeletePostAsync(string postId);
/// <summary>
/// Get a page of posts in a channel.
/// </summary>
/// <param name="channelId"> Channel identifier. </param>
/// <param name="page"> The page to select. </param>
/// <param name="perPage"> The number of posts per page. </param>
/// <param name="beforePostId"> A post id to select the posts that came before this one. </param>
/// <param name="afterPostId"> A post id to select the posts that came after this one. </param>
/// <param name="includeDeleted"> Whether to include deleted posts or not. Must have system admin permissions. </param>
/// <param name="since"> Time to select modified posts after. </param>
/// <returns> ChannelPosts object with posts. </returns>
public Task<ChannelPostsResponse> GetChannelPostsAsync(string channelId, int page = 0,
int perPage = 60, string? beforePostId = null, string? afterPostId = null,
bool includeDeleted = false, DateTime? since = null);
/// <summary>
/// Get posts related to specified post identifier in thread format.
/// </summary>
/// <param name="postId"> Post identifier to get thread posts. </param>
/// <param name="fromPostId"> Post identifier to start from. </param>
/// <returns> Collection of posts in thread format. </returns>
public Task<ChannelPostsResponse> GetThreadPostsAsync(string postId, string? fromPostId = null);
#endregion
#region Interactive Dialogs
/// <summary>
/// Open an interactive dialog.
/// </summary>
/// <param name="triggerId"> Trigger identifier from a slash command or interactive action payload. </param>
/// <param name="url"> URL where Mattermost sends the submitted dialog payload. </param>
/// <param name="dialog"> Dialog definition. </param>
Task OpenInteractiveDialogAsync(string triggerId, string url, InteractiveDialog dialog);
/// <summary>
/// Open an interactive dialog.
/// </summary>
/// <param name="request"> Open dialog request. </param>
Task OpenInteractiveDialogAsync(OpenInteractiveDialogRequest request);
#endregion
#region Teams
/// <summary>
/// Get team by specified identifier.
/// </summary>
/// <param name="teamId"> Team identifier. </param>
/// <returns> Team information. </returns>
Task<Team> GetTeamAsync(string teamId);
/// <summary>
/// Get a page of teams.
/// </summary>
/// <param name="page"> The page to select. </param>
/// <param name="perPage"> The number of teams per page. </param>
/// <returns> Teams visible to the current user. </returns>
Task<IList<Team>> GetTeamsAsync(int page = 0, int perPage = 60);
/// <summary>
/// Get team by name.
/// </summary>
/// <param name="teamName"> Team name. </param>
/// <returns> Team information. </returns>
Task<Team> GetTeamByNameAsync(string teamName);
#endregion
#region Channels
/// <summary>
/// Get channel from the provided channel id string.
/// </summary>
/// <param name="channelId"> Channel identifier. </param>
/// <returns> Channel information. </returns>
Task<Channel> GetChannelAsync(string channelId);
/// <summary>
/// Get a page of public channels for a team.
/// </summary>
/// <param name="teamId"> Team identifier. </param>
/// <param name="page"> The page to select. </param>
/// <param name="perPage"> The number of channels per page. </param>
/// <returns> Public channels for the team. </returns>
Task<IList<Channel>> GetTeamChannelsAsync(string teamId, int page = 0, int perPage = 60);
/// <summary>
/// Create simple channel with specified users.
/// </summary>
/// <param name="teamId"> Team identifier. </param>
/// <param name="name"> Channel name. </param>
/// <param name="displayName"> Channel display name. </param>
/// <param name="channelType"> Channel type: open or private. </param>
/// <param name="purpose"> Channel purpose (optional). </param>
/// <param name="header"> Channel header (optional). </param>
/// <returns> Created channel info. </returns>
Task<Channel> CreateChannelAsync(string teamId, string name, string displayName,
ChannelType channelType, string purpose = "", string header = "");
/// <summary>
/// Create group channel with specified users.
/// </summary>
/// <param name="userIds"> Participant users. </param>
/// <returns> Created channel info. </returns>
Task<Channel> CreateGroupChannelAsync(params string[] userIds);
/// <summary>
/// Add user to channel.
/// </summary>
/// <param name="channelId"> Channel identifier. </param>
/// <param name="userId"> User identifier. </param>
/// <returns> Channel user information. </returns>
Task<ChannelUserInfo> AddUserToChannelAsync(string channelId, string userId);
/// <summary>
/// Delete user from channel.
/// </summary>
/// <param name="channelId"> Channel identifier. </param>
/// <param name="userId"> User identifier. </param>
/// <returns> True if deleted, otherwise false. </returns>
Task DeleteUserFromChannelAsync(string channelId, string userId);
/// <summary>
/// Find channel by channel name and team name or identifier.
/// </summary>
/// <param name="teamIdOrName"> Team name or identifier where channel exists. </param>
/// <param name="channelName"> Channel name. </param>
/// <param name="isTeamId"> True if teamIdOrName is team identifier, otherwise false (team name). Default is true. </param>
/// <param name="includeDeleted"> Include deleted channels in search, default is true. </param>
/// <returns> Channel info. </returns>
Task<Channel?> FindChannelByNameAsync(string teamIdOrName, string channelName, bool isTeamId = true, bool includeDeleted = true);
/// <summary>
/// Archive channel by specified channel identifier.
/// </summary>
/// <param name="channelId"> Channel identifier. </param>
/// <returns> True if archieved, otherwise false. </returns>
Task ArchiveChannelAsync(string channelId);
/// <summary>
/// Create a new direct message channel between current user and specified user. <br/>
/// Must have create_direct_channel permission. <br/>
/// Having the manage_system permission voids the previous requirements.
/// </summary>
/// <param name="userId"> User identifier to create direct channel with. </param>
/// <returns>Created direct channel.</returns>
Task<Channel> CreateDirectChannelAsync(string userId);
/// <summary>
/// Create a new direct message channel between two users. <br/>
/// Must be one of the two users and have create_direct_channel permission. <br/>
/// Having the manage_system permission voids the previous requirements.
/// </summary>
/// <param name="userId1"> First user identifier to create direct channel with. </param>
/// <param name="userId2"> Second user identifier to create direct channel with. </param>
/// <returns>Created direct channel.</returns>
Task<Channel> CreateDirectChannelAsync(string userId1, string userId2);
#endregion
#region Files
/// <summary>
/// Get file by identifier.
/// </summary>
/// <param name="fileId"> File identifier. </param>
/// <returns> File bytes. </returns>
Task<byte[]> GetFileAsync(string fileId);
/// <summary>
/// Get file stream by identifier.
/// </summary>
/// <param name="fileId"> File identifier. </param>
/// <returns> File stream. </returns>
Task<Stream> GetFileStreamAsync(string fileId);
/// <summary>
/// Get file details by specified identifier.
/// </summary>
/// <param name="fileId"> File identifier. </param>
/// <returns> File details. </returns>
Task<FileDetails> GetFileDetailsAsync(string fileId);
/// <summary>
/// Upload new file.
/// </summary>
/// <param name="channelId"> Channel where file will be posted. </param>
/// <param name="filePath"> File fullname on local device. </param>
/// <param name="progressChanged"> Uploading progress callback in percents - from 0 to 100. </param>
/// <returns> Created file details. </returns>
Task<FileDetails> UploadFileAsync(string channelId, string filePath, Action<int>? progressChanged = null);
/// <summary>
/// Upload new file.
/// </summary>
/// <param name="channelId"> Channel where file will be posted. </param>
/// <param name="fileName"> Name of the uploaded file. </param>
/// <param name="stream"> File content. </param>
/// <param name="progressChanged"> Uploading progress callback in percents - from 0 to 100. </param>
/// <returns> Created file details. </returns>
Task<FileDetails> UploadFileAsync(string channelId, string fileName, Stream stream, Action<int>? progressChanged = null);
#endregion
#region Users
/// <summary>
/// Get current authorized user information.
/// </summary>
/// <returns> Authorized user information. </returns>
Task<User> GetMeAsync();
/// <summary>
/// Get user by identifier.
/// </summary>
/// <param name="userId"> User identifier. </param>
/// <returns> User information. </returns>
Task<User> GetUserAsync(string userId);
/// <summary>
/// Get a page of users.
/// </summary>
/// <param name="page"> The page to select. </param>
/// <param name="perPage"> The number of users per page. </param>
/// <param name="inTeamId"> Only users in this team. </param>
/// <param name="notInTeamId"> Only users not in this team. </param>
/// <param name="inChannelId"> Only users in this channel. </param>
/// <param name="notInChannelId"> Only users not in this channel. </param>
/// <param name="active"> Only active users. </param>
/// <param name="inactive"> Only inactive users. </param>
/// <returns> Users matching the query. </returns>
Task<IList<User>> GetUsersAsync(
int page = 0,
int perPage = 60,
string? inTeamId = null,
string? notInTeamId = null,
string? inChannelId = null,
string? notInChannelId = null,
bool? active = null,
bool? inactive = null);
/// <summary>
/// Search users by term.
/// </summary>
/// <param name="term"> Search term matched against username, full name, nickname and email. </param>
/// <param name="teamId"> Only search users on this team. </param>
/// <param name="notInTeamId"> Only search users not on this team. </param>
/// <param name="inChannelId"> Only search users in this channel. </param>
/// <param name="notInChannelId"> Only search users not in this channel. Must specify teamId when using this option. </param>
/// <param name="groupConstrained"> Only users allowed to join based on group constraints. </param>
/// <param name="allowInactive"> Include deactivated users in the results. </param>
/// <param name="withoutTeam"> Search users that are not on a team. </param>
/// <param name="limit"> Maximum number of users to return. </param>
/// <returns> Users matching the search term. </returns>
Task<IList<User>> SearchUsersAsync(
string term,
string? teamId = null,
string? notInTeamId = null,
string? inChannelId = null,
string? notInChannelId = null,
bool groupConstrained = false,
bool allowInactive = false,
bool withoutTeam = false,
int? limit = null);
/// <summary>
/// Get user by username.
/// </summary>
/// <param name="username"> Username. </param>
/// <returns> User information. </returns>
Task<User> GetUserByUsernameAsync(string username);
/// <summary>
/// Get user by email address.
/// </summary>
/// <param name="email"> Email address. </param>
/// <returns> User information. </returns>
Task<User> GetUserByEmailAsync(string email);
#endregion
/// <summary>
/// Set call state for channel identifier - 'Calls' plugin required.
/// </summary>
/// <param name="isCallsEnabled"> New state. </param>
/// <param name="channelId"> Channel identifier where calls must be in specified state. </param>
/// <returns> True if calls state setted, otherwise false. </returns>
Task SetChannelCallStateAsync(string channelId, bool isCallsEnabled);
/// <summary>
/// Login with specified login identifier and password.
/// </summary>
/// <param name="username">Username or email.</param>
/// <param name="password">Password.</param>
/// <returns>Authorized <see cref="User"/> object.</returns>
Task<User> LoginAsync(string username, string password);
/// <summary>
/// Logout from server.
/// </summary>
/// <returns> Task representing logout operation. </returns>
Task LogoutAsync();
}
}