diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildIntegrationProperties.cs b/src/Discord.Net.Core/Entities/Guilds/GuildIntegrationProperties.cs
deleted file mode 100644
index 2ca19b50a..000000000
--- a/src/Discord.Net.Core/Entities/Guilds/GuildIntegrationProperties.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace Discord
-{
- ///
- /// Provides properties used to modify an with the specified changes.
- ///
- public class GuildIntegrationProperties
- {
- ///
- /// Gets or sets the behavior when an integration subscription lapses.
- ///
- public Optional ExpireBehavior { get; set; }
- ///
- /// Gets or sets the period (in seconds) where the integration will ignore lapsed subscriptions.
- ///
- public Optional ExpireGracePeriod { get; set; }
- ///
- /// Gets or sets whether emoticons should be synced for this integration.
- ///
- public Optional EnableEmoticons { get; set; }
- }
-}
diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
index 3111ff495..b4625abbf 100644
--- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
@@ -718,8 +718,25 @@ namespace Discord
///
Task> GetVoiceRegionsAsync(RequestOptions options = null);
- Task> GetIntegrationsAsync(RequestOptions options = null);
- Task CreateIntegrationAsync(ulong id, string type, RequestOptions options = null);
+ ///
+ /// Gets a collection of all the integrations this guild contains.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains a read-only collection of
+ /// integrations the guild can has.
+ ///
+ Task> GetIntegrationsAsync(RequestOptions options = null);
+
+ ///
+ /// Deletes an integration.
+ ///
+ /// The id for the integration.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous removal operation.
+ ///
+ Task DeleteIntegrationAsync(ulong id, RequestOptions options = null);
///
/// Gets a collection of all invites in this guild.
diff --git a/src/Discord.Net.Core/Entities/Guilds/IntegrationAccount.cs b/src/Discord.Net.Core/Entities/Guilds/IntegrationAccount.cs
deleted file mode 100644
index 340115fde..000000000
--- a/src/Discord.Net.Core/Entities/Guilds/IntegrationAccount.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Diagnostics;
-
-namespace Discord
-{
- [DebuggerDisplay("{DebuggerDisplay,nq}")]
- public struct IntegrationAccount
- {
- /// Gets the ID of the account.
- /// A unique identifier of this integration account.
- public string Id { get; }
- /// Gets the name of the account.
- /// A string containing the name of this integration account.
- public string Name { get; private set; }
-
- public override string ToString() => Name;
- private string DebuggerDisplay => $"{Name} ({Id})";
- }
-}
diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuildIntegration.cs b/src/Discord.Net.Core/Entities/Integrations/IIntegration.cs
similarity index 61%
rename from src/Discord.Net.Core/Entities/Guilds/IGuildIntegration.cs
rename to src/Discord.Net.Core/Entities/Integrations/IIntegration.cs
index 6fe3f7b55..304d58792 100644
--- a/src/Discord.Net.Core/Entities/Guilds/IGuildIntegration.cs
+++ b/src/Discord.Net.Core/Entities/Integrations/IIntegration.cs
@@ -3,15 +3,16 @@ using System;
namespace Discord
{
///
- /// Holds information for a guild integration feature.
+ /// Holds information for an integration feature.
+ /// Nullable fields not provided for Discord bot integrations, but are for Twitch etc.
///
- public interface IGuildIntegration
+ public interface IIntegration
{
///
/// Gets the integration ID.
///
///
- /// An representing the unique identifier value of this integration.
+ /// A representing the unique identifier value of this integration.
///
ulong Id { get; }
///
@@ -45,30 +46,52 @@ namespace Discord
///
/// true if this integration is syncing; otherwise false.
///
- bool IsSyncing { get; }
+ bool? IsSyncing { get; }
///
/// Gets the ID that this integration uses for "subscribers".
///
- ulong ExpireBehavior { get; }
+ ulong? RoleId { get; }
+ ///
+ /// Gets whether emoticons should be synced for this integration (twitch only currently).
+ ///
+ bool? HasEnabledEmoticons { get; }
+ ///
+ /// Gets the behavior of expiring subscribers.
+ ///
+ IntegrationExpireBehavior? ExpireBehavior { get; }
///
/// Gets the grace period before expiring "subscribers".
///
- ulong ExpireGracePeriod { get; }
+ int? ExpireGracePeriod { get; }
+ ///
+ /// Gets the user for this integration.
+ ///
+ IUser User { get; }
+ ///
+ /// Gets integration account information.
+ ///
+ IIntegrationAccount Account { get; }
///
/// Gets when this integration was last synced.
///
///
/// A containing a date and time of day when the integration was last synced.
///
- DateTimeOffset SyncedAt { get; }
+ DateTimeOffset? SyncedAt { get; }
///
- /// Gets integration account information.
+ /// Gets how many subscribers this integration has.
///
- IntegrationAccount Account { get; }
-
+ int? SubscriberCount { get; }
+ ///
+ /// Gets whether this integration been revoked.
+ ///
+ bool? IsRevoked { get; }
+ ///
+ /// Gets the bot/OAuth2 application for a discord integration.
+ ///
+ IIntegrationApplication Application { get; }
+
IGuild Guild { get; }
ulong GuildId { get; }
- ulong RoleId { get; }
- IUser User { get; }
}
}
diff --git a/src/Discord.Net.Core/Entities/Integrations/IIntegrationAccount.cs b/src/Discord.Net.Core/Entities/Integrations/IIntegrationAccount.cs
new file mode 100644
index 000000000..322ffa5c2
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Integrations/IIntegrationAccount.cs
@@ -0,0 +1,23 @@
+namespace Discord
+{
+ ///
+ /// Provides the account information for an .
+ ///
+ public interface IIntegrationAccount
+ {
+ ///
+ /// Gets the ID of the account.
+ ///
+ ///
+ /// A unique identifier of this integration account.
+ ///
+ string Id { get; }
+ ///
+ /// Gets the name of the account.
+ ///
+ ///
+ /// A string containing the name of this integration account.
+ ///
+ string Name { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Integrations/IIntegrationApplication.cs b/src/Discord.Net.Core/Entities/Integrations/IIntegrationApplication.cs
new file mode 100644
index 000000000..9085ae686
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Integrations/IIntegrationApplication.cs
@@ -0,0 +1,33 @@
+namespace Discord
+{
+ ///
+ /// Provides the bot/OAuth2 application for an .
+ ///
+ public interface IIntegrationApplication
+ {
+ ///
+ /// Gets the id of the app.
+ ///
+ ulong Id { get; }
+ ///
+ /// Gets the name of the app.
+ ///
+ string Name { get; }
+ ///
+ /// Gets the icon hash of the app.
+ ///
+ string Icon { get; }
+ ///
+ /// Gets the description of the app.
+ ///
+ string Description { get; }
+ ///
+ /// Gets the summary of the app.
+ ///
+ string Summary { get; }
+ ///
+ /// Gets the bot associated with this application.
+ ///
+ IUser Bot { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Integrations/IntegrationExpireBehavior.cs b/src/Discord.Net.Core/Entities/Integrations/IntegrationExpireBehavior.cs
new file mode 100644
index 000000000..642e247eb
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Integrations/IntegrationExpireBehavior.cs
@@ -0,0 +1,17 @@
+namespace Discord
+{
+ ///
+ /// The behavior of expiring subscribers for an .
+ ///
+ public enum IntegrationExpireBehavior
+ {
+ ///
+ /// Removes a role from an expired subscriber.
+ ///
+ RemoveRole = 0,
+ ///
+ /// Kicks an expired subscriber from the guild.
+ ///
+ Kick = 1
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Users/ConnectionVisibility.cs b/src/Discord.Net.Core/Entities/Users/ConnectionVisibility.cs
new file mode 100644
index 000000000..ed041c9f9
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Users/ConnectionVisibility.cs
@@ -0,0 +1,17 @@
+namespace Discord
+{
+ ///
+ /// The visibility of the connected account.
+ ///
+ public enum ConnectionVisibility
+ {
+ ///
+ /// Invisible to everyone except the user themselves.
+ ///
+ None = 0,
+ ///
+ /// Visible to everyone.
+ ///
+ Everyone = 1
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Users/IConnection.cs b/src/Discord.Net.Core/Entities/Users/IConnection.cs
index 1e65d971f..94b23a4b5 100644
--- a/src/Discord.Net.Core/Entities/Users/IConnection.cs
+++ b/src/Discord.Net.Core/Entities/Users/IConnection.cs
@@ -4,24 +4,53 @@ namespace Discord
{
public interface IConnection
{
- /// Gets the ID of the connection account.
- /// A representing the unique identifier value of this connection.
+ ///
+ /// Gets the ID of the connection account.
+ ///
+ ///
+ /// A representing the unique identifier value of this connection.
+ ///
string Id { get; }
- /// Gets the service of the connection (twitch, youtube).
- /// A string containing the name of this type of connection.
- string Type { get; }
- /// Gets the username of the connection account.
- /// A string containing the name of this connection.
+ ///
+ /// Gets the username of the connection account.
+ ///
+ ///
+ /// A string containing the name of this connection.
+ ///
string Name { get; }
- /// Gets whether the connection is revoked.
- /// A value which if true indicates that this connection has been revoked, otherwise false.
- bool IsRevoked { get; }
-
- /// Gets a of integration IDs.
+ ///
+ /// Gets the service of the connection (twitch, youtube).
+ ///
+ ///
+ /// A string containing the name of this type of connection.
+ ///
+ string Type { get; }
+ ///
+ /// Gets whether the connection is revoked.
+ ///
///
- /// An containing
- /// representations of unique identifier values of integrations.
+ /// A value which if true indicates that this connection has been revoked, otherwise false.
///
- IReadOnlyCollection IntegrationIds { get; }
+ bool? IsRevoked { get; }
+ ///
+ /// Gets a of integration parials.
+ ///
+ IReadOnlyCollection Integrations { get; }
+ ///
+ /// Gets whether the connection is verified.
+ ///
+ bool Verified { get; }
+ ///
+ /// Gets whether friend sync is enabled for this connection.
+ ///
+ bool FriendSync { get; }
+ ///
+ /// Gets whether activities related to this connection will be shown in presence updates.
+ ///
+ bool ShowActivity { get; }
+ ///
+ /// Visibility of this connection.
+ ///
+ ConnectionVisibility Visibility { get; }
}
}
diff --git a/src/Discord.Net.Rest/API/Common/Connection.cs b/src/Discord.Net.Rest/API/Common/Connection.cs
index bd8de3902..0a9940e23 100644
--- a/src/Discord.Net.Rest/API/Common/Connection.cs
+++ b/src/Discord.Net.Rest/API/Common/Connection.cs
@@ -7,14 +7,22 @@ namespace Discord.API
{
[JsonProperty("id")]
public string Id { get; set; }
- [JsonProperty("type")]
- public string Type { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
+ [JsonProperty("type")]
+ public string Type { get; set; }
[JsonProperty("revoked")]
- public bool Revoked { get; set; }
-
+ public Optional Revoked { get; set; }
[JsonProperty("integrations")]
- public IReadOnlyCollection Integrations { get; set; }
+ public Optional> Integrations { get; set; }
+ [JsonProperty("verified")]
+ public bool Verified { get; set; }
+ [JsonProperty("friend_sync")]
+ public bool FriendSync { get; set; }
+ [JsonProperty("show_activity")]
+ public bool ShowActivity { get; set; }
+ [JsonProperty("visibility")]
+ public ConnectionVisibility Visibility { get; set; }
+
}
}
diff --git a/src/Discord.Net.Rest/API/Common/Integration.cs b/src/Discord.Net.Rest/API/Common/Integration.cs
index 47d67e149..5a2b00001 100644
--- a/src/Discord.Net.Rest/API/Common/Integration.cs
+++ b/src/Discord.Net.Rest/API/Common/Integration.cs
@@ -5,6 +5,9 @@ namespace Discord.API
{
internal class Integration
{
+ [JsonProperty("guild_id")]
+ public Optional GuildId { get; set; }
+
[JsonProperty("id")]
public ulong Id { get; set; }
[JsonProperty("name")]
@@ -14,18 +17,26 @@ namespace Discord.API
[JsonProperty("enabled")]
public bool Enabled { get; set; }
[JsonProperty("syncing")]
- public bool Syncing { get; set; }
+ public Optional Syncing { get; set; }
[JsonProperty("role_id")]
- public ulong RoleId { get; set; }
+ public Optional RoleId { get; set; }
+ [JsonProperty("enable_emoticons")]
+ public Optional EnableEmoticons { get; set; }
[JsonProperty("expire_behavior")]
- public ulong ExpireBehavior { get; set; }
+ public Optional ExpireBehavior { get; set; }
[JsonProperty("expire_grace_period")]
- public ulong ExpireGracePeriod { get; set; }
+ public Optional ExpireGracePeriod { get; set; }
[JsonProperty("user")]
- public User User { get; set; }
+ public Optional User { get; set; }
[JsonProperty("account")]
- public IntegrationAccount Account { get; set; }
+ public Optional Account { get; set; }
[JsonProperty("synced_at")]
- public DateTimeOffset SyncedAt { get; set; }
+ public Optional SyncedAt { get; set; }
+ [JsonProperty("subscriber_count")]
+ public Optional SubscriberAccount { get; set; }
+ [JsonProperty("revoked")]
+ public Optional Revoked { get; set; }
+ [JsonProperty("application")]
+ public Optional Application { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Common/IntegrationAccount.cs b/src/Discord.Net.Rest/API/Common/IntegrationAccount.cs
index a8d33931c..6b8328074 100644
--- a/src/Discord.Net.Rest/API/Common/IntegrationAccount.cs
+++ b/src/Discord.Net.Rest/API/Common/IntegrationAccount.cs
@@ -5,7 +5,7 @@ namespace Discord.API
internal class IntegrationAccount
{
[JsonProperty("id")]
- public ulong Id { get; set; }
+ public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
diff --git a/src/Discord.Net.Rest/API/Common/IntegrationApplication.cs b/src/Discord.Net.Rest/API/Common/IntegrationApplication.cs
new file mode 100644
index 000000000..4e07398b8
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/IntegrationApplication.cs
@@ -0,0 +1,20 @@
+using Newtonsoft.Json;
+
+namespace Discord.API
+{
+ internal class IntegrationApplication
+ {
+ [JsonProperty("id")]
+ public ulong Id { get; set; }
+ [JsonProperty("name")]
+ public string Name { get; set; }
+ [JsonProperty("icon")]
+ public Optional Icon { get; set; }
+ [JsonProperty("description")]
+ public string Description { get; set; }
+ [JsonProperty("summary")]
+ public string Summary { get; set; }
+ [JsonProperty("bot")]
+ public Optional Bot { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/ClientHelper.cs b/src/Discord.Net.Rest/ClientHelper.cs
index 5debea27e..c6ad6a9fb 100644
--- a/src/Discord.Net.Rest/ClientHelper.cs
+++ b/src/Discord.Net.Rest/ClientHelper.cs
@@ -49,7 +49,7 @@ namespace Discord.Rest
public static async Task> GetConnectionsAsync(BaseDiscordClient client, RequestOptions options)
{
var models = await client.ApiClient.GetMyConnectionsAsync(options).ConfigureAwait(false);
- return models.Select(RestConnection.Create).ToImmutableArray();
+ return models.Select(model => RestConnection.Create(client, model)).ToImmutableArray();
}
public static async Task GetInviteAsync(BaseDiscordClient client,
diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs
index f6d579d79..645e6711c 100644
--- a/src/Discord.Net.Rest/DiscordRestApiClient.cs
+++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs
@@ -1626,7 +1626,7 @@ namespace Discord.API
#region Guild Integrations
/// must not be equal to zero.
- public async Task> GetGuildIntegrationsAsync(ulong guildId, RequestOptions options = null)
+ public async Task> GetIntegrationsAsync(ulong guildId, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
options = RequestOptions.CreateOrClone(options);
@@ -1634,47 +1634,14 @@ namespace Discord.API
var ids = new BucketIds(guildId: guildId);
return await SendAsync>("GET", () => $"guilds/{guildId}/integrations", ids, options: options).ConfigureAwait(false);
}
- /// and must not be equal to zero.
- /// must not be .
- public async Task CreateGuildIntegrationAsync(ulong guildId, CreateGuildIntegrationParams args, RequestOptions options = null)
- {
- Preconditions.NotEqual(guildId, 0, nameof(guildId));
- Preconditions.NotNull(args, nameof(args));
- Preconditions.NotEqual(args.Id, 0, nameof(args.Id));
- options = RequestOptions.CreateOrClone(options);
-
- var ids = new BucketIds(guildId: guildId);
- return await SendAsync("POST", () => $"guilds/{guildId}/integrations", ids, options: options).ConfigureAwait(false);
- }
- public async Task DeleteGuildIntegrationAsync(ulong guildId, ulong integrationId, RequestOptions options = null)
- {
- Preconditions.NotEqual(guildId, 0, nameof(guildId));
- Preconditions.NotEqual(integrationId, 0, nameof(integrationId));
- options = RequestOptions.CreateOrClone(options);
-
- var ids = new BucketIds(guildId: guildId);
- return await SendAsync("DELETE", () => $"guilds/{guildId}/integrations/{integrationId}", ids, options: options).ConfigureAwait(false);
- }
- public async Task ModifyGuildIntegrationAsync(ulong guildId, ulong integrationId, Rest.ModifyGuildIntegrationParams args, RequestOptions options = null)
- {
- Preconditions.NotEqual(guildId, 0, nameof(guildId));
- Preconditions.NotEqual(integrationId, 0, nameof(integrationId));
- Preconditions.NotNull(args, nameof(args));
- Preconditions.AtLeast(args.ExpireBehavior, 0, nameof(args.ExpireBehavior));
- Preconditions.AtLeast(args.ExpireGracePeriod, 0, nameof(args.ExpireGracePeriod));
- options = RequestOptions.CreateOrClone(options);
-
- var ids = new BucketIds(guildId: guildId);
- return await SendJsonAsync("PATCH", () => $"guilds/{guildId}/integrations/{integrationId}", args, ids, options: options).ConfigureAwait(false);
- }
- public async Task SyncGuildIntegrationAsync(ulong guildId, ulong integrationId, RequestOptions options = null)
+ public async Task DeleteIntegrationAsync(ulong guildId, ulong integrationId, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotEqual(integrationId, 0, nameof(integrationId));
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds(guildId: guildId);
- return await SendAsync("POST", () => $"guilds/{guildId}/integrations/{integrationId}/sync", ids, options: options).ConfigureAwait(false);
+ await SendAsync("DELETE", () => $"guilds/{guildId}/integrations/{integrationId}", ids, options: options).ConfigureAwait(false);
}
#endregion
diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
index 25f474dcc..7dbe20881 100644
--- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
+++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
@@ -305,19 +305,15 @@ namespace Discord.Rest
#endregion
#region Integrations
- public static async Task> GetIntegrationsAsync(IGuild guild, BaseDiscordClient client,
+ public static async Task> GetIntegrationsAsync(IGuild guild, BaseDiscordClient client,
RequestOptions options)
{
- var models = await client.ApiClient.GetGuildIntegrationsAsync(guild.Id, options).ConfigureAwait(false);
- return models.Select(x => RestGuildIntegration.Create(client, guild, x)).ToImmutableArray();
- }
- public static async Task CreateIntegrationAsync(IGuild guild, BaseDiscordClient client,
- ulong id, string type, RequestOptions options)
- {
- var args = new CreateGuildIntegrationParams(id, type);
- var model = await client.ApiClient.CreateGuildIntegrationAsync(guild.Id, args, options).ConfigureAwait(false);
- return RestGuildIntegration.Create(client, guild, model);
+ var models = await client.ApiClient.GetIntegrationsAsync(guild.Id, options).ConfigureAwait(false);
+ return models.Select(x => RestIntegration.Create(client, guild, x)).ToImmutableArray();
}
+ public static async Task DeleteIntegrationAsync(IGuild guild, BaseDiscordClient client, ulong id,
+ RequestOptions options) =>
+ await client.ApiClient.DeleteIntegrationAsync(guild.Id, id, options).ConfigureAwait(false);
#endregion
#region Interactions
diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
index e89096f00..d7ab65a55 100644
--- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
+++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
@@ -720,10 +720,10 @@ namespace Discord.Rest
#endregion
#region Integrations
- public Task> GetIntegrationsAsync(RequestOptions options = null)
+ public Task> GetIntegrationsAsync(RequestOptions options = null)
=> GuildHelper.GetIntegrationsAsync(this, Discord, options);
- public Task CreateIntegrationAsync(ulong id, string type, RequestOptions options = null)
- => GuildHelper.CreateIntegrationAsync(this, Discord, id, type, options);
+ public Task DeleteIntegrationAsync(ulong id, RequestOptions options = null)
+ => GuildHelper.DeleteIntegrationAsync(this, Discord, id, options);
#endregion
#region Invites
@@ -1370,11 +1370,11 @@ namespace Discord.Rest
=> await GetVoiceRegionsAsync(options).ConfigureAwait(false);
///
- async Task> IGuild.GetIntegrationsAsync(RequestOptions options)
+ async Task> IGuild.GetIntegrationsAsync(RequestOptions options)
=> await GetIntegrationsAsync(options).ConfigureAwait(false);
///
- async Task IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options)
- => await CreateIntegrationAsync(id, type, options).ConfigureAwait(false);
+ async Task IGuild.DeleteIntegrationAsync(ulong id, RequestOptions options)
+ => await DeleteIntegrationAsync(id, options).ConfigureAwait(false);
///
async Task> IGuild.GetInvitesAsync(RequestOptions options)
diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs
deleted file mode 100644
index 9759e64d2..000000000
--- a/src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Threading.Tasks;
-using Model = Discord.API.Integration;
-
-namespace Discord.Rest
-{
- [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
- public class RestGuildIntegration : RestEntity, IGuildIntegration
- {
- private long _syncedAtTicks;
-
- ///
- public string Name { get; private set; }
- ///
- public string Type { get; private set; }
- ///
- public bool IsEnabled { get; private set; }
- ///
- public bool IsSyncing { get; private set; }
- ///
- public ulong ExpireBehavior { get; private set; }
- ///
- public ulong ExpireGracePeriod { get; private set; }
- ///
- public ulong GuildId { get; private set; }
- ///
- public ulong RoleId { get; private set; }
- public RestUser User { get; private set; }
- ///
- public IntegrationAccount Account { get; private set; }
- internal IGuild Guild { get; private set; }
-
- ///
- public DateTimeOffset SyncedAt => DateTimeUtils.FromTicks(_syncedAtTicks);
-
- internal RestGuildIntegration(BaseDiscordClient discord, IGuild guild, ulong id)
- : base(discord, id)
- {
- Guild = guild;
- }
- internal static RestGuildIntegration Create(BaseDiscordClient discord, IGuild guild, Model model)
- {
- var entity = new RestGuildIntegration(discord, guild, model.Id);
- entity.Update(model);
- return entity;
- }
-
- internal void Update(Model model)
- {
- Name = model.Name;
- Type = model.Type;
- IsEnabled = model.Enabled;
- IsSyncing = model.Syncing;
- ExpireBehavior = model.ExpireBehavior;
- ExpireGracePeriod = model.ExpireGracePeriod;
- _syncedAtTicks = model.SyncedAt.UtcTicks;
-
- RoleId = model.RoleId;
- User = RestUser.Create(Discord, model.User);
- }
-
- public async Task DeleteAsync()
- {
- await Discord.ApiClient.DeleteGuildIntegrationAsync(GuildId, Id).ConfigureAwait(false);
- }
- public async Task ModifyAsync(Action func)
- {
- if (func == null) throw new NullReferenceException(nameof(func));
-
- var args = new GuildIntegrationProperties();
- func(args);
- var apiArgs = new API.Rest.ModifyGuildIntegrationParams
- {
- EnableEmoticons = args.EnableEmoticons,
- ExpireBehavior = args.ExpireBehavior,
- ExpireGracePeriod = args.ExpireGracePeriod
- };
- var model = await Discord.ApiClient.ModifyGuildIntegrationAsync(GuildId, Id, apiArgs).ConfigureAwait(false);
-
- Update(model);
- }
- public async Task SyncAsync()
- {
- await Discord.ApiClient.SyncGuildIntegrationAsync(GuildId, Id).ConfigureAwait(false);
- }
-
- public override string ToString() => Name;
- private string DebuggerDisplay => $"{Name} ({Id}{(IsEnabled ? ", Enabled" : "")})";
-
- ///
- IGuild IGuildIntegration.Guild
- {
- get
- {
- if (Guild != null)
- return Guild;
- throw new InvalidOperationException("Unable to return this entity's parent unless it was fetched through that object.");
- }
- }
- ///
- IUser IGuildIntegration.User => User;
- }
-}
diff --git a/src/Discord.Net.Rest/Entities/Integrations/RestIntegration.cs b/src/Discord.Net.Rest/Entities/Integrations/RestIntegration.cs
new file mode 100644
index 000000000..e92ecdded
--- /dev/null
+++ b/src/Discord.Net.Rest/Entities/Integrations/RestIntegration.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using Model = Discord.API.Integration;
+
+namespace Discord.Rest
+{
+ ///
+ /// Represents a Rest-based implementation of .
+ ///
+ [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
+ public class RestIntegration : RestEntity, IIntegration
+ {
+ private long? _syncedAtTicks;
+
+ ///
+ public string Name { get; private set; }
+ ///
+ public string Type { get; private set; }
+ ///
+ public bool IsEnabled { get; private set; }
+ ///
+ public bool? IsSyncing { get; private set; }
+ ///
+ public ulong? RoleId { get; private set; }
+ ///
+ public bool? HasEnabledEmoticons { get; private set; }
+ ///
+ public IntegrationExpireBehavior? ExpireBehavior { get; private set; }
+ ///
+ public int? ExpireGracePeriod { get; private set; }
+ ///
+ IUser IIntegration.User => User;
+ ///
+ public IIntegrationAccount Account { get; private set; }
+ ///
+ public DateTimeOffset? SyncedAt => DateTimeUtils.FromTicks(_syncedAtTicks);
+ ///
+ public int? SubscriberCount { get; private set; }
+ ///
+ public bool? IsRevoked { get; private set; }
+ ///
+ public IIntegrationApplication Application { get; private set; }
+
+ internal IGuild Guild { get; private set; }
+ public RestUser User { get; private set; }
+
+ internal RestIntegration(BaseDiscordClient discord, IGuild guild, ulong id)
+ : base(discord, id)
+ {
+ Guild = guild;
+ }
+ internal static RestIntegration Create(BaseDiscordClient discord, IGuild guild, Model model)
+ {
+ var entity = new RestIntegration(discord, guild, model.Id);
+ entity.Update(model);
+ return entity;
+ }
+
+ internal void Update(Model model)
+ {
+ Name = model.Name;
+ Type = model.Type;
+ IsEnabled = model.Enabled;
+
+ IsSyncing = model.Syncing.IsSpecified ? model.Syncing.Value : null;
+ RoleId = model.RoleId.IsSpecified ? model.RoleId.Value : null;
+ HasEnabledEmoticons = model.EnableEmoticons.IsSpecified ? model.EnableEmoticons.Value : null;
+ ExpireBehavior = model.ExpireBehavior.IsSpecified ? model.ExpireBehavior.Value : null;
+ ExpireGracePeriod = model.ExpireGracePeriod.IsSpecified ? model.ExpireGracePeriod.Value : null;
+ User = model.User.IsSpecified ? RestUser.Create(Discord, model.User.Value) : null;
+ Account = model.Account.IsSpecified ? RestIntegrationAccount.Create(model.Account.Value) : null;
+ SubscriberCount = model.SubscriberAccount.IsSpecified ? model.SubscriberAccount.Value : null;
+ IsRevoked = model.Revoked.IsSpecified ? model.Revoked.Value : null;
+ Application = model.Application.IsSpecified ? RestIntegrationApplication.Create(Discord, model.Application.Value) : null;
+
+ _syncedAtTicks = model.SyncedAt.IsSpecified ? model.SyncedAt.Value.UtcTicks : null;
+ }
+
+ public async Task DeleteAsync()
+ {
+ await Discord.ApiClient.DeleteIntegrationAsync(GuildId, Id).ConfigureAwait(false);
+ }
+
+ public override string ToString() => Name;
+ private string DebuggerDisplay => $"{Name} ({Id}{(IsEnabled ? ", Enabled" : "")})";
+
+ ///
+ public ulong GuildId { get; private set; }
+
+ ///
+ IGuild IIntegration.Guild
+ {
+ get
+ {
+ if (Guild != null)
+ return Guild;
+ throw new InvalidOperationException("Unable to return this entity's parent unless it was fetched through that object.");
+ }
+ }
+ }
+}
diff --git a/src/Discord.Net.Rest/Entities/Integrations/RestIntegrationAccount.cs b/src/Discord.Net.Rest/Entities/Integrations/RestIntegrationAccount.cs
new file mode 100644
index 000000000..6d83aa1f0
--- /dev/null
+++ b/src/Discord.Net.Rest/Entities/Integrations/RestIntegrationAccount.cs
@@ -0,0 +1,29 @@
+using Model = Discord.API.IntegrationAccount;
+
+namespace Discord.Rest
+{
+ ///
+ /// Represents a Rest-based implementation of .
+ ///
+ public class RestIntegrationAccount : IIntegrationAccount
+ {
+ internal RestIntegrationAccount() { }
+
+ public string Id { get; private set; }
+
+ public string Name { get; private set; }
+
+ internal static RestIntegrationAccount Create(Model model)
+ {
+ var entity = new RestIntegrationAccount();
+ entity.Update(model);
+ return entity;
+ }
+
+ internal void Update(Model model)
+ {
+ model.Name = Name;
+ model.Id = Id;
+ }
+ }
+}
diff --git a/src/Discord.Net.Rest/Entities/Integrations/RestIntegrationApplication.cs b/src/Discord.Net.Rest/Entities/Integrations/RestIntegrationApplication.cs
new file mode 100644
index 000000000..e532ac970
--- /dev/null
+++ b/src/Discord.Net.Rest/Entities/Integrations/RestIntegrationApplication.cs
@@ -0,0 +1,39 @@
+using Model = Discord.API.IntegrationApplication;
+
+namespace Discord.Rest
+{
+ ///
+ /// Represents a Rest-based implementation of .
+ ///
+ public class RestIntegrationApplication : RestEntity, IIntegrationApplication
+ {
+ public string Name { get; private set; }
+
+ public string Icon { get; private set; }
+
+ public string Description { get; private set; }
+
+ public string Summary { get; private set; }
+
+ public IUser Bot { get; private set; }
+
+ internal RestIntegrationApplication(BaseDiscordClient discord, ulong id)
+ : base(discord, id) { }
+
+ internal static RestIntegrationApplication Create(BaseDiscordClient discord, Model model)
+ {
+ var entity = new RestIntegrationApplication(discord, model.Id);
+ entity.Update(model);
+ return entity;
+ }
+
+ internal void Update(Model model)
+ {
+ Name = model.Name;
+ Icon = model.Icon.IsSpecified ? model.Icon.Value : null;
+ Description = model.Description;
+ Summary = model.Summary;
+ Bot = RestUser.Create(Discord, model.Bot.Value);
+ }
+ }
+}
diff --git a/src/Discord.Net.Rest/Entities/Users/RestConnection.cs b/src/Discord.Net.Rest/Entities/Users/RestConnection.cs
index 1afb813c0..496279727 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestConnection.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestConnection.cs
@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Collections.ObjectModel;
using System.Diagnostics;
+using System.Linq;
using Model = Discord.API.Connection;
namespace Discord.Rest
@@ -9,28 +11,49 @@ namespace Discord.Rest
public class RestConnection : IConnection
{
///
- public string Id { get; }
+ public string Id { get; private set; }
///
- public string Type { get; }
+ public string Name { get; private set; }
///
- public string Name { get; }
+ public string Type { get; private set; }
///
- public bool IsRevoked { get; }
+ public bool? IsRevoked { get; private set; }
///
- public IReadOnlyCollection IntegrationIds { get; }
+ public IReadOnlyCollection Integrations { get; private set; }
+ ///
+ public bool Verified { get; private set; }
+ ///
+ public bool FriendSync { get; private set; }
+ ///
+ public bool ShowActivity { get; private set; }
+ ///
+ public ConnectionVisibility Visibility { get; private set; }
- internal RestConnection(string id, string type, string name, bool isRevoked, IReadOnlyCollection integrationIds)
- {
- Id = id;
- Type = type;
- Name = name;
- IsRevoked = isRevoked;
+ internal BaseDiscordClient Discord { get; }
- IntegrationIds = integrationIds;
+ internal RestConnection(BaseDiscordClient discord) {
+ Discord = discord;
}
- internal static RestConnection Create(Model model)
+
+ internal static RestConnection Create(BaseDiscordClient discord, Model model)
+ {
+ var entity = new RestConnection(discord);
+ entity.Update(model);
+ return entity;
+ }
+
+ internal void Update(Model model)
{
- return new RestConnection(model.Id, model.Type, model.Name, model.Revoked, model.Integrations.ToImmutableArray());
+ Id = model.Id;
+ Name = model.Name;
+ Type = model.Type;
+ IsRevoked = model.Revoked.IsSpecified ? model.Revoked.Value : null;
+ Integrations = model.Integrations.IsSpecified ?model.Integrations.Value
+ .Select(intergration => RestIntegration.Create(Discord, null, intergration)).ToImmutableArray() : null;
+ Verified = model.Verified;
+ FriendSync = model.FriendSync;
+ ShowActivity = model.ShowActivity;
+ Visibility = model.Visibility;
}
///
@@ -40,6 +63,6 @@ namespace Discord.Rest
/// Name of the connection.
///
public override string ToString() => Name;
- private string DebuggerDisplay => $"{Name} ({Id}, {Type}{(IsRevoked ? ", Revoked" : "")})";
+ private string DebuggerDisplay => $"{Name} ({Id}, {Type}{(IsRevoked.GetValueOrDefault() ? ", Revoked" : "")})";
}
}
diff --git a/src/Discord.Net.WebSocket/API/Gateway/IntegrationDeletedEvent.cs b/src/Discord.Net.WebSocket/API/Gateway/IntegrationDeletedEvent.cs
new file mode 100644
index 000000000..cf6e70ca6
--- /dev/null
+++ b/src/Discord.Net.WebSocket/API/Gateway/IntegrationDeletedEvent.cs
@@ -0,0 +1,14 @@
+using Newtonsoft.Json;
+
+namespace Discord.API.Gateway
+{
+ internal class IntegrationDeletedEvent
+ {
+ [JsonProperty("id")]
+ public ulong Id { get; set; }
+ [JsonProperty("guild_id")]
+ public ulong GuildId { get; set; }
+ [JsonProperty("application_id")]
+ public Optional ApplicationID { get; set; }
+ }
+}
diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs
index b8d3b6a10..c47591418 100644
--- a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs
+++ b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs
@@ -415,6 +415,32 @@ namespace Discord.WebSocket
#endregion
+ #region Integrations
+ /// Fired when an integration is created.
+ public event Func IntegrationCreated
+ {
+ add { _integrationCreated.Add(value); }
+ remove { _integrationCreated.Remove(value); }
+ }
+ internal readonly AsyncEvent> _integrationCreated = new AsyncEvent>();
+
+ /// Fired when an integration is updated.
+ public event Func IntegrationUpdated
+ {
+ add { _integrationUpdated.Add(value); }
+ remove { _integrationUpdated.Remove(value); }
+ }
+ internal readonly AsyncEvent> _integrationUpdated = new AsyncEvent>();
+
+ /// Fired when an integration is deleted.
+ public event Func, Task> IntegrationDeleted
+ {
+ add { _integrationDeleted.Add(value); }
+ remove { _integrationDeleted.Remove(value); }
+ }
+ internal readonly AsyncEvent, Task>> _integrationDeleted = new AsyncEvent, Task>>();
+ #endregion
+
#region Users
/// Fired when a user joins a guild.
public event Func UserJoined
diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs
index b692f0691..f33d89047 100644
--- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs
+++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs
@@ -2017,6 +2017,92 @@ namespace Discord.WebSocket
break;
#endregion
+ #region Integrations
+ case "INTEGRATION_CREATE":
+ {
+ await _gatewayLogger.DebugAsync("Received Dispatch (INTEGRATION_CREATE)").ConfigureAwait(false);
+
+ var data = (payload as JToken).ToObject(_serializer);
+
+ // Integrations from Gateway should always have guild IDs specified.
+ if (!data.GuildId.IsSpecified)
+ return;
+
+ var guild = State.GetGuild(data.GuildId.Value);
+
+ if (guild != null)
+ {
+ if (!guild.IsSynced)
+ {
+ await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
+ return;
+ }
+
+ await TimedInvokeAsync(_integrationCreated, nameof(IntegrationCreated), RestIntegration.Create(this, guild, data)).ConfigureAwait(false);
+ }
+ else
+ {
+ await UnknownGuildAsync(type, data.GuildId.Value).ConfigureAwait(false);
+ return;
+ }
+ }
+ break;
+ case "INTEGRATION_UPDATE":
+ {
+ await _gatewayLogger.DebugAsync("Received Dispatch (INTEGRATION_UPDATE)").ConfigureAwait(false);
+
+ var data = (payload as JToken).ToObject(_serializer);
+
+ // Integrations from Gateway should always have guild IDs specified.
+ if (!data.GuildId.IsSpecified)
+ return;
+
+ var guild = State.GetGuild(data.GuildId.Value);
+
+ if (guild != null)
+ {
+ if (!guild.IsSynced)
+ {
+ await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
+ return;
+ }
+
+ await TimedInvokeAsync(_integrationUpdated, nameof(IntegrationUpdated), RestIntegration.Create(this, guild, data)).ConfigureAwait(false);
+ }
+ else
+ {
+ await UnknownGuildAsync(type, data.GuildId.Value).ConfigureAwait(false);
+ return;
+ }
+ }
+ break;
+ case "INTEGRATION_DELETE":
+ {
+ await _gatewayLogger.DebugAsync("Received Dispatch (INTEGRATION_DELETE)").ConfigureAwait(false);
+
+ var data = (payload as JToken).ToObject(_serializer);
+
+ var guild = State.GetGuild(data.GuildId);
+
+ if (guild != null)
+ {
+ if (!guild.IsSynced)
+ {
+ await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
+ return;
+ }
+
+ await TimedInvokeAsync(_integrationDeleted, nameof(IntegrationDeleted), guild, data.Id, data.ApplicationID).ConfigureAwait(false);
+ }
+ else
+ {
+ await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false);
+ return;
+ }
+ }
+ break;
+ #endregion
+
#region Users
case "USER_UPDATE":
{
diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
index c4b756410..47bd57552 100644
--- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
+++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
@@ -847,10 +847,10 @@ namespace Discord.WebSocket
#endregion
#region Integrations
- public Task> GetIntegrationsAsync(RequestOptions options = null)
+ public Task> GetIntegrationsAsync(RequestOptions options = null)
=> GuildHelper.GetIntegrationsAsync(this, Discord, options);
- public Task CreateIntegrationAsync(ulong id, string type, RequestOptions options = null)
- => GuildHelper.CreateIntegrationAsync(this, Discord, id, type, options);
+ public Task DeleteIntegrationAsync(ulong id, RequestOptions options = null)
+ => GuildHelper.DeleteIntegrationAsync(this, Discord, id, options);
#endregion
#region Interactions
@@ -1888,11 +1888,11 @@ namespace Discord.WebSocket
=> await GetVoiceRegionsAsync(options).ConfigureAwait(false);
///
- async Task> IGuild.GetIntegrationsAsync(RequestOptions options)
+ async Task> IGuild.GetIntegrationsAsync(RequestOptions options)
=> await GetIntegrationsAsync(options).ConfigureAwait(false);
///
- async Task IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options)
- => await CreateIntegrationAsync(id, type, options).ConfigureAwait(false);
+ async Task IGuild.DeleteIntegrationAsync(ulong id, RequestOptions options)
+ => await DeleteIntegrationAsync(id, options).ConfigureAwait(false);
///
async Task> IGuild.GetInvitesAsync(RequestOptions options)