Skip to content

Commit

Permalink
Support for Slack Connect invitations
Browse files Browse the repository at this point in the history
  • Loading branch information
soxtoby committed Oct 16, 2022
1 parent 81e9b3f commit 0de38bf
Show file tree
Hide file tree
Showing 11 changed files with 237 additions and 0 deletions.
16 changes: 16 additions & 0 deletions SlackNet/Events/SharedChannelInviteAccepted.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;

namespace SlackNet.Events
{
public class SharedChannelInviteAccepted : Event
{
public bool ApprovalRequired { get; set; }
public Invite Invite { get; set; }
public User InvitingUser { get; set; }
public string RecipientEmail { get; set; }
public string RecipientUserId { get; set; }
public InviteChannel Channel { get; set; }
public IList<ConnectedTeam> TeamsInChannel { get; set; } = new List<ConnectedTeam>();
public User AcceptingUser { get; set; }
}
}
13 changes: 13 additions & 0 deletions SlackNet/Events/SharedChannelInviteApproved.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace SlackNet.Events
{
public class SharedChannelInviteApproved : Event
{
public Invite Invite { get; set; }
public InviteChannel Channel { get; set; }
public string ApprovingTeamId { get; set; }
public IList<ConnectedTeam> TeamsInChannel { get; set; } = new List<ConnectedTeam>();
public User ApprovingUser { get; set; }
}
}
13 changes: 13 additions & 0 deletions SlackNet/Events/SharedChannelInviteDeclined.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace SlackNet.Events
{
public class SharedChannelInviteDeclined : Event
{
public Invite Invite { get; set; }
public InviteChannel Channel { get; set; }
public string DecliningTeamId { get; set; }
public IList<ConnectedTeam> TeamsInChannel { get; set; } = new List<ConnectedTeam>();
public User DecliningUser { get; set; }
}
}
8 changes: 8 additions & 0 deletions SlackNet/Events/SharedChannelInviteReceived.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace SlackNet.Events
{
public class SharedChannelInviteReceived : Event
{
public Invite Invite { get; set; }
public InviteChannel Channel { get; set; }
}
}
12 changes: 12 additions & 0 deletions SlackNet/Objects/ConnectedTeam.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace SlackNet
{
public class ConnectedTeam
{
public string Id { get; set; }
public string Name { get; set; }
public Icons Icon { get; set; }
public bool IsVerified { get; set; }
public string Domain { get; set; }
public int DateCreated { get; set; }
}
}
13 changes: 13 additions & 0 deletions SlackNet/Objects/Invite.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace SlackNet
{
public class Invite
{
public string Id { get; set; }
public int DateCreated { get; set; }
public int DateInvalid { get; set; }
public ConnectedTeam InvitingTeam { get; set; }
public User InvitingUser { get; set; }
public string RecipientUserId { get; set; }
public string Link { get; set; }
}
}
10 changes: 10 additions & 0 deletions SlackNet/Objects/InviteChannel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace SlackNet
{
public class InviteChannel
{
public string Id { get; set; }
public bool IsPrivate { get; set; }
public bool IsIm { get; set; }
public string Name { get; set; }
}
}
94 changes: 94 additions & 0 deletions SlackNet/WebApi/ConversationsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ namespace SlackNet.WebApi
{
public interface IConversationsApi
{
/// <summary>
/// Accepts an invitation to a Slack Connect channel.
/// </summary>
/// <remarks>See the <a href="https://api.slack.com/methods/conversations.acceptSharedInvite">Slack documentation</a> for more information.</remarks>
/// <param name="channelName">Name of the channel. If the channel does not exist already in your workspace, this name is the one that the channel will take.</param>
/// <param name="inviteId"><see cref="SlackNet.Invite.Id"/> from the <see cref="SharedChannelInviteReceived"/> event.</param>
/// <param name="channelId">ID of the channel that you'd like to accept. Must provide either <see cref="inviteId"/> or <see cref="channelId"/>.</param>
/// <param name="freeTrialAccepted">Whether you'd like to use your workspace's free trial to begin using Slack Connect.</param>
/// <param name="isPrivate">Whether the channel should be private.</param>
/// <param name="teamId">The ID of the workspace to accept the channel in. If an org-level token is used to call this method, the <see cref="teamId"/> argument is required.</param>
/// <param name="cancellationToken"></param>
Task<AcceptSharedInviteResponse> AcceptSharedInvite(string channelName, string inviteId = null, string channelId = null, bool freeTrialAccepted = false, bool isPrivate = false, string teamId = null, CancellationToken? cancellationToken = null);

/// <summary>
/// Approves an invitation to a Slack Connect channel.
/// </summary>
/// <remarks>See the <a href="https://api.slack.com/methods/conversations.approveSharedInvite">Slack documentation</a> for more information.</remarks>
/// <param name="inviteId">ID of the shared channel invite to approve. Subscribe to the <see cref="SharedChannelInviteAccepted"/> event to receive IDs of Slack Connect channel invites that have been accepted and are awaiting approval.</param>
/// <param name="targetTeam">The team or enterprise id of the other party involved in the invitation you are approving.</param>
/// <param name="cancellationToken"></param>
Task ApproveSharedInvite(string inviteId, string targetTeam = null, CancellationToken? cancellationToken = null);

/// <summary>
/// Archives a conversation. Not all types of conversations can be archived.
/// </summary>
Expand All @@ -33,6 +55,15 @@ public interface IConversationsApi
/// <param name="cancellationToken"></param>
Task<Conversation> Create(string name, bool isPrivate, CancellationToken? cancellationToken = null);

/// <summary>
/// Declines a Slack Connect channel invite.
/// </summary>
/// <remarks>See the <a href="https://api.slack.com/methods/conversations.declineSharedInvite">Slack documentation</a> for more information.</remarks>
/// <param name="inviteId">ID of the Slack Connect invite to decline. Subscribe to the <see cref="SharedChannelInviteAccepted"/> event to receive IDs of Slack Connect channel invites that have been accepted and are awaiting approval.</param>
/// <param name="targetTeam">The team or enterprise id of the other party involved in the invitation you are declining.</param>
/// <param name="cancellationToken"></param>
Task DeclineSharedInvite(string inviteId, string targetTeam = null, CancellationToken? cancellationToken = null);

/// <summary>
/// Fetches a conversation's history of messages and events.
/// </summary>
Expand Down Expand Up @@ -69,6 +100,17 @@ public interface IConversationsApi
/// <param name="cancellationToken"></param>
Task<Conversation> Invite(string channelId, IEnumerable<string> userIds, CancellationToken? cancellationToken = null);

/// <summary>
/// Sends an invitation to a Slack Connect channel.
/// </summary>
/// <remarks>See the <a href="https://api.slack.com/methods/conversations.inviteShared">Slack documentation</a> for more information.</remarks>
/// <param name="channelId">ID of the channel on your team that you'd like to share.</param>
/// <param name="emails">Emails to receive this invite. Either <see cref="emails"/> or <see cref="userIds"/> must be provided.</param>
/// <param name="userIds">User IDs to receive this invite. Either <see cref="emails"/> or <see cref="userIds"/> must be provided.</param>
/// <param name="externalLimited">Whether invite is to an external limited member.</param>
/// <param name="cancellationToken"></param>
Task<InviteSharedResponse> InviteShared(string channelId, IEnumerable<string> emails, IEnumerable<string> userIds, bool externalLimited = true, CancellationToken? cancellationToken = null);

/// <summary>
/// Joins an existing conversation.
/// </summary>
Expand Down Expand Up @@ -110,6 +152,16 @@ public interface IConversationsApi
/// <param name="cancellationToken"></param>
Task<ConversationListResponse> List(bool excludeArchived = false, int limit = 100, IEnumerable<ConversationType> types = null, string cursor = null, string teamId = null, CancellationToken? cancellationToken = null);

/// <summary>
/// Lists shared channel invites that have been generated or received but have not been approved by all parties.
/// </summary>
/// <remarks>See the <a href="https://api.slack.com/methods/conversations.listConnectInvites">Slack documentation</a> for more information.</remarks>
/// <param name="count">Maximum number of invites to return.</param>
/// <param name="cursor">Set to <see cref="ResponseMetadata.NextCursor"/> returned by previous call to list items in subsequent page.</param>
/// <param name="teamId">Encoded team id for the workspace to retrieve invites for, required if org token is used.</param>
/// <param name="cancellationToken"></param>
Task<ConnectInvitesListResponse> ListConnectInvites(int count = 100, string cursor = null, string teamId = null, CancellationToken? cancellationToken = null);

/// <summary>
/// Sets the read cursor in a channel.
/// </summary>
Expand Down Expand Up @@ -230,6 +282,24 @@ public class ConversationsApi : IConversationsApi
private readonly ISlackApiClient _client;
public ConversationsApi(ISlackApiClient client) => _client = client;

public Task<AcceptSharedInviteResponse> AcceptSharedInvite(string channelName, string inviteId = null, string channelId = null, bool freeTrialAccepted = false, bool isPrivate = false, string teamId = null, CancellationToken? cancellationToken = null) =>
_client.Post<AcceptSharedInviteResponse>("conversations.acceptSharedInvite", new Args
{
{ "channel_name", channelName },
{ "invite_id", inviteId },
{ "channel_id", channelId },
{ "free_trial_accepted", freeTrialAccepted },
{ "is_private", isPrivate },
{ "team_id", teamId }
}, cancellationToken);

public Task ApproveSharedInvite(string inviteId, string targetTeam = null, CancellationToken? cancellationToken = null) =>
_client.Post("conversations.approveSharedInvite", new Args
{
{ "invite_id", inviteId },
{ "target_team", targetTeam }
}, cancellationToken);

public Task Archive(string channelId, CancellationToken? cancellationToken = null) =>
_client.Post("conversations.archive", new Args { { "channel", channelId } }, cancellationToken);

Expand All @@ -244,6 +314,13 @@ public async Task<Conversation> Create(string name, bool isPrivate, Cancellation
}, cancellationToken).ConfigureAwait(false))
.Channel;

public Task DeclineSharedInvite(string inviteId, string targetTeam = null, CancellationToken? cancellationToken = null) =>
_client.Get("conversations.declineSharedInvite", new Args
{
{ "invite_id", inviteId },
{ "target_team", targetTeam }
}, cancellationToken);

public Task<ConversationHistoryResponse> History(string channelId, string latestTs = null, string oldestTs = null, bool inclusive = false, int limit = 100, string cursor = null, CancellationToken? cancellationToken = null) =>
_client.Get<ConversationHistoryResponse>("conversations.history", new Args
{
Expand Down Expand Up @@ -272,6 +349,15 @@ public async Task<Conversation> Invite(string channelId, IEnumerable<string> use
}, cancellationToken).ConfigureAwait(false))
.Channel;

public Task<InviteSharedResponse> InviteShared(string channelId, IEnumerable<string> emails, IEnumerable<string> userIds, bool externalLimited = true, CancellationToken? cancellationToken = null) =>
_client.Get<InviteSharedResponse>("conversations.inviteShared", new Args()
{
{ "channel", channelId },
{ "emails", emails },
{ "user_ids", userIds },
{ "external_limited", externalLimited }
}, cancellationToken);

public Task<ConversationJoinResponse> Join(string channelId, CancellationToken? cancellationToken = null) =>
_client.Post<ConversationJoinResponse>("conversations.join", new Args { { "channel", channelId } }, cancellationToken);

Expand All @@ -295,6 +381,14 @@ public Task<ConversationListResponse> List(bool excludeArchived = false, int lim
{ "team_id", teamId }
}, cancellationToken);

public Task<ConnectInvitesListResponse> ListConnectInvites(int count = 100, string cursor = null, string teamId = null, CancellationToken? cancellationToken = null) =>
_client.Post<ConnectInvitesListResponse>("conversations.listConnectInvites", new Args
{
{ "count", count },
{ "cursor", cursor },
{ "team_id", teamId }
}, cancellationToken);

public Task Mark(string channelId, string messageTs, CancellationToken? cancellationToken = null) =>
_client.Post("conversations.mark", new Args
{
Expand Down
9 changes: 9 additions & 0 deletions SlackNet/WebApi/Responses/AcceptSharedInviteResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace SlackNet.WebApi
{
public class AcceptSharedInviteResponse
{
public bool ImplicitApproval { get; set; }
public string ChannelId { get; set; }
public string InviteId { get; set; }
}
}
39 changes: 39 additions & 0 deletions SlackNet/WebApi/Responses/ConnectInvitesListResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Collections.Generic;

namespace SlackNet.WebApi
{
public class ConnectInvitesListResponse
{
public IList<PendingInvite> Invites { get; set; }
public ResponseMetadata ResponseMetadata { get; set; } = new();
}

public class PendingInvite
{
public string Direction { get; set; }
public string Status { get; set; }
public int DateLastUpdated { get; set; }
public string InviteType { get; set; }
public Invite Invite { get; set; }
public InviteChannel Channel { get; set; }
public IList<InviteAcceptance> Acceptances { get; set; } = new List<InviteAcceptance>();
}

public class InviteAcceptance
{
public string ApprovalStatus { get; set; }
public int DateAccepted { get; set; }
public int DateInvalid { get; set; }
public int DateLastUpdated { get; set; }
public ConnectedTeam AcceptingTeam { get; set; }
public User AcceptingUser { get; set; }
public IList<InviteReview> Reviews { get; set; } = new List<InviteReview>();
}

public class InviteReview
{
public string Type { get; set; }
public int DateReview { get; set; }
public ConnectedTeam ReviewingTeam { get; set; }
}
}
10 changes: 10 additions & 0 deletions SlackNet/WebApi/Responses/InviteSharedResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace SlackNet.WebApi
{
public class InviteSharedResponse
{
public string InviteId { get; set; }
public bool IsLegacySharedChannel { get; set; }
public string ConfCode { get; set; }
public string Url { get; set; }
}
}

0 comments on commit 0de38bf

Please sign in to comment.