feature: Add INVITE_CREATE and INVITE_DELETE events (#1491)
* Add invite events (create and delete) * Removed unused using * Fixing IInviteMetadata properties * Add two new fields to the gateway event * Better event summary and remarks * Change how to assign to target variable Co-Authored-By: Joe4evr <jii.geugten@gmail.com> * Applying suggested changes to TargetUserType * Renaming NotDefined to Undefined * Fixing xml docs * Changed the summary style format Co-authored-by: Joe4evr <jii.geugten@gmail.com>
This commit is contained in:
14
src/Discord.Net.Core/Entities/Invites/TargetUserType.cs
Normal file
14
src/Discord.Net.Core/Entities/Invites/TargetUserType.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace Discord
|
||||||
|
{
|
||||||
|
public enum TargetUserType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The invite whose target user type is not defined.
|
||||||
|
/// </summary>
|
||||||
|
Undefined = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// The invite is for a Go Live stream.
|
||||||
|
/// </summary>
|
||||||
|
Stream = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/Discord.Net.WebSocket/API/Gateway/InviteCreateEvent.cs
Normal file
31
src/Discord.Net.WebSocket/API/Gateway/InviteCreateEvent.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Discord.API.Gateway
|
||||||
|
{
|
||||||
|
internal class InviteCreateEvent
|
||||||
|
{
|
||||||
|
[JsonProperty("channel_id")]
|
||||||
|
public ulong ChannelId { get; set; }
|
||||||
|
[JsonProperty("code")]
|
||||||
|
public string Code { get; set; }
|
||||||
|
[JsonProperty("created_at")]
|
||||||
|
public DateTimeOffset CreatedAt { get; set; }
|
||||||
|
[JsonProperty("guild_id")]
|
||||||
|
public Optional<ulong> GuildId { get; set; }
|
||||||
|
[JsonProperty("inviter")]
|
||||||
|
public Optional<User> Inviter { get; set; }
|
||||||
|
[JsonProperty("max_age")]
|
||||||
|
public int MaxAge { get; set; }
|
||||||
|
[JsonProperty("max_uses")]
|
||||||
|
public int MaxUses { get; set; }
|
||||||
|
[JsonProperty("target_user")]
|
||||||
|
public Optional<User> TargetUser { get; set; }
|
||||||
|
[JsonProperty("target_user_type")]
|
||||||
|
public Optional<TargetUserType> TargetUserType { get; set; }
|
||||||
|
[JsonProperty("temporary")]
|
||||||
|
public bool Temporary { get; set; }
|
||||||
|
[JsonProperty("uses")]
|
||||||
|
public int Uses { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/Discord.Net.WebSocket/API/Gateway/InviteDeleteEvent.cs
Normal file
14
src/Discord.Net.WebSocket/API/Gateway/InviteDeleteEvent.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Discord.API.Gateway
|
||||||
|
{
|
||||||
|
internal class InviteDeleteEvent
|
||||||
|
{
|
||||||
|
[JsonProperty("channel_id")]
|
||||||
|
public ulong ChannelId { get; set; }
|
||||||
|
[JsonProperty("code")]
|
||||||
|
public string Code { get; set; }
|
||||||
|
[JsonProperty("guild_id")]
|
||||||
|
public Optional<ulong> GuildId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -389,5 +389,47 @@ namespace Discord.WebSocket
|
|||||||
remove { _recipientRemovedEvent.Remove(value); }
|
remove { _recipientRemovedEvent.Remove(value); }
|
||||||
}
|
}
|
||||||
internal readonly AsyncEvent<Func<SocketGroupUser, Task>> _recipientRemovedEvent = new AsyncEvent<Func<SocketGroupUser, Task>>();
|
internal readonly AsyncEvent<Func<SocketGroupUser, Task>> _recipientRemovedEvent = new AsyncEvent<Func<SocketGroupUser, Task>>();
|
||||||
|
|
||||||
|
//Invites
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when an invite is created.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// This event is fired when an invite is created. The event handler must return a
|
||||||
|
/// <see cref="Task"/> and accept a <see cref="SocketInvite"/> as its parameter.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The invite created will be passed into the <see cref="SocketInvite"/> parameter.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
public event Func<SocketInvite, Task> InviteCreated
|
||||||
|
{
|
||||||
|
add { _inviteCreatedEvent.Add(value); }
|
||||||
|
remove { _inviteCreatedEvent.Remove(value); }
|
||||||
|
}
|
||||||
|
internal readonly AsyncEvent<Func<SocketInvite, Task>> _inviteCreatedEvent = new AsyncEvent<Func<SocketInvite, Task>>();
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when an invite is deleted.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// This event is fired when an invite is deleted. The event handler must return
|
||||||
|
/// a <see cref="Task"/> and accept a <see cref="SocketGuildChannel"/> and
|
||||||
|
/// <see cref="string"/> as its parameter.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The channel where this invite was created will be passed into the <see cref="SocketGuildChannel"/> parameter.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The code of the deleted invite will be passed into the <see cref="string"/> parameter.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
public event Func<SocketGuildChannel, string, Task> InviteDeleted
|
||||||
|
{
|
||||||
|
add { _inviteDeletedEvent.Add(value); }
|
||||||
|
remove { _inviteDeletedEvent.Remove(value); }
|
||||||
|
}
|
||||||
|
internal readonly AsyncEvent<Func<SocketGuildChannel, string, Task>> _inviteDeletedEvent = new AsyncEvent<Func<SocketGuildChannel, string, Task>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,9 @@ namespace Discord.WebSocket
|
|||||||
client.UserIsTyping += (oldUser, newUser) => _userIsTypingEvent.InvokeAsync(oldUser, newUser);
|
client.UserIsTyping += (oldUser, newUser) => _userIsTypingEvent.InvokeAsync(oldUser, newUser);
|
||||||
client.RecipientAdded += (user) => _recipientAddedEvent.InvokeAsync(user);
|
client.RecipientAdded += (user) => _recipientAddedEvent.InvokeAsync(user);
|
||||||
client.RecipientRemoved += (user) => _recipientRemovedEvent.InvokeAsync(user);
|
client.RecipientRemoved += (user) => _recipientRemovedEvent.InvokeAsync(user);
|
||||||
|
|
||||||
|
client.InviteCreated += (invite) => _inviteCreatedEvent.InvokeAsync(invite);
|
||||||
|
client.InviteDeleted += (channel, invite) => _inviteDeletedEvent.InvokeAsync(channel, invite);
|
||||||
}
|
}
|
||||||
|
|
||||||
//IDiscordClient
|
//IDiscordClient
|
||||||
|
|||||||
@@ -1688,6 +1688,64 @@ namespace Discord.WebSocket
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//Invites
|
||||||
|
case "INVITE_CREATE":
|
||||||
|
{
|
||||||
|
await _gatewayLogger.DebugAsync("Received Dispatch (INVITE_CREATE)").ConfigureAwait(false);
|
||||||
|
|
||||||
|
var data = (payload as JToken).ToObject<API.Gateway.InviteCreateEvent>(_serializer);
|
||||||
|
if (State.GetChannel(data.ChannelId) is SocketGuildChannel channel)
|
||||||
|
{
|
||||||
|
var guild = channel.Guild;
|
||||||
|
if (!guild.IsSynced)
|
||||||
|
{
|
||||||
|
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketGuildUser inviter = data.Inviter.IsSpecified
|
||||||
|
? (guild.GetUser(data.Inviter.Value.Id) ?? guild.AddOrUpdateUser(data.Inviter.Value))
|
||||||
|
: null;
|
||||||
|
|
||||||
|
SocketUser target = data.TargetUser.IsSpecified
|
||||||
|
? (guild.GetUser(data.TargetUser.Value.Id) ?? (SocketUser)SocketUnknownUser.Create(this, State, data.TargetUser.Value))
|
||||||
|
: null;
|
||||||
|
|
||||||
|
var invite = SocketInvite.Create(this, guild, channel, inviter, target, data);
|
||||||
|
|
||||||
|
await TimedInvokeAsync(_inviteCreatedEvent, nameof(InviteCreated), invite).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "INVITE_DELETE":
|
||||||
|
{
|
||||||
|
await _gatewayLogger.DebugAsync("Received Dispatch (INVITE_DELETE)").ConfigureAwait(false);
|
||||||
|
|
||||||
|
var data = (payload as JToken).ToObject<API.Gateway.InviteDeleteEvent>(_serializer);
|
||||||
|
if (State.GetChannel(data.ChannelId) is SocketGuildChannel channel)
|
||||||
|
{
|
||||||
|
var guild = channel.Guild;
|
||||||
|
if (!guild.IsSynced)
|
||||||
|
{
|
||||||
|
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await TimedInvokeAsync(_inviteDeletedEvent, nameof(InviteDeleted), channel, data.Code).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
//Ignored (User only)
|
//Ignored (User only)
|
||||||
case "CHANNEL_PINS_ACK":
|
case "CHANNEL_PINS_ACK":
|
||||||
await _gatewayLogger.DebugAsync("Ignored Dispatch (CHANNEL_PINS_ACK)").ConfigureAwait(false);
|
await _gatewayLogger.DebugAsync("Ignored Dispatch (CHANNEL_PINS_ACK)").ConfigureAwait(false);
|
||||||
|
|||||||
143
src/Discord.Net.WebSocket/Entities/Invites/SocketInvite.cs
Normal file
143
src/Discord.Net.WebSocket/Entities/Invites/SocketInvite.cs
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
using Discord.Rest;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Model = Discord.API.Gateway.InviteCreateEvent;
|
||||||
|
|
||||||
|
namespace Discord.WebSocket
|
||||||
|
{
|
||||||
|
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||||
|
public class SocketInvite : SocketEntity<string>, IInviteMetadata
|
||||||
|
{
|
||||||
|
private long _createdAtTicks;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ulong ChannelId { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channel where this invite was created.
|
||||||
|
/// </summary>
|
||||||
|
public SocketGuildChannel Channel { get; private set; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ulong? GuildId { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the guild where this invite was created.
|
||||||
|
/// </summary>
|
||||||
|
public SocketGuild Guild { get; private set; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
ChannelType IInvite.ChannelType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (Channel)
|
||||||
|
{
|
||||||
|
case IVoiceChannel voiceChannel: return ChannelType.Voice;
|
||||||
|
case ICategoryChannel categoryChannel: return ChannelType.Category;
|
||||||
|
case IDMChannel dmChannel: return ChannelType.DM;
|
||||||
|
case IGroupChannel groupChannel: return ChannelType.Group;
|
||||||
|
case SocketNewsChannel socketNewsChannel: return ChannelType.News;
|
||||||
|
case ITextChannel textChannel: return ChannelType.Text;
|
||||||
|
default: throw new InvalidOperationException("Invalid channel type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
|
string IInvite.ChannelName => Channel.Name;
|
||||||
|
/// <inheritdoc />
|
||||||
|
string IInvite.GuildName => Guild.Name;
|
||||||
|
/// <inheritdoc />
|
||||||
|
int? IInvite.PresenceCount => throw new NotImplementedException();
|
||||||
|
/// <inheritdoc />
|
||||||
|
int? IInvite.MemberCount => throw new NotImplementedException();
|
||||||
|
/// <inheritdoc />
|
||||||
|
bool IInviteMetadata.IsRevoked => throw new NotImplementedException();
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsTemporary { get; private set; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
int? IInviteMetadata.MaxAge { get => MaxAge; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
int? IInviteMetadata.MaxUses { get => MaxUses; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
int? IInviteMetadata.Uses { get => Uses; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the time (in seconds) until the invite expires.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxAge { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the max number of uses this invite may have.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxUses { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of times this invite has been used.
|
||||||
|
/// </summary>
|
||||||
|
public int Uses { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user that created this invite if available.
|
||||||
|
/// </summary>
|
||||||
|
public SocketGuildUser Inviter { get; private set; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
DateTimeOffset? IInviteMetadata.CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets when this invite was created.
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user targeted by this invite if available.
|
||||||
|
/// </summary>
|
||||||
|
public SocketUser TargetUser { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type of the user targeted by this invite.
|
||||||
|
/// </summary>
|
||||||
|
public TargetUserType TargetUserType { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Code => Id;
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Url => $"{DiscordConfig.InviteUrl}{Code}";
|
||||||
|
|
||||||
|
internal SocketInvite(DiscordSocketClient discord, SocketGuild guild, SocketGuildChannel channel, SocketGuildUser inviter, SocketUser target, string id)
|
||||||
|
: base(discord, id)
|
||||||
|
{
|
||||||
|
Guild = guild;
|
||||||
|
Channel = channel;
|
||||||
|
Inviter = inviter;
|
||||||
|
TargetUser = target;
|
||||||
|
}
|
||||||
|
internal static SocketInvite Create(DiscordSocketClient discord, SocketGuild guild, SocketGuildChannel channel, SocketGuildUser inviter, SocketUser target, Model model)
|
||||||
|
{
|
||||||
|
var entity = new SocketInvite(discord, guild, channel, inviter, target, model.Code);
|
||||||
|
entity.Update(model);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
internal void Update(Model model)
|
||||||
|
{
|
||||||
|
ChannelId = model.ChannelId;
|
||||||
|
GuildId = model.GuildId.IsSpecified ? model.GuildId.Value : Guild.Id;
|
||||||
|
IsTemporary = model.Temporary;
|
||||||
|
MaxAge = model.MaxAge;
|
||||||
|
MaxUses = model.MaxUses;
|
||||||
|
Uses = model.Uses;
|
||||||
|
_createdAtTicks = model.CreatedAt.UtcTicks;
|
||||||
|
TargetUserType = model.TargetUserType.IsSpecified ? model.TargetUserType.Value : TargetUserType.Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task DeleteAsync(RequestOptions options = null)
|
||||||
|
=> InviteHelper.DeleteAsync(this, Discord, options);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the URL of the invite.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A string that resolves to the Url of the invite.
|
||||||
|
/// </returns>
|
||||||
|
public override string ToString() => Url;
|
||||||
|
private string DebuggerDisplay => $"{Url} ({Guild?.Name} / {Channel.Name})";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
IGuild IInvite.Guild => Guild;
|
||||||
|
/// <inheritdoc />
|
||||||
|
IChannel IInvite.Channel => Channel;
|
||||||
|
/// <inheritdoc />
|
||||||
|
IUser IInviteMetadata.Inviter => Inviter;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user