Browse Source

fix integration models; add integration events

pull/2168/head
FeroxFoxxo 3 years ago
parent
commit
753b58d60d
25 changed files with 547 additions and 210 deletions
  1. +0
    -21
      src/Discord.Net.Core/Entities/Guilds/GuildIntegrationProperties.cs
  2. +15
    -2
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  3. +0
    -18
      src/Discord.Net.Core/Entities/Guilds/IntegrationAccount.cs
  4. +36
    -13
      src/Discord.Net.Core/Entities/Integrations/IIntegration.cs
  5. +23
    -0
      src/Discord.Net.Core/Entities/Integrations/IIntegrationAccount.cs
  6. +33
    -0
      src/Discord.Net.Core/Entities/Integrations/IIntegrationApplication.cs
  7. +17
    -0
      src/Discord.Net.Core/Entities/Integrations/IntegrationExpireBehavior.cs
  8. +14
    -0
      src/Discord.Net.Core/Entities/Users/ConnectionVisibility.cs
  9. +14
    -11
      src/Discord.Net.Core/Entities/Users/IConnection.cs
  10. +13
    -5
      src/Discord.Net.Rest/API/Common/Connection.cs
  11. +18
    -7
      src/Discord.Net.Rest/API/Common/Integration.cs
  12. +1
    -1
      src/Discord.Net.Rest/API/Common/IntegrationAccount.cs
  13. +20
    -0
      src/Discord.Net.Rest/API/Common/IntegrationApplication.cs
  14. +1
    -1
      src/Discord.Net.Rest/ClientHelper.cs
  15. +4
    -4
      src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
  16. +4
    -4
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  17. +0
    -104
      src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs
  18. +104
    -0
      src/Discord.Net.Rest/Entities/Integrations/RestIntegration.cs
  19. +26
    -0
      src/Discord.Net.Rest/Entities/Integrations/RestIntegrationAccount.cs
  20. +36
    -0
      src/Discord.Net.Rest/Entities/Integrations/RestIntegrationApplication.cs
  21. +38
    -15
      src/Discord.Net.Rest/Entities/Users/RestConnection.cs
  22. +14
    -0
      src/Discord.Net.WebSocket/API/Gateway/IntegrationDeletedEvent.cs
  23. +26
    -0
      src/Discord.Net.WebSocket/BaseSocketClient.Events.cs
  24. +86
    -0
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  25. +4
    -4
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs

+ 0
- 21
src/Discord.Net.Core/Entities/Guilds/GuildIntegrationProperties.cs View File

@@ -1,21 +0,0 @@
namespace Discord
{
/// <summary>
/// Provides properties used to modify an <see cref="IGuildIntegration" /> with the specified changes.
/// </summary>
public class GuildIntegrationProperties
{
/// <summary>
/// Gets or sets the behavior when an integration subscription lapses.
/// </summary>
public Optional<int> ExpireBehavior { get; set; }
/// <summary>
/// Gets or sets the period (in seconds) where the integration will ignore lapsed subscriptions.
/// </summary>
public Optional<int> ExpireGracePeriod { get; set; }
/// <summary>
/// Gets or sets whether emoticons should be synced for this integration.
/// </summary>
public Optional<bool> EnableEmoticons { get; set; }
}
}

+ 15
- 2
src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -718,8 +718,21 @@ namespace Discord
/// </returns>
Task<IReadOnlyCollection<IVoiceRegion>> GetVoiceRegionsAsync(RequestOptions options = null);

Task<IReadOnlyCollection<IGuildIntegration>> GetIntegrationsAsync(RequestOptions options = null);
Task<IGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null);
/// <summary>
///
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
Task<IReadOnlyCollection<IIntegration>> GetIntegrationsAsync(RequestOptions options = null);

/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="type"></param>
/// <param name="options"></param>
/// <returns></returns>
Task<IIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null);

/// <summary>
/// Gets a collection of all invites in this guild.


+ 0
- 18
src/Discord.Net.Core/Entities/Guilds/IntegrationAccount.cs View File

@@ -1,18 +0,0 @@
using System.Diagnostics;

namespace Discord
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct IntegrationAccount
{
/// <summary> Gets the ID of the account. </summary>
/// <returns> A <see cref="string"/> unique identifier of this integration account. </returns>
public string Id { get; }
/// <summary> Gets the name of the account. </summary>
/// <returns> A string containing the name of this integration account. </returns>
public string Name { get; private set; }

public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id})";
}
}

src/Discord.Net.Core/Entities/Guilds/IGuildIntegration.cs → src/Discord.Net.Core/Entities/Integrations/IIntegration.cs View File

@@ -3,15 +3,16 @@ using System;
namespace Discord
{
/// <summary>
/// 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.
/// </summary>
public interface IGuildIntegration
public interface IIntegration
{
/// <summary>
/// Gets the integration ID.
/// </summary>
/// <returns>
/// An <see cref="UInt64"/> representing the unique identifier value of this integration.
/// A <see cref="ulong"/> representing the unique identifier value of this integration.
/// </returns>
ulong Id { get; }
/// <summary>
@@ -45,30 +46,52 @@ namespace Discord
/// <returns>
/// <c>true</c> if this integration is syncing; otherwise <c>false</c>.
/// </returns>
bool IsSyncing { get; }
bool? IsSyncing { get; }
/// <summary>
/// Gets the ID that this integration uses for "subscribers".
/// </summary>
ulong ExpireBehavior { get; }
ulong? RoleId { get; }
/// <summary>
/// Gets whether emoticons should be synced for this integration (twitch only currently).
/// </summary>
bool? HasEnabledEmoticons { get; }
/// <summary>
/// Gets the behavior of expiring subscribers.
/// </summary>
IntegrationExpireBehavior? ExpireBehavior { get; }
/// <summary>
/// Gets the grace period before expiring "subscribers".
/// </summary>
ulong ExpireGracePeriod { get; }
int? ExpireGracePeriod { get; }
/// <summary>
/// Gets the user for this integration.
/// </summary>
IUser User { get; }
/// <summary>
/// Gets integration account information.
/// </summary>
IIntegrationAccount Account { get; }
/// <summary>
/// Gets when this integration was last synced.
/// </summary>
/// <returns>
/// A <see cref="DateTimeOffset"/> containing a date and time of day when the integration was last synced.
/// Gets a <see cref="DateTimeOffset"/> containing a date and time of day when the integration was last synced.
/// </returns>
DateTimeOffset SyncedAt { get; }
DateTimeOffset? SyncedAt { get; }
/// <summary>
/// Gets integration account information.
/// Gets how many subscribers this integration has.
/// </summary>
IntegrationAccount Account { get; }

int? SubscriberCount { get; }
/// <summary>
/// Gets whether this integration been revoked.
/// </summary>
bool? IsRevoked { get; }
/// <summary>
/// Gets the bot/OAuth2 application for a discord integration.
/// </summary>
IIntegrationApplication Application { get; }
IGuild Guild { get; }
ulong GuildId { get; }
ulong RoleId { get; }
IUser User { get; }
}
}

+ 23
- 0
src/Discord.Net.Core/Entities/Integrations/IIntegrationAccount.cs View File

@@ -0,0 +1,23 @@
namespace Discord
{
/// <summary>
/// Provides the account information for an <see cref="IIntegration" />.
/// </summary>
public interface IIntegrationAccount
{
/// <summary>
/// Gets the ID of the account.
/// </summary>
/// <returns>
/// A <see cref="string"/> unique identifier of this integration account.
/// </returns>
string Id { get; }
/// <summary>
/// Gets the name of the account.
/// </summary>
/// <returns>
/// A string containing the name of this integration account.
/// </returns>
string Name { get; }
}
}

+ 33
- 0
src/Discord.Net.Core/Entities/Integrations/IIntegrationApplication.cs View File

@@ -0,0 +1,33 @@
namespace Discord
{
/// <summary>
/// Provides the bot/OAuth2 application for an <see cref="IIntegration" />.
/// </summary>
public interface IIntegrationApplication
{
/// <summary>
/// Gets the id of the app.
/// </summary>
public ulong Id { get; }
/// <summary>
/// Gets the name of the app.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the icon hash of the app.
/// </summary>
public string Icon { get; }
/// <summary>
/// Gets the description of the app.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the summary of the app.
/// </summary>
public string Summary { get; }
/// <summary>
/// Gets the bot associated with this application.
/// </summary>
public IUser Bot { get; }
}
}

+ 17
- 0
src/Discord.Net.Core/Entities/Integrations/IntegrationExpireBehavior.cs View File

@@ -0,0 +1,17 @@
namespace Discord
{
/// <summary>
/// The behavior of expiring subscribers for an <see cref="IIntegration" />.
/// </summary>
public enum IntegrationExpireBehavior
{
/// <summary>
/// Removes a role from an expired subscriber.
/// </summary>
RemoveRole = 0,
/// <summary>
/// Kicks an expired subscriber from the guild.
/// </summary>
Kick = 1
}
}

+ 14
- 0
src/Discord.Net.Core/Entities/Users/ConnectionVisibility.cs View File

@@ -0,0 +1,14 @@
namespace Discord
{
public enum ConnectionVisibility
{
/// <summary>
/// Invisible to everyone except the user themselves.
/// </summary>
None = 0,
/// <summary>
/// Visible to everyone.
/// </summary>
Everyone = 1
}
}

+ 14
- 11
src/Discord.Net.Core/Entities/Users/IConnection.cs View File

@@ -7,21 +7,24 @@ namespace Discord
/// <summary> Gets the ID of the connection account. </summary>
/// <returns> A <see cref="string"/> representing the unique identifier value of this connection. </returns>
string Id { get; }
/// <summary> Gets the service of the connection (twitch, youtube). </summary>
/// <returns> A string containing the name of this type of connection. </returns>
string Type { get; }
/// <summary> Gets the username of the connection account. </summary>
/// <returns> A string containing the name of this connection. </returns>
string Name { get; }
/// <summary> Gets the service of the connection (twitch, youtube). </summary>
/// <returns> A string containing the name of this type of connection. </returns>
string Type { get; }
/// <summary> Gets whether the connection is revoked. </summary>
/// <returns> A value which if true indicates that this connection has been revoked, otherwise false. </returns>
bool IsRevoked { get; }

/// <summary> Gets a <see cref="IReadOnlyCollection{T}"/> of integration IDs. </summary>
/// <returns>
/// An <see cref="IReadOnlyCollection{T}"/> containing <see cref="ulong"/>
/// representations of unique identifier values of integrations.
/// </returns>
IReadOnlyCollection<ulong> IntegrationIds { get; }
bool? IsRevoked { get; }
/// <summary> Gets a <see cref="IReadOnlyCollection{T}"/> of integration parials. </summary>
IReadOnlyCollection<IIntegration> Integrations { get; }
/// <summary> Gets whether the connection is verified. </summary>
public bool Verified { get; }
/// <summary> Gets whether friend sync is enabled for this connection. </summary>
public bool FriendSync { get; }
/// <summary> Gets whether activities related to this connection will be shown in presence updates. </summary>
public bool ShowActivity { get; }
/// <summary> Visibility of this connection. </summary>
public ConnectionVisibility Visibility { get; }
}
}

+ 13
- 5
src/Discord.Net.Rest/API/Common/Connection.cs View File

@@ -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<bool> Revoked { get; set; }
[JsonProperty("integrations")]
public IReadOnlyCollection<ulong> Integrations { get; set; }
public Optional<IReadOnlyCollection<Integration>> 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; }

}
}

+ 18
- 7
src/Discord.Net.Rest/API/Common/Integration.cs View File

@@ -5,6 +5,9 @@ namespace Discord.API
{
internal class Integration
{
[JsonProperty("guild_id")]
public Optional<ulong> 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<bool> Syncing { get; set; }
[JsonProperty("role_id")]
public ulong RoleId { get; set; }
public ulong? RoleId { get; set; }
[JsonProperty("enable_emoticons")]
public Optional<bool> EnableEmoticons { get; set; }
[JsonProperty("expire_behavior")]
public ulong ExpireBehavior { get; set; }
public Optional<IntegrationExpireBehavior> ExpireBehavior { get; set; }
[JsonProperty("expire_grace_period")]
public ulong ExpireGracePeriod { get; set; }
public Optional<int> ExpireGracePeriod { get; set; }
[JsonProperty("user")]
public User User { get; set; }
public Optional<User> User { get; set; }
[JsonProperty("account")]
public IntegrationAccount Account { get; set; }
public Optional<IntegrationAccount> Account { get; set; }
[JsonProperty("synced_at")]
public DateTimeOffset SyncedAt { get; set; }
public Optional<DateTimeOffset> SyncedAt { get; set; }
[JsonProperty("subscriber_count")]
public Optional<int> SubscriberAccount { get; set; }
[JsonProperty("revoked")]
public Optional<bool> Revoked { get; set; }
[JsonProperty("application")]
public Optional<IntegrationApplication> Application { get; set; }
}
}

+ 1
- 1
src/Discord.Net.Rest/API/Common/IntegrationAccount.cs View File

@@ -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; }
}


+ 20
- 0
src/Discord.Net.Rest/API/Common/IntegrationApplication.cs View File

@@ -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<string> Icon { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("summary")]
public string Summary { get; set; }
[JsonProperty("bot")]
public Optional<User> Bot { get; set; }
}
}

+ 1
- 1
src/Discord.Net.Rest/ClientHelper.cs View File

@@ -49,7 +49,7 @@ namespace Discord.Rest
public static async Task<IReadOnlyCollection<RestConnection>> 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<RestInviteMetadata> GetInviteAsync(BaseDiscordClient client,


+ 4
- 4
src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs View File

@@ -305,18 +305,18 @@ namespace Discord.Rest
#endregion

#region Integrations
public static async Task<IReadOnlyCollection<RestGuildIntegration>> GetIntegrationsAsync(IGuild guild, BaseDiscordClient client,
public static async Task<IReadOnlyCollection<RestIntegration>> 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();
return models.Select(x => RestIntegration.Create(client, guild, x)).ToImmutableArray();
}
public static async Task<RestGuildIntegration> CreateIntegrationAsync(IGuild guild, BaseDiscordClient client,
public static async Task<RestIntegration> 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);
return RestIntegration.Create(client, guild, model);
}
#endregion



+ 4
- 4
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs View File

@@ -720,9 +720,9 @@ namespace Discord.Rest
#endregion

#region Integrations
public Task<IReadOnlyCollection<RestGuildIntegration>> GetIntegrationsAsync(RequestOptions options = null)
public Task<IReadOnlyCollection<RestIntegration>> GetIntegrationsAsync(RequestOptions options = null)
=> GuildHelper.GetIntegrationsAsync(this, Discord, options);
public Task<RestGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null)
public Task<RestIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null)
=> GuildHelper.CreateIntegrationAsync(this, Discord, id, type, options);
#endregion

@@ -1375,10 +1375,10 @@ namespace Discord.Rest
=> await GetVoiceRegionsAsync(options).ConfigureAwait(false);

/// <inheritdoc />
async Task<IReadOnlyCollection<IGuildIntegration>> IGuild.GetIntegrationsAsync(RequestOptions options)
async Task<IReadOnlyCollection<IIntegration>> IGuild.GetIntegrationsAsync(RequestOptions options)
=> await GetIntegrationsAsync(options).ConfigureAwait(false);
/// <inheritdoc />
async Task<IGuildIntegration> IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options)
async Task<IIntegration> IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options)
=> await CreateIntegrationAsync(id, type, options).ConfigureAwait(false);

/// <inheritdoc />


+ 0
- 104
src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs View File

@@ -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<ulong>, IGuildIntegration
{
private long _syncedAtTicks;

/// <inheritdoc />
public string Name { get; private set; }
/// <inheritdoc />
public string Type { get; private set; }
/// <inheritdoc />
public bool IsEnabled { get; private set; }
/// <inheritdoc />
public bool IsSyncing { get; private set; }
/// <inheritdoc />
public ulong ExpireBehavior { get; private set; }
/// <inheritdoc />
public ulong ExpireGracePeriod { get; private set; }
/// <inheritdoc />
public ulong GuildId { get; private set; }
/// <inheritdoc />
public ulong RoleId { get; private set; }
public RestUser User { get; private set; }
/// <inheritdoc />
public IntegrationAccount Account { get; private set; }
internal IGuild Guild { get; private set; }

/// <inheritdoc />
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<GuildIntegrationProperties> 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" : "")})";

/// <inheritdoc />
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.");
}
}
/// <inheritdoc />
IUser IGuildIntegration.User => User;
}
}

+ 104
- 0
src/Discord.Net.Rest/Entities/Integrations/RestIntegration.cs View File

@@ -0,0 +1,104 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Model = Discord.API.Integration;

namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestIntegration : RestEntity<ulong>, IIntegration
{
private long? _syncedAtTicks;

/// <inheritdoc />
public string Name { get; private set; }
/// <inheritdoc />
public string Type { get; private set; }
/// <inheritdoc />
public bool IsEnabled { get; private set; }
/// <inheritdoc />
public bool? IsSyncing { get; private set; }
/// <inheritdoc />
public ulong? RoleId { get; private set; }
/// <inheritdoc />
public bool? HasEnabledEmoticons { get; private set; }
/// <inheritdoc />
public IntegrationExpireBehavior? ExpireBehavior { get; private set; }
/// <inheritdoc />
public int? ExpireGracePeriod { get; private set; }
/// <inheritdoc />
IUser IIntegration.User => User;
/// <inheritdoc />
public IIntegrationAccount Account { get; private set; }
/// <inheritdoc />
public DateTimeOffset? SyncedAt => DateTimeUtils.FromTicks(_syncedAtTicks);
/// <inheritdoc />
public int? SubscriberCount { get; private set; }
/// <inheritdoc />
public bool? IsRevoked { get; private set; }
/// <inheritdoc />
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.HasValue ? 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.DeleteGuildIntegrationAsync(GuildId, Id).ConfigureAwait(false);
}

public async Task SyncAsync()
{
await Discord.ApiClient.SyncGuildIntegrationAsync(GuildId, Id).ConfigureAwait(false);
}

public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id}{(IsEnabled ? ", Enabled" : "")})";

/// <inheritdoc />
public ulong GuildId { get; private set; }

/// <inheritdoc />
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.");
}
}
}
}

+ 26
- 0
src/Discord.Net.Rest/Entities/Integrations/RestIntegrationAccount.cs View File

@@ -0,0 +1,26 @@
using Model = Discord.API.IntegrationAccount;

namespace Discord.Rest
{
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;
}
}
}

+ 36
- 0
src/Discord.Net.Rest/Entities/Integrations/RestIntegrationApplication.cs View File

@@ -0,0 +1,36 @@
using Model = Discord.API.IntegrationApplication;

namespace Discord.Rest
{
public class RestIntegrationApplication : RestEntity<ulong>, 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);
}
}
}

+ 38
- 15
src/Discord.Net.Rest/Entities/Users/RestConnection.cs View File

@@ -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
{
/// <inheritdoc />
public string Id { get; }
public string Id { get; private set; }
/// <inheritdoc />
public string Type { get; }
public string Name { get; private set; }
/// <inheritdoc />
public string Name { get; }
public string Type { get; private set; }
/// <inheritdoc />
public bool IsRevoked { get; }
public bool? IsRevoked { get; private set; }
/// <inheritdoc />
public IReadOnlyCollection<ulong> IntegrationIds { get; }
public IReadOnlyCollection<IIntegration> Integrations { get; private set; }
/// <inheritdoc />
public bool Verified { get; private set; }
/// <inheritdoc />
public bool FriendSync { get; private set; }
/// <inheritdoc />
public bool ShowActivity { get; private set; }
/// <inheritdoc />
public ConnectionVisibility Visibility { get; private set; }

internal RestConnection(string id, string type, string name, bool isRevoked, IReadOnlyCollection<ulong> 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;
}

/// <summary>
@@ -40,6 +63,6 @@ namespace Discord.Rest
/// Name of the connection.
/// </returns>
public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id}, {Type}{(IsRevoked ? ", Revoked" : "")})";
private string DebuggerDisplay => $"{Name} ({Id}, {Type}{(IsRevoked.GetValueOrDefault() ? ", Revoked" : "")})";
}
}

+ 14
- 0
src/Discord.Net.WebSocket/API/Gateway/IntegrationDeletedEvent.cs View File

@@ -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<ulong> ApplicationID { get; set; }
}
}

+ 26
- 0
src/Discord.Net.WebSocket/BaseSocketClient.Events.cs View File

@@ -415,6 +415,32 @@ namespace Discord.WebSocket

#endregion

#region Integrations
/// <summary> Fired when an integration is created. </summary>
public event Func<IIntegration, Task> IntegrationCreated
{
add { _integrationCreated.Add(value); }
remove { _integrationCreated.Remove(value); }
}
internal readonly AsyncEvent<Func<IIntegration, Task>> _integrationCreated = new AsyncEvent<Func<IIntegration, Task>>();

/// <summary> Fired when an integration is updated. </summary>
public event Func<IIntegration, Task> IntegrationUpdated
{
add { _integrationUpdated.Add(value); }
remove { _integrationUpdated.Remove(value); }
}
internal readonly AsyncEvent<Func<IIntegration, Task>> _integrationUpdated = new AsyncEvent<Func<IIntegration, Task>>();

/// <summary> Fired when an integration is deleted. </summary>
public event Func<IGuild, ulong, Optional<ulong>, Task> IntegrationDeleted
{
add { _integrationDeleted.Add(value); }
remove { _integrationDeleted.Remove(value); }
}
internal readonly AsyncEvent<Func<IGuild, ulong, Optional<ulong>, Task>> _integrationDeleted = new AsyncEvent<Func<IGuild, ulong, Optional<ulong>, Task>>();
#endregion

#region Users
/// <summary> Fired when a user joins a guild. </summary>
public event Func<SocketGuildUser, Task> UserJoined


+ 86
- 0
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -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<Integration>(_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<Integration>(_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<IntegrationDeletedEvent>(_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":
{


+ 4
- 4
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -847,9 +847,9 @@ namespace Discord.WebSocket
#endregion

#region Integrations
public Task<IReadOnlyCollection<RestGuildIntegration>> GetIntegrationsAsync(RequestOptions options = null)
public Task<IReadOnlyCollection<RestIntegration>> GetIntegrationsAsync(RequestOptions options = null)
=> GuildHelper.GetIntegrationsAsync(this, Discord, options);
public Task<RestGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null)
public Task<RestIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null)
=> GuildHelper.CreateIntegrationAsync(this, Discord, id, type, options);
#endregion

@@ -1892,10 +1892,10 @@ namespace Discord.WebSocket
=> await GetVoiceRegionsAsync(options).ConfigureAwait(false);

/// <inheritdoc />
async Task<IReadOnlyCollection<IGuildIntegration>> IGuild.GetIntegrationsAsync(RequestOptions options)
async Task<IReadOnlyCollection<IIntegration>> IGuild.GetIntegrationsAsync(RequestOptions options)
=> await GetIntegrationsAsync(options).ConfigureAwait(false);
/// <inheritdoc />
async Task<IGuildIntegration> IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options)
async Task<IIntegration> IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options)
=> await CreateIntegrationAsync(id, type, options).ConfigureAwait(false);

/// <inheritdoc />


Loading…
Cancel
Save