Browse Source

Guilduser timeouts and MODERATE_MEMBERS permission (#2003)

Co-Authored-By: Armano den Boef <68127614+Rozen4334@users.noreply.github.com>
tags/3.1.0
Quin Lynch GitHub 3 years ago
parent
commit
144741e7c4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 157 additions and 11 deletions
  1. +5
    -2
      src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs
  2. +12
    -6
      src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
  3. +10
    -1
      src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs
  4. +28
    -0
      src/Discord.Net.Core/Entities/Users/IGuildUser.cs
  5. +2
    -0
      src/Discord.Net.Rest/API/Common/GuildMember.cs
  6. +3
    -0
      src/Discord.Net.Rest/API/Rest/ModifyGuildMemberParams.cs
  7. +21
    -0
      src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs
  8. +8
    -0
      src/Discord.Net.Rest/Entities/Users/RestWebhookUser.cs
  9. +28
    -1
      src/Discord.Net.Rest/Entities/Users/UserHelper.cs
  10. +20
    -1
      src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
  11. +8
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs
  12. +10
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
  13. +2
    -0
      test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs

+ 5
- 2
src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs View File

@@ -214,7 +214,10 @@ namespace Discord
/// <summary> /// <summary>
/// Allows for launching activities (applications with the EMBEDDED flag) in a voice channel. /// Allows for launching activities (applications with the EMBEDDED flag) in a voice channel.
/// </summary> /// </summary>
StartEmbeddedActivities = 0x80_00_00_00_00

StartEmbeddedActivities = 0x80_00_00_00_00,
/// <summary>
/// Allows for timing out users.
/// </summary>
ModerateMembers = 0x01_00_00_00_00_00
} }
} }

+ 12
- 6
src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs View File

@@ -102,7 +102,8 @@ namespace Discord
public bool SendMessagesInThreads => Permissions.GetValue(RawValue, GuildPermission.SendMessagesInThreads); public bool SendMessagesInThreads => Permissions.GetValue(RawValue, GuildPermission.SendMessagesInThreads);
/// <summary> If <c>true</c>, a user launch application activities in voice channels in this guild. </summary> /// <summary> If <c>true</c>, a user launch application activities in voice channels in this guild. </summary>
public bool StartEmbeddedActivities => Permissions.GetValue(RawValue, GuildPermission.StartEmbeddedActivities); public bool StartEmbeddedActivities => Permissions.GetValue(RawValue, GuildPermission.StartEmbeddedActivities);

/// <summary> If <c>true</c>, a user can timeout other users in this guild.</summary>
public bool ModerateMembers => Permissions.GetValue(RawValue, GuildPermission.ModerateMembers);
/// <summary> Creates a new <see cref="GuildPermissions"/> with the provided packed value. </summary> /// <summary> Creates a new <see cref="GuildPermissions"/> with the provided packed value. </summary>
public GuildPermissions(ulong rawValue) { RawValue = rawValue; } public GuildPermissions(ulong rawValue) { RawValue = rawValue; }


@@ -149,7 +150,8 @@ namespace Discord
bool? createPrivateThreads = null, bool? createPrivateThreads = null,
bool? useExternalStickers = null, bool? useExternalStickers = null,
bool? sendMessagesInThreads = null, bool? sendMessagesInThreads = null,
bool? startEmbeddedActivities = null)
bool? startEmbeddedActivities = null,
bool? moderateMembers = null)
{ {
ulong value = initialValue; ulong value = initialValue;


@@ -193,6 +195,7 @@ namespace Discord
Permissions.SetValue(ref value, useExternalStickers, GuildPermission.UseExternalStickers); Permissions.SetValue(ref value, useExternalStickers, GuildPermission.UseExternalStickers);
Permissions.SetValue(ref value, sendMessagesInThreads, GuildPermission.SendMessagesInThreads); Permissions.SetValue(ref value, sendMessagesInThreads, GuildPermission.SendMessagesInThreads);
Permissions.SetValue(ref value, startEmbeddedActivities, GuildPermission.StartEmbeddedActivities); Permissions.SetValue(ref value, startEmbeddedActivities, GuildPermission.StartEmbeddedActivities);
Permissions.SetValue(ref value, moderateMembers, GuildPermission.ModerateMembers);


RawValue = value; RawValue = value;
} }
@@ -238,7 +241,8 @@ namespace Discord
bool createPrivateThreads = false, bool createPrivateThreads = false,
bool useExternalStickers = false, bool useExternalStickers = false,
bool sendMessagesInThreads = false, bool sendMessagesInThreads = false,
bool startEmbeddedActivities = false)
bool startEmbeddedActivities = false,
bool moderateMembers = false)
: this(0, : this(0,
createInstantInvite: createInstantInvite, createInstantInvite: createInstantInvite,
manageRoles: manageRoles, manageRoles: manageRoles,
@@ -279,7 +283,8 @@ namespace Discord
createPrivateThreads: createPrivateThreads, createPrivateThreads: createPrivateThreads,
useExternalStickers: useExternalStickers, useExternalStickers: useExternalStickers,
sendMessagesInThreads: sendMessagesInThreads, sendMessagesInThreads: sendMessagesInThreads,
startEmbeddedActivities: startEmbeddedActivities)
startEmbeddedActivities: startEmbeddedActivities,
moderateMembers: moderateMembers)
{ } { }


/// <summary> Creates a new <see cref="GuildPermissions"/> from this one, changing the provided non-null permissions. </summary> /// <summary> Creates a new <see cref="GuildPermissions"/> from this one, changing the provided non-null permissions. </summary>
@@ -323,13 +328,14 @@ namespace Discord
bool? createPrivateThreads = null, bool? createPrivateThreads = null,
bool? useExternalStickers = null, bool? useExternalStickers = null,
bool? sendMessagesInThreads = null, bool? sendMessagesInThreads = null,
bool? startEmbeddedActivities = null)
bool? startEmbeddedActivities = null,
bool? moderateMembers = null)
=> new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions, => new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions,
viewAuditLog, viewGuildInsights, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, viewAuditLog, viewGuildInsights, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles,
readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers,
useVoiceActivation, prioritySpeaker, stream, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojisAndStickers, useVoiceActivation, prioritySpeaker, stream, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojisAndStickers,
useApplicationCommands, requestToSpeak, manageEvents, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads, useApplicationCommands, requestToSpeak, manageEvents, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads,
startEmbeddedActivities);
startEmbeddedActivities, moderateMembers);


/// <summary> /// <summary>
/// Returns a value that indicates if a specific <see cref="GuildPermission"/> is enabled /// Returns a value that indicates if a specific <see cref="GuildPermission"/> is enabled


+ 10
- 1
src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;


namespace Discord namespace Discord
@@ -72,6 +73,14 @@ namespace Discord
/// <remarks> /// <remarks>
/// This user MUST already be in a <see cref="IVoiceChannel"/> for this to work. /// This user MUST already be in a <see cref="IVoiceChannel"/> for this to work.
/// </remarks> /// </remarks>
public Optional<ulong> ChannelId { get; set; } // TODO: v3 breaking change, change ChannelId to ulong? to allow for kicking users from voice
public Optional<ulong?> ChannelId { get; set; }

/// <summary>
/// Sets a timestamp how long a user should be timed out for.
/// </summary>
/// <remarks>
/// <see cref="null"/> or a time in the past to clear a currently existing timeout.
/// </remarks>
public Optional<DateTimeOffset?> TimedOutUntil { get; set; }
} }
} }

+ 28
- 0
src/Discord.Net.Core/Entities/Users/IGuildUser.cs View File

@@ -85,6 +85,17 @@ namespace Discord
/// </summary> /// </summary>
int Hierarchy { get; } int Hierarchy { get; }


/// <summary>
/// Gets the date and time that indicates if and for how long a user has been timed out.
/// </summary>
/// <remarks>
/// <see cref="null"/> or a timestamp in the past if the user is not timed out.
/// </remarks>
/// <returns>
/// A <see cref="DateTimeOffset"/> indicating how long the user will be timed out for.
/// </returns>
DateTimeOffset? TimedOutUntil { get; }

/// <summary> /// <summary>
/// Gets the level permissions granted to this user to a given channel. /// Gets the level permissions granted to this user to a given channel.
/// </summary> /// </summary>
@@ -211,5 +222,22 @@ namespace Discord
/// A task that represents the asynchronous role removal operation. /// A task that represents the asynchronous role removal operation.
/// </returns> /// </returns>
Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null); Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null);
/// <summary>
/// Sets a timeout based on provided <see cref="TimeSpan"/> to this user in the guild.
/// </summary>
/// <param name="span">The <see cref="TimeSpan"/> indicating how long a user should be timed out for.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous timeout creation operation.
/// </returns>
Task SetTimeOutAsync(TimeSpan span, RequestOptions options = null);
/// <summary>
/// Removes the current timeout from the user in this guild if one exists.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous timeout removal operation.
/// </returns>
Task RemoveTimeOutAsync(RequestOptions options = null);
} }
} }

+ 2
- 0
src/Discord.Net.Rest/API/Common/GuildMember.cs View File

@@ -23,5 +23,7 @@ namespace Discord.API
public Optional<bool> Pending { get; set; } public Optional<bool> Pending { get; set; }
[JsonProperty("premium_since")] [JsonProperty("premium_since")]
public Optional<DateTimeOffset?> PremiumSince { get; set; } public Optional<DateTimeOffset?> PremiumSince { get; set; }
[JsonProperty("communication_disabled_until")]
public Optional<DateTimeOffset?> TimedOutUntil { get; set; }
} }
} }

+ 3
- 0
src/Discord.Net.Rest/API/Rest/ModifyGuildMemberParams.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System;


namespace Discord.API.Rest namespace Discord.API.Rest
{ {
@@ -15,5 +16,7 @@ namespace Discord.API.Rest
public Optional<ulong[]> RoleIds { get; set; } public Optional<ulong[]> RoleIds { get; set; }
[JsonProperty("channel_id")] [JsonProperty("channel_id")]
public Optional<ulong?> ChannelId { get; set; } public Optional<ulong?> ChannelId { get; set; }
[JsonProperty("communication_disabled_until")]
public Optional<DateTimeOffset?> TimedOutUntil { get; set; }
} }
} }

+ 21
- 0
src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs View File

@@ -16,6 +16,7 @@ namespace Discord.Rest
{ {
#region RestGuildUser #region RestGuildUser
private long? _premiumSinceTicks; private long? _premiumSinceTicks;
private long? _timedOutTicks;
private long? _joinedAtTicks; private long? _joinedAtTicks;
private ImmutableArray<ulong> _roleIds; private ImmutableArray<ulong> _roleIds;


@@ -47,6 +48,18 @@ namespace Discord.Rest
} }
} }


/// <inheritdoc />
public DateTimeOffset? TimedOutUntil
{
get
{
if (!_timedOutTicks.HasValue || _timedOutTicks.Value < 0)
return null;
else
return DateTimeUtils.FromTicks(_timedOutTicks);
}
}

/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="InvalidOperationException" accessor="get">Resolving permissions requires the parent guild to be downloaded.</exception> /// <exception cref="InvalidOperationException" accessor="get">Resolving permissions requires the parent guild to be downloaded.</exception>
public GuildPermissions GuildPermissions public GuildPermissions GuildPermissions
@@ -92,6 +105,8 @@ namespace Discord.Rest
UpdateRoles(model.Roles.Value); UpdateRoles(model.Roles.Value);
if (model.PremiumSince.IsSpecified) if (model.PremiumSince.IsSpecified)
_premiumSinceTicks = model.PremiumSince.Value?.UtcTicks; _premiumSinceTicks = model.PremiumSince.Value?.UtcTicks;
if (model.TimedOutUntil.IsSpecified)
_timedOutTicks = model.TimedOutUntil.Value?.UtcTicks;
if (model.Pending.IsSpecified) if (model.Pending.IsSpecified)
IsPending = model.Pending.Value; IsPending = model.Pending.Value;
} }
@@ -152,6 +167,12 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null) public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null)
=> RemoveRolesAsync(roles.Select(x => x.Id)); => RemoveRolesAsync(roles.Select(x => x.Id));
/// <inheritdoc />
public Task SetTimeOutAsync(TimeSpan span, RequestOptions options = null)
=> UserHelper.SetTimeoutAsync(this, Discord, span, options);
/// <inheritdoc />
public Task RemoveTimeOutAsync(RequestOptions options = null)
=> UserHelper.RemoveTimeOutAsync(this, Discord, options);


/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="InvalidOperationException">Resolving permissions requires the parent guild to be downloaded.</exception> /// <exception cref="InvalidOperationException">Resolving permissions requires the parent guild to be downloaded.</exception>


+ 8
- 0
src/Discord.Net.Rest/Entities/Users/RestWebhookUser.cs View File

@@ -62,6 +62,8 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
int IGuildUser.Hierarchy => 0; int IGuildUser.Hierarchy => 0;
/// <inheritdoc /> /// <inheritdoc />
DateTimeOffset? IGuildUser.TimedOutUntil => null;
/// <inheritdoc />
GuildPermissions IGuildUser.GuildPermissions => GuildPermissions.Webhook; GuildPermissions IGuildUser.GuildPermissions => GuildPermissions.Webhook;


/// <inheritdoc /> /// <inheritdoc />
@@ -97,6 +99,12 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
Task IGuildUser.RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options) => Task IGuildUser.RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options) =>
throw new NotSupportedException("Roles are not supported on webhook users."); throw new NotSupportedException("Roles are not supported on webhook users.");
/// <inheritdoc />
Task IGuildUser.SetTimeOutAsync(TimeSpan span, RequestOptions options) =>
throw new NotSupportedException("Timeouts are not supported on webhook users.");
/// <inheritdoc />
Task IGuildUser.RemoveTimeOutAsync(RequestOptions options) =>
throw new NotSupportedException("Timeouts are not supported on webhook users.");
#endregion #endregion


#region IVoiceState #region IVoiceState


+ 28
- 1
src/Discord.Net.Rest/Entities/Users/UserHelper.cs View File

@@ -31,11 +31,16 @@ namespace Discord.Rest
{ {
var args = new GuildUserProperties(); var args = new GuildUserProperties();
func(args); func(args);

if (args.TimedOutUntil.IsSpecified && args.TimedOutUntil.Value.Value.Offset > (new TimeSpan(28, 0, 0, 0)))
throw new ArgumentOutOfRangeException(nameof(args.TimedOutUntil), "Offset cannot be more than 28 days from the current date.");

var apiArgs = new API.Rest.ModifyGuildMemberParams var apiArgs = new API.Rest.ModifyGuildMemberParams
{ {
Deaf = args.Deaf, Deaf = args.Deaf,
Mute = args.Mute, Mute = args.Mute,
Nickname = args.Nickname
Nickname = args.Nickname,
TimedOutUntil = args.TimedOutUntil
}; };


if (args.Channel.IsSpecified) if (args.Channel.IsSpecified)
@@ -84,5 +89,27 @@ namespace Discord.Rest
foreach (var roleId in roleIds) foreach (var roleId in roleIds)
await client.ApiClient.RemoveRoleAsync(user.Guild.Id, user.Id, roleId, options).ConfigureAwait(false); await client.ApiClient.RemoveRoleAsync(user.Guild.Id, user.Id, roleId, options).ConfigureAwait(false);
} }

public static async Task SetTimeoutAsync(IGuildUser user, BaseDiscordClient client, TimeSpan span, RequestOptions options)
{
if (span.TotalDays > 28) // As its double, an exact value of 28 can be accepted.
throw new ArgumentOutOfRangeException(nameof(span), "Offset cannot be more than 28 days from the current date.");
if (span.Ticks <= 0)
throw new ArgumentOutOfRangeException(nameof(span), "Offset cannot hold no value or have a negative value.");
var apiArgs = new API.Rest.ModifyGuildMemberParams()
{
TimedOutUntil = DateTimeOffset.UtcNow.Add(span)
};
await client.ApiClient.ModifyGuildMemberAsync(user.Guild.Id, user.Id, apiArgs, options).ConfigureAwait(false);
}

public static async Task RemoveTimeOutAsync(IGuildUser user, BaseDiscordClient client, RequestOptions options)
{
var apiArgs = new API.Rest.ModifyGuildMemberParams()
{
TimedOutUntil = null
};
await client.ApiClient.ModifyGuildMemberAsync(user.Guild.Id, user.Id, apiArgs, options).ConfigureAwait(false);
}
} }
} }

+ 20
- 1
src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs View File

@@ -20,6 +20,7 @@ namespace Discord.WebSocket
{ {
#region SocketGuildUser #region SocketGuildUser
private long? _premiumSinceTicks; private long? _premiumSinceTicks;
private long? _timedOutTicks;
private long? _joinedAtTicks; private long? _joinedAtTicks;
private ImmutableArray<ulong> _roleIds; private ImmutableArray<ulong> _roleIds;


@@ -89,6 +90,17 @@ namespace Discord.WebSocket
public AudioInStream AudioStream => Guild.GetAudioStream(Id); public AudioInStream AudioStream => Guild.GetAudioStream(Id);
/// <inheritdoc /> /// <inheritdoc />
public DateTimeOffset? PremiumSince => DateTimeUtils.FromTicks(_premiumSinceTicks); public DateTimeOffset? PremiumSince => DateTimeUtils.FromTicks(_premiumSinceTicks);
/// <inheritdoc />
public DateTimeOffset? TimedOutUntil
{
get
{
if (!_timedOutTicks.HasValue || _timedOutTicks.Value < 0)
return null;
else
return DateTimeUtils.FromTicks(_timedOutTicks);
}
}


/// <summary> /// <summary>
/// Returns the position of the user within the role hierarchy. /// Returns the position of the user within the role hierarchy.
@@ -157,6 +169,8 @@ namespace Discord.WebSocket
UpdateRoles(model.Roles.Value); UpdateRoles(model.Roles.Value);
if (model.PremiumSince.IsSpecified) if (model.PremiumSince.IsSpecified)
_premiumSinceTicks = model.PremiumSince.Value?.UtcTicks; _premiumSinceTicks = model.PremiumSince.Value?.UtcTicks;
if (model.TimedOutUntil.IsSpecified)
_timedOutTicks = model.TimedOutUntil.Value?.UtcTicks;
if (model.Pending.IsSpecified) if (model.Pending.IsSpecified)
IsPending = model.Pending.Value; IsPending = model.Pending.Value;
} }
@@ -221,7 +235,12 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null) public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null)
=> RemoveRolesAsync(roles.Select(x => x.Id)); => RemoveRolesAsync(roles.Select(x => x.Id));

/// <inheritdoc />
public Task SetTimeOutAsync(TimeSpan span, RequestOptions options = null)
=> UserHelper.SetTimeoutAsync(this, Discord, span, options);
/// <inheritdoc />
public Task RemoveTimeOutAsync(RequestOptions options = null)
=> UserHelper.RemoveTimeOutAsync(this, Discord, options);
/// <inheritdoc /> /// <inheritdoc />
public ChannelPermissions GetPermissions(IGuildChannel channel) public ChannelPermissions GetPermissions(IGuildChannel channel)
=> new ChannelPermissions(Permissions.ResolveChannel(Guild, this, channel, GuildPermissions.RawValue)); => new ChannelPermissions(Permissions.ResolveChannel(Guild, this, channel, GuildPermissions.RawValue));


+ 8
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs View File

@@ -39,6 +39,10 @@ namespace Discord.WebSocket
public DateTimeOffset? PremiumSince public DateTimeOffset? PremiumSince
=> GuildUser.PremiumSince; => GuildUser.PremiumSince;


/// <inheritdoc/>
public DateTimeOffset? TimedOutUntil
=> GuildUser.TimedOutUntil;

/// <inheritdoc/> /// <inheritdoc/>
public bool? IsPending public bool? IsPending
=> GuildUser.IsPending; => GuildUser.IsPending;
@@ -171,7 +175,11 @@ namespace Discord.WebSocket


/// <inheritdoc/> /// <inheritdoc/>
public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null) => GuildUser.RemoveRolesAsync(roles, options); public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null) => GuildUser.RemoveRolesAsync(roles, options);
/// <inheritdoc/>
public Task SetTimeOutAsync(TimeSpan span, RequestOptions options = null) => GuildUser.SetTimeOutAsync(span, options);


/// <inheritdoc/>
public Task RemoveTimeOutAsync(RequestOptions options = null) => GuildUser.RemoveTimeOutAsync(options);
/// <inheritdoc/> /// <inheritdoc/>
GuildPermissions IGuildUser.GuildPermissions => GuildUser.GuildPermissions; GuildPermissions IGuildUser.GuildPermissions => GuildUser.GuildPermissions;




+ 10
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs View File

@@ -72,6 +72,8 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
DateTimeOffset? IGuildUser.PremiumSince => null; DateTimeOffset? IGuildUser.PremiumSince => null;
/// <inheritdoc /> /// <inheritdoc />
DateTimeOffset? IGuildUser.TimedOutUntil => null;
/// <inheritdoc />
bool? IGuildUser.IsPending => null; bool? IGuildUser.IsPending => null;
/// <inheritdoc /> /// <inheritdoc />
int IGuildUser.Hierarchy => 0; int IGuildUser.Hierarchy => 0;
@@ -129,6 +131,14 @@ namespace Discord.WebSocket
/// <exception cref="NotSupportedException">Roles are not supported on webhook users.</exception> /// <exception cref="NotSupportedException">Roles are not supported on webhook users.</exception>
Task IGuildUser.RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options) => Task IGuildUser.RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options) =>
throw new NotSupportedException("Roles are not supported on webhook users."); throw new NotSupportedException("Roles are not supported on webhook users.");
/// <inheritdoc />
/// <exception cref="NotSupportedException">Timeouts are not supported on webhook users.</exception>
Task IGuildUser.SetTimeOutAsync(TimeSpan span, RequestOptions options) =>
throw new NotSupportedException("Timeouts are not supported on webhook users.");
/// <inheritdoc />
/// <exception cref="NotSupportedException">Timeouts are not supported on webhook users.</exception>
Task IGuildUser.RemoveTimeOutAsync(RequestOptions options) =>
throw new NotSupportedException("Timeouts are not supported on webhook users.");
#endregion #endregion


#region IVoiceState #region IVoiceState


+ 2
- 0
test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs View File

@@ -99,6 +99,7 @@ namespace Discord
AssertFlag(() => new GuildPermissions(createPublicThreads: true), GuildPermission.CreatePublicThreads); AssertFlag(() => new GuildPermissions(createPublicThreads: true), GuildPermission.CreatePublicThreads);
AssertFlag(() => new GuildPermissions(createPrivateThreads: true), GuildPermission.CreatePrivateThreads); AssertFlag(() => new GuildPermissions(createPrivateThreads: true), GuildPermission.CreatePrivateThreads);
AssertFlag(() => new GuildPermissions(useExternalStickers: true), GuildPermission.UseExternalStickers); AssertFlag(() => new GuildPermissions(useExternalStickers: true), GuildPermission.UseExternalStickers);
AssertFlag(() => new GuildPermissions(moderateMembers: true), GuildPermission.ModerateMembers);
} }


/// <summary> /// <summary>
@@ -176,6 +177,7 @@ namespace Discord
AssertUtil(GuildPermission.CreatePublicThreads, x => x.CreatePublicThreads, (p, enable) => p.Modify(createPublicThreads: enable)); AssertUtil(GuildPermission.CreatePublicThreads, x => x.CreatePublicThreads, (p, enable) => p.Modify(createPublicThreads: enable));
AssertUtil(GuildPermission.CreatePrivateThreads, x => x.CreatePrivateThreads, (p, enable) => p.Modify(createPrivateThreads: enable)); AssertUtil(GuildPermission.CreatePrivateThreads, x => x.CreatePrivateThreads, (p, enable) => p.Modify(createPrivateThreads: enable));
AssertUtil(GuildPermission.UseExternalStickers, x => x.UseExternalStickers, (p, enable) => p.Modify(useExternalStickers: enable)); AssertUtil(GuildPermission.UseExternalStickers, x => x.UseExternalStickers, (p, enable) => p.Modify(useExternalStickers: enable));
AssertUtil(GuildPermission.ModerateMembers, x => x.ModerateMembers, (p, enable) => p.Modify(moderateMembers: enable));
} }
} }
} }

Loading…
Cancel
Save