Format the project with 'dotnet format' (#2551)
* Sync and Re-Format * Fix Title string. * Fix indentation.
This commit is contained in:
@@ -4,7 +4,7 @@ namespace Discord.API.Gateway
|
||||
{
|
||||
internal class GuildRoleUpdateEvent
|
||||
{
|
||||
[JsonProperty("guild_id")]
|
||||
[JsonProperty("guild_id")]
|
||||
public ulong GuildId { get; set; }
|
||||
[JsonProperty("role")]
|
||||
public Role Role { get; set; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Gateway
|
||||
{
|
||||
|
||||
@@ -2,8 +2,8 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Gateway
|
||||
{
|
||||
internal class ResumedEvent
|
||||
{
|
||||
internal class ResumedEvent
|
||||
{
|
||||
[JsonProperty("heartbeat_interval")]
|
||||
public int HeartbeatInterval { get; set; }
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ using Newtonsoft.Json;
|
||||
namespace Discord.API.Gateway
|
||||
{
|
||||
internal class VoiceServerUpdateEvent
|
||||
{
|
||||
[JsonProperty("guild_id")]
|
||||
public ulong GuildId { get; set; }
|
||||
{
|
||||
[JsonProperty("guild_id")]
|
||||
public ulong GuildId { get; set; }
|
||||
[JsonProperty("endpoint")]
|
||||
public string Endpoint { get; set; }
|
||||
public string Endpoint { get; set; }
|
||||
[JsonProperty("token")]
|
||||
public string Token { get; set; }
|
||||
public string Token { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord.Audio
|
||||
{
|
||||
@@ -137,7 +137,8 @@ namespace Discord.Audio
|
||||
await keepaliveTask.ConfigureAwait(false);
|
||||
_keepaliveTask = null;
|
||||
|
||||
while (_heartbeatTimes.TryDequeue(out _)) { }
|
||||
while (_heartbeatTimes.TryDequeue(out _))
|
||||
{ }
|
||||
_lastMessageTime = 0;
|
||||
|
||||
await ClearInputStreamsAsync().ConfigureAwait(false);
|
||||
@@ -149,7 +150,7 @@ namespace Discord.Audio
|
||||
public AudioOutStream CreateOpusStream(int bufferMillis)
|
||||
{
|
||||
var outputStream = new OutputStream(ApiClient); //Ignores header
|
||||
var sodiumEncrypter = new SodiumEncryptStream( outputStream, this); //Passes header
|
||||
var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header
|
||||
var rtpWriter = new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header, passes
|
||||
return new BufferedWriteStream(rtpWriter, this, bufferMillis, _connection.CancelToken, _audioLogger); //Generates header
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Discord.Audio
|
||||
namespace Discord.Audio
|
||||
{
|
||||
internal enum OpusApplication : int
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace Discord.Audio
|
||||
{
|
||||
@@ -15,7 +15,7 @@ namespace Discord.Audio
|
||||
public const int FrameSamplesPerChannel = SamplingRate / 1000 * FrameMillis;
|
||||
public const int FrameSamples = FrameSamplesPerChannel * Channels;
|
||||
public const int FrameBytes = FrameSamplesPerChannel * SampleBytes;
|
||||
|
||||
|
||||
protected bool _isDisposed = false;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
@@ -32,7 +32,7 @@ namespace Discord.Audio
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
protected static void CheckError(int result)
|
||||
{
|
||||
if (result < 0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Discord.Audio
|
||||
namespace Discord.Audio
|
||||
{
|
||||
//https://github.com/gcp/opus/blob/master/include/opus_defines.h
|
||||
internal enum OpusCtl : int
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Discord.Audio
|
||||
@@ -19,7 +19,7 @@ namespace Discord.Audio
|
||||
_ptr = CreateDecoder(SamplingRate, Channels, out var error);
|
||||
CheckError(error);
|
||||
}
|
||||
|
||||
|
||||
public unsafe int DecodeFrame(byte[] input, int inputOffset, int inputCount, byte[] output, int outputOffset, bool decodeFEC)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Discord.Audio
|
||||
@@ -13,9 +13,9 @@ namespace Discord.Audio
|
||||
private static extern int Encode(IntPtr st, byte* pcm, int frame_size, byte* data, int max_data_bytes);
|
||||
[DllImport("opus", EntryPoint = "opus_encoder_ctl", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern OpusError EncoderCtl(IntPtr st, OpusCtl request, int value);
|
||||
|
||||
|
||||
public AudioApplication Application { get; }
|
||||
public int BitRate { get;}
|
||||
public int BitRate { get; }
|
||||
|
||||
public OpusEncoder(int bitrate, AudioApplication application, int packetLoss)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Discord.Audio
|
||||
namespace Discord.Audio
|
||||
{
|
||||
internal enum OpusError : int
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Discord.Audio
|
||||
|
||||
@@ -243,4 +243,4 @@ namespace Discord.Audio.Streams
|
||||
return Task.Delay(0);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}*/
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Discord.Audio.Streams
|
||||
public override void WriteHeader(ushort seq, uint timestamp, bool missed)
|
||||
{
|
||||
if (_hasHeader)
|
||||
throw new InvalidOperationException("Header received with no payload.");
|
||||
throw new InvalidOperationException("Header received with no payload.");
|
||||
_hasHeader = true;
|
||||
|
||||
_nextMissed = missed;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Discord.Audio.Streams
|
||||
private int _partialFramePos;
|
||||
private ushort _seq;
|
||||
private uint _timestamp;
|
||||
|
||||
|
||||
public OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application, int packetLoss)
|
||||
{
|
||||
_next = next;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Discord.Audio.Streams
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
|
||||
|
||||
public override void WriteHeader(ushort seq, uint timestamp, bool missed) { } //Ignore
|
||||
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken)
|
||||
{
|
||||
@@ -21,4 +21,4 @@ namespace Discord.Audio.Streams
|
||||
await _client.SendAsync(buffer, offset, count).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Discord.Audio.Streams
|
||||
|
||||
int headerSize = GetHeaderSize(buffer, offset);
|
||||
|
||||
ushort seq = (ushort)((buffer[offset + 2] << 8) |
|
||||
ushort seq = (ushort)((buffer[offset + 2] << 8) |
|
||||
(buffer[offset + 3] << 0));
|
||||
|
||||
uint timestamp = (uint)((buffer[offset + 4] << 24) |
|
||||
@@ -46,7 +46,7 @@ namespace Discord.Audio.Streams
|
||||
ssrc = 0;
|
||||
if (buffer.Length - offset < 12)
|
||||
return false;
|
||||
|
||||
|
||||
int version = (buffer[offset + 0] & 0b1100_0000) >> 6;
|
||||
if (version != 2)
|
||||
return false;
|
||||
@@ -71,8 +71,8 @@ namespace Discord.Audio.Streams
|
||||
return 12 + csics * 4;
|
||||
|
||||
int extensionOffset = offset + 12 + (csics * 4);
|
||||
int extensionLength =
|
||||
(buffer[extensionOffset + 2] << 8) |
|
||||
int extensionLength =
|
||||
(buffer[extensionOffset + 2] << 8) |
|
||||
(buffer[extensionOffset + 3]);
|
||||
return extensionOffset + 4 + (extensionLength * 4);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Discord.Audio.Streams
|
||||
{
|
||||
if (_hasHeader)
|
||||
throw new InvalidOperationException("Header received with no payload");
|
||||
|
||||
|
||||
_hasHeader = true;
|
||||
_nextSeq = seq;
|
||||
_nextTimestamp = timestamp;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Discord.Audio.Streams
|
||||
|
||||
if (_client.SecretKey == null)
|
||||
return;
|
||||
|
||||
|
||||
Buffer.BlockCopy(buffer, offset, _nonce, 0, 12); //Copy nonce from RTP header
|
||||
count = SecretBox.Encrypt(buffer, offset + 12, count - 12, buffer, 12, _nonce, _client.SecretKey);
|
||||
_next.WriteHeader(_nextSeq, _nextTimestamp, false);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Discord.API;
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.API;
|
||||
using Discord.Rest;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
@@ -283,7 +283,7 @@ namespace Discord.WebSocket
|
||||
/// A <see cref="SocketSticker"/> if found, otherwise <see langword="null"/>.
|
||||
/// </returns>
|
||||
public abstract Task<SocketSticker> GetStickerAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region IDiscordClient
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Discord.Commands
|
||||
/// <summary> Gets the shard ID of the command context. </summary>
|
||||
private static int GetShardId(DiscordShardedClient client, IGuild guild)
|
||||
=> guild == null ? 0 : client.GetShardIdFor(guild);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region ICommandContext
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Discord.Commands
|
||||
User = msg.Author;
|
||||
Message = msg;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region ICommandContext
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Discord.Logging;
|
||||
using Discord.Net;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Net;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
@@ -164,7 +164,8 @@ namespace Discord
|
||||
}
|
||||
private async Task DisconnectAsync(Exception ex, bool isReconnecting)
|
||||
{
|
||||
if (State == ConnectionState.Disconnected) return;
|
||||
if (State == ConnectionState.Disconnected)
|
||||
return;
|
||||
State = ConnectionState.Disconnecting;
|
||||
await _logger.InfoAsync("Disconnecting").ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -7,28 +7,28 @@ namespace Discord.WebSocket
|
||||
{
|
||||
#region General
|
||||
/// <summary> Fired when a shard is connected to the Discord gateway. </summary>
|
||||
public event Func<DiscordSocketClient, Task> ShardConnected
|
||||
public event Func<DiscordSocketClient, Task> ShardConnected
|
||||
{
|
||||
add { _shardConnectedEvent.Add(value); }
|
||||
remove { _shardConnectedEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<DiscordSocketClient, Task>> _shardConnectedEvent = new AsyncEvent<Func<DiscordSocketClient, Task>>();
|
||||
/// <summary> Fired when a shard is disconnected from the Discord gateway. </summary>
|
||||
public event Func<Exception, DiscordSocketClient, Task> ShardDisconnected
|
||||
public event Func<Exception, DiscordSocketClient, Task> ShardDisconnected
|
||||
{
|
||||
add { _shardDisconnectedEvent.Add(value); }
|
||||
remove { _shardDisconnectedEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<Exception, DiscordSocketClient, Task>> _shardDisconnectedEvent = new AsyncEvent<Func<Exception, DiscordSocketClient, Task>>();
|
||||
/// <summary> Fired when a guild data for a shard has finished downloading. </summary>
|
||||
public event Func<DiscordSocketClient, Task> ShardReady
|
||||
public event Func<DiscordSocketClient, Task> ShardReady
|
||||
{
|
||||
add { _shardReadyEvent.Add(value); }
|
||||
remove { _shardReadyEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<DiscordSocketClient, Task>> _shardReadyEvent = new AsyncEvent<Func<DiscordSocketClient, Task>>();
|
||||
/// <summary> Fired when a shard receives a heartbeat from the Discord gateway. </summary>
|
||||
public event Func<int, int, DiscordSocketClient, Task> ShardLatencyUpdated
|
||||
public event Func<int, int, DiscordSocketClient, Task> ShardLatencyUpdated
|
||||
{
|
||||
add { _shardLatencyUpdatedEvent.Add(value); }
|
||||
remove { _shardLatencyUpdatedEvent.Remove(value); }
|
||||
|
||||
@@ -2,11 +2,11 @@ using Discord.API;
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
@@ -170,7 +170,7 @@ namespace Discord.WebSocket
|
||||
await _shards[i].LoginAsync(tokenType, token);
|
||||
}
|
||||
|
||||
if(_defaultStickers.Length == 0 && _baseConfig.AlwaysDownloadDefaultStickers)
|
||||
if (_defaultStickers.Length == 0 && _baseConfig.AlwaysDownloadDefaultStickers)
|
||||
await DownloadDefaultStickersAsync().ConfigureAwait(false);
|
||||
|
||||
}
|
||||
@@ -370,7 +370,8 @@ namespace Discord.WebSocket
|
||||
/// <exception cref="ArgumentNullException"><paramref name="guilds"/> is <see langword="null"/></exception>
|
||||
public override async Task DownloadUsersAsync(IEnumerable<IGuild> guilds)
|
||||
{
|
||||
if (guilds == null) throw new ArgumentNullException(nameof(guilds));
|
||||
if (guilds == null)
|
||||
throw new ArgumentNullException(nameof(guilds));
|
||||
for (int i = 0; i < _shards.Length; i++)
|
||||
{
|
||||
int id = _shardIds[i];
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Discord.API
|
||||
|
||||
public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent,
|
||||
string url = null, RetryMode defaultRetryMode = RetryMode.AlwaysRetry, JsonSerializer serializer = null,
|
||||
bool useSystemClock = true, Func<IRateLimitInfo, Task> defaultRatelimitCallback = null)
|
||||
bool useSystemClock = true, Func<IRateLimitInfo, Task> defaultRatelimitCallback = null)
|
||||
: base(restClientProvider, userAgent, defaultRetryMode, serializer, useSystemClock, defaultRatelimitCallback)
|
||||
{
|
||||
_gatewayUrl = url;
|
||||
@@ -275,10 +275,12 @@ namespace Discord.API
|
||||
if (WebSocketClient == null)
|
||||
throw new NotSupportedException("This client is not configured with WebSocket support.");
|
||||
|
||||
if (ConnectionState == ConnectionState.Disconnected) return;
|
||||
if (ConnectionState == ConnectionState.Disconnected)
|
||||
return;
|
||||
ConnectionState = ConnectionState.Disconnecting;
|
||||
|
||||
try { _connectCancelToken?.Cancel(false); }
|
||||
try
|
||||
{ _connectCancelToken?.Cancel(false); }
|
||||
catch { }
|
||||
|
||||
if (ex is GatewayReconnectException)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Discord.API;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.API;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
|
||||
@@ -333,7 +333,8 @@ namespace Discord.WebSocket
|
||||
await heartbeatTask.ConfigureAwait(false);
|
||||
_heartbeatTask = null;
|
||||
|
||||
while (_heartbeatTimes.TryDequeue(out _)) { }
|
||||
while (_heartbeatTimes.TryDequeue(out _))
|
||||
{ }
|
||||
_lastMessageTime = 0;
|
||||
|
||||
await _gatewayLogger.DebugAsync("Waiting for guild downloader").ConfigureAwait(false);
|
||||
@@ -344,7 +345,8 @@ namespace Discord.WebSocket
|
||||
|
||||
//Clear large guild queue
|
||||
await _gatewayLogger.DebugAsync("Clearing large guild queue").ConfigureAwait(false);
|
||||
while (_largeGuilds.TryDequeue(out _)) { }
|
||||
while (_largeGuilds.TryDequeue(out _))
|
||||
{ }
|
||||
|
||||
//Raise virtual GUILD_UNAVAILABLEs
|
||||
await _gatewayLogger.DebugAsync("Raising virtual GuildUnavailables").ConfigureAwait(false);
|
||||
@@ -461,7 +463,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
var commands = (await ApiClient.GetGlobalApplicationCommandsAsync(withLocalizations, locale, options)).Select(x => SocketApplicationCommand.Create(this, x));
|
||||
|
||||
foreach(var command in commands)
|
||||
foreach (var command in commands)
|
||||
{
|
||||
State.AddCommand(command);
|
||||
}
|
||||
@@ -490,7 +492,7 @@ namespace Discord.WebSocket
|
||||
//Purge our previous commands
|
||||
State.PurgeCommands(x => x.IsGlobalCommand);
|
||||
|
||||
foreach(var entity in entities)
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
State.AddCommand(entity);
|
||||
}
|
||||
@@ -531,7 +533,7 @@ namespace Discord.WebSocket
|
||||
if (sticker != null)
|
||||
return sticker;
|
||||
|
||||
foreach(var guild in Guilds)
|
||||
foreach (var guild in Guilds)
|
||||
{
|
||||
sticker = await guild.GetStickerAsync(id, CacheMode.CacheOnly).ConfigureAwait(false);
|
||||
|
||||
@@ -544,7 +546,7 @@ namespace Discord.WebSocket
|
||||
|
||||
var model = await ApiClient.GetStickerAsync(id, options).ConfigureAwait(false);
|
||||
|
||||
if(model == null)
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -750,7 +752,7 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.WarningAsync("You're using the GuildPresences intent without listening to the PresenceUpdate event, consider removing the intent from your config.").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if(!_gatewayIntents.HasFlag(GatewayIntents.GuildPresences) &&
|
||||
if (!_gatewayIntents.HasFlag(GatewayIntents.GuildPresences) &&
|
||||
((_shardedClient is null && _presenceUpdated.HasSubscribers) ||
|
||||
(_shardedClient is not null && _shardedClient._presenceUpdated.HasSubscribers)))
|
||||
{
|
||||
@@ -767,7 +769,7 @@ namespace Discord.WebSocket
|
||||
_guildScheduledEventUserAdd.HasSubscribers;
|
||||
|
||||
bool shardedClientHasGuildScheduledEventsSubscribers =
|
||||
_shardedClient is not null &&
|
||||
_shardedClient is not null &&
|
||||
(_shardedClient._guildScheduledEventCancelled.HasSubscribers ||
|
||||
_shardedClient._guildScheduledEventUserRemove.HasSubscribers ||
|
||||
_shardedClient._guildScheduledEventCompleted.HasSubscribers ||
|
||||
@@ -783,7 +785,7 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.WarningAsync("You're using the GuildScheduledEvents gateway intent without listening to any events related to that intent, consider removing the intent from your config.").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if(!_gatewayIntents.HasFlag(GatewayIntents.GuildScheduledEvents) &&
|
||||
if (!_gatewayIntents.HasFlag(GatewayIntents.GuildScheduledEvents) &&
|
||||
((_shardedClient is null && hasGuildScheduledEventsSubscribers) ||
|
||||
(_shardedClient is not null && shardedClientHasGuildScheduledEventsSubscribers)))
|
||||
{
|
||||
@@ -2238,12 +2240,12 @@ namespace Discord.WebSocket
|
||||
await TimedInvokeAsync(_requestToSpeak, nameof(RequestToSpeak), stage, guildUser);
|
||||
return;
|
||||
}
|
||||
if(before.IsSuppressed && !after.IsSuppressed)
|
||||
if (before.IsSuppressed && !after.IsSuppressed)
|
||||
{
|
||||
await TimedInvokeAsync(_speakerAdded, nameof(SpeakerAdded), stage, guildUser);
|
||||
return;
|
||||
}
|
||||
if(!before.IsSuppressed && after.IsSuppressed)
|
||||
if (!before.IsSuppressed && after.IsSuppressed)
|
||||
{
|
||||
await TimedInvokeAsync(_speakerRemoved, nameof(SpeakerRemoved), stage, guildUser);
|
||||
}
|
||||
@@ -2349,7 +2351,7 @@ namespace Discord.WebSocket
|
||||
case "INTERACTION_CREATE":
|
||||
{
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (INTERACTION_CREATE)").ConfigureAwait(false);
|
||||
|
||||
|
||||
var data = (payload as JToken).ToObject<API.Interaction>(_serializer);
|
||||
|
||||
var guild = data.GuildId.IsSpecified ? GetGuild(data.GuildId.Value) : null;
|
||||
@@ -2366,7 +2368,7 @@ namespace Discord.WebSocket
|
||||
: State.GetOrAddUser(data.Member.Value.User.Id, (_) => SocketGlobalUser.Create(this, State, data.Member.Value.User));
|
||||
|
||||
SocketChannel channel = null;
|
||||
if(data.ChannelId.IsSpecified)
|
||||
if (data.ChannelId.IsSpecified)
|
||||
{
|
||||
channel = State.GetChannel(data.ChannelId.Value);
|
||||
|
||||
@@ -2507,7 +2509,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
threadChannel.Update(State, data);
|
||||
|
||||
if(data.ThreadMember.IsSpecified)
|
||||
if (data.ThreadMember.IsSpecified)
|
||||
threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser);
|
||||
}
|
||||
else
|
||||
@@ -2570,7 +2572,7 @@ namespace Discord.WebSocket
|
||||
|
||||
var guild = State.GetGuild(data.GuildId.Value);
|
||||
|
||||
if(guild == null)
|
||||
if (guild == null)
|
||||
{
|
||||
await UnknownGuildAsync(type, data.GuildId.Value).ConfigureAwait(false);
|
||||
return;
|
||||
@@ -2591,17 +2593,17 @@ namespace Discord.WebSocket
|
||||
|
||||
var guild = State.GetGuild(data.GuildId);
|
||||
|
||||
if(guild == null)
|
||||
if (guild == null)
|
||||
{
|
||||
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(var thread in data.Threads)
|
||||
foreach (var thread in data.Threads)
|
||||
{
|
||||
var entity = guild.ThreadChannels.FirstOrDefault(x => x.Id == thread.Id);
|
||||
|
||||
if(entity == null)
|
||||
if (entity == null)
|
||||
{
|
||||
entity = (SocketThreadChannel)guild.AddChannel(State, thread);
|
||||
}
|
||||
@@ -2610,7 +2612,7 @@ namespace Discord.WebSocket
|
||||
entity.Update(State, thread);
|
||||
}
|
||||
|
||||
foreach(var member in data.Members.Where(x => x.Id.Value == entity.Id))
|
||||
foreach (var member in data.Members.Where(x => x.Id.Value == entity.Id))
|
||||
{
|
||||
var guildMember = guild.GetUser(member.Id.Value);
|
||||
|
||||
@@ -2653,7 +2655,7 @@ namespace Discord.WebSocket
|
||||
|
||||
var thread = (SocketThreadChannel)guild.GetChannel(data.Id);
|
||||
|
||||
if(thread == null)
|
||||
if (thread == null)
|
||||
{
|
||||
await UnknownChannelAsync(type, data.Id);
|
||||
return;
|
||||
@@ -2671,13 +2673,13 @@ namespace Discord.WebSocket
|
||||
if (data.AddedMembers.IsSpecified)
|
||||
{
|
||||
List<SocketThreadUser> newThreadMembers = new List<SocketThreadUser>();
|
||||
foreach(var threadMember in data.AddedMembers.Value)
|
||||
foreach (var threadMember in data.AddedMembers.Value)
|
||||
{
|
||||
SocketGuildUser guildMember;
|
||||
|
||||
guildMember = guild.GetUser(threadMember.UserId.Value);
|
||||
|
||||
if(guildMember == null)
|
||||
if (guildMember == null)
|
||||
{
|
||||
await UnknownGuildUserAsync("THREAD_MEMBERS_UPDATE", threadMember.UserId.Value, guild.Id);
|
||||
}
|
||||
@@ -2691,15 +2693,15 @@ namespace Discord.WebSocket
|
||||
|
||||
if (leftUsers != null)
|
||||
{
|
||||
foreach(var threadUser in leftUsers)
|
||||
foreach (var threadUser in leftUsers)
|
||||
{
|
||||
await TimedInvokeAsync(_threadMemberLeft, nameof(ThreadMemberLeft), threadUser).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
if(joinUsers != null)
|
||||
if (joinUsers != null)
|
||||
{
|
||||
foreach(var threadUser in joinUsers)
|
||||
foreach (var threadUser in joinUsers)
|
||||
{
|
||||
await TimedInvokeAsync(_threadMemberJoined, nameof(ThreadMemberJoined), threadUser).ConfigureAwait(false);
|
||||
}
|
||||
@@ -2718,7 +2720,7 @@ namespace Discord.WebSocket
|
||||
|
||||
var guild = State.GetGuild(data.GuildId);
|
||||
|
||||
if(guild == null)
|
||||
if (guild == null)
|
||||
{
|
||||
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false);
|
||||
return;
|
||||
@@ -2726,7 +2728,7 @@ namespace Discord.WebSocket
|
||||
|
||||
var stageChannel = guild.GetStageChannel(data.ChannelId);
|
||||
|
||||
if(stageChannel == null)
|
||||
if (stageChannel == null)
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
return;
|
||||
@@ -2792,15 +2794,16 @@ namespace Discord.WebSocket
|
||||
|
||||
var after = guild.AddOrUpdateEvent(data);
|
||||
|
||||
if((before != null ? before.Status != GuildScheduledEventStatus.Completed : true) && data.Status == GuildScheduledEventStatus.Completed)
|
||||
if ((before != null ? before.Status != GuildScheduledEventStatus.Completed : true) && data.Status == GuildScheduledEventStatus.Completed)
|
||||
{
|
||||
await TimedInvokeAsync(_guildScheduledEventCompleted, nameof(GuildScheduledEventCompleted), after).ConfigureAwait(false);
|
||||
}
|
||||
else if((before != null ? before.Status != GuildScheduledEventStatus.Active : false) && data.Status == GuildScheduledEventStatus.Active)
|
||||
else if ((before != null ? before.Status != GuildScheduledEventStatus.Active : false) && data.Status == GuildScheduledEventStatus.Active)
|
||||
{
|
||||
await TimedInvokeAsync(_guildScheduledEventStarted, nameof(GuildScheduledEventStarted), after).ConfigureAwait(false);
|
||||
}
|
||||
else await TimedInvokeAsync(_guildScheduledEventUpdated, nameof(GuildScheduledEventUpdated), beforeCacheable, after).ConfigureAwait(false);
|
||||
else
|
||||
await TimedInvokeAsync(_guildScheduledEventUpdated, nameof(GuildScheduledEventUpdated), beforeCacheable, after).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case "GUILD_SCHEDULED_EVENT_DELETE":
|
||||
@@ -2830,7 +2833,7 @@ namespace Discord.WebSocket
|
||||
|
||||
var guild = State.GetGuild(data.GuildId);
|
||||
|
||||
if(guild == null)
|
||||
if (guild == null)
|
||||
{
|
||||
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false);
|
||||
return;
|
||||
@@ -2902,7 +2905,8 @@ namespace Discord.WebSocket
|
||||
|
||||
#region Others
|
||||
default:
|
||||
if(!SuppressUnknownDispatchWarnings) await _gatewayLogger.WarningAsync($"Unknown Dispatch ({type})").ConfigureAwait(false);
|
||||
if (!SuppressUnknownDispatchWarnings)
|
||||
await _gatewayLogger.WarningAsync($"Unknown Dispatch ({type})").ConfigureAwait(false);
|
||||
break;
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Rest;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
|
||||
@@ -19,20 +19,20 @@ namespace Discord.WebSocket
|
||||
IReadOnlyCollection<SocketMessage> CachedMessages { get; }
|
||||
|
||||
/// <inheritdoc cref="IMessageChannel.SendMessageAsync(string, bool, Embed, RequestOptions, AllowedMentions, MessageReference, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
|
||||
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
|
||||
RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null,
|
||||
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
|
||||
/// <inheritdoc cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
|
||||
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null,
|
||||
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
|
||||
/// <inheritdoc cref="IMessageChannel.SendFileAsync(Stream, string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
|
||||
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false,
|
||||
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <inheritdoc cref="IMessageChannel.SendFileAsync(FileAttachment, string, bool, Embed, RequestOptions, AllowedMentions, MessageReference, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Rest;
|
||||
using Model = Discord.API.Channel;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
|
||||
@@ -68,11 +68,20 @@ namespace Discord.WebSocket
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case SocketDMChannel dmChannel: dmChannel.AddMessage(msg); break;
|
||||
case SocketGroupChannel groupChannel: groupChannel.AddMessage(msg); break;
|
||||
case SocketThreadChannel threadChannel: threadChannel.AddMessage(msg); break;
|
||||
case SocketTextChannel textChannel: textChannel.AddMessage(msg); break;
|
||||
default: throw new NotSupportedException($"Unexpected {nameof(ISocketMessageChannel)} type.");
|
||||
case SocketDMChannel dmChannel:
|
||||
dmChannel.AddMessage(msg);
|
||||
break;
|
||||
case SocketGroupChannel groupChannel:
|
||||
groupChannel.AddMessage(msg);
|
||||
break;
|
||||
case SocketThreadChannel threadChannel:
|
||||
threadChannel.AddMessage(msg);
|
||||
break;
|
||||
case SocketTextChannel textChannel:
|
||||
textChannel.AddMessage(msg);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException($"Unexpected {nameof(ISocketMessageChannel)} type.");
|
||||
}
|
||||
}
|
||||
/// <exception cref="NotSupportedException">Unexpected <see cref="ISocketMessageChannel"/> type.</exception>
|
||||
|
||||
@@ -140,16 +140,16 @@ namespace Discord.WebSocket
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
|
||||
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
|
||||
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
|
||||
RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null,
|
||||
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
|
||||
RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null,
|
||||
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference,
|
||||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference,
|
||||
components, stickers, options, embeds, flags);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
|
||||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
|
||||
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
|
||||
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference,
|
||||
@@ -158,28 +158,28 @@ namespace Discord.WebSocket
|
||||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
|
||||
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
|
||||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
|
||||
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions,
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions,
|
||||
messageReference, components, stickers, options, isSpoiler, embeds, flags);
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
|
||||
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
|
||||
public Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
|
||||
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
public Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
|
||||
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions,
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions,
|
||||
messageReference, components, stickers, options, embeds, flags);
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
|
||||
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
|
||||
public Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false,
|
||||
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
public Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false,
|
||||
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
|
||||
Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
=> ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions,
|
||||
=> ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions,
|
||||
messageReference, components, stickers, options, embeds, flags);
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
throw new NotSupportedException("Voice is not yet supported for group channels.");
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Messages
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace Discord.WebSocket
|
||||
public override string ToString() => Name;
|
||||
private string DebuggerDisplay => $"{Name} ({Id}, Guild)";
|
||||
internal new SocketGuildChannel Clone() => MemberwiseClone() as SocketGuildChannel;
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region SocketChannel
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Discord.WebSocket
|
||||
public class SocketNewsChannel : SocketTextChannel, INewsChannel
|
||||
{
|
||||
internal SocketNewsChannel(DiscordSocketClient discord, ulong id, SocketGuild guild)
|
||||
:base(discord, id, guild)
|
||||
: base(discord, id, guild)
|
||||
{
|
||||
}
|
||||
internal new static SocketNewsChannel Create(SocketGuild guild, ClientState state, Model model)
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace Discord.WebSocket
|
||||
|
||||
var thread = (SocketThreadChannel)Guild.AddOrUpdateChannel(Discord.State, model);
|
||||
|
||||
if(Discord.AlwaysDownloadUsers && Discord.HasGatewayIntent(GatewayIntents.GuildMembers))
|
||||
if (Discord.AlwaysDownloadUsers && Discord.HasGatewayIntent(GatewayIntents.GuildMembers))
|
||||
await thread.DownloadUsersAsync();
|
||||
|
||||
return thread;
|
||||
@@ -461,7 +461,7 @@ namespace Discord.WebSocket
|
||||
AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components,
|
||||
ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region INestedChannel
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
@@ -8,7 +9,6 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Channel;
|
||||
using ThreadMember = Discord.API.ThreadMember;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
if (!IsTextInVoice)
|
||||
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
|
||||
return base.DeleteMessageAsync(messageId, options);
|
||||
return base.DeleteMessageAsync(messageId, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
|
||||
@@ -136,7 +136,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
if (!IsTextInVoice)
|
||||
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
|
||||
return base.DeleteMessagesAsync(messages, options);
|
||||
return base.DeleteMessagesAsync(messages, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
|
||||
@@ -144,7 +144,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
if (!IsTextInVoice)
|
||||
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
|
||||
return base.DeleteMessagesAsync(messageIds, options);
|
||||
return base.DeleteMessagesAsync(messageIds, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
|
||||
@@ -160,7 +160,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
if (!IsTextInVoice)
|
||||
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
|
||||
return base.GetCachedMessage(id);
|
||||
return base.GetCachedMessage(id);
|
||||
}
|
||||
|
||||
/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
|
||||
@@ -192,7 +192,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
if (!IsTextInVoice)
|
||||
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
|
||||
return base.GetMessagesAsync(fromMessage, dir, limit, options);
|
||||
return base.GetMessagesAsync(fromMessage, dir, limit, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
|
||||
@@ -232,7 +232,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
if (!IsTextInVoice)
|
||||
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
|
||||
return base.GetWebhooksAsync(options);
|
||||
return base.GetWebhooksAsync(options);
|
||||
}
|
||||
|
||||
/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
|
||||
@@ -256,7 +256,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
if (!IsTextInVoice)
|
||||
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
|
||||
return base.SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
|
||||
return base.SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
|
||||
}
|
||||
|
||||
/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
|
||||
|
||||
@@ -7,22 +7,22 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ChannelModel = Discord.API.Channel;
|
||||
using EmojiUpdateModel = Discord.API.Gateway.GuildEmojiUpdateEvent;
|
||||
using EventModel = Discord.API.GuildScheduledEvent;
|
||||
using ExtendedModel = Discord.API.Gateway.ExtendedGuild;
|
||||
using GuildSyncModel = Discord.API.Gateway.GuildSyncEvent;
|
||||
using MemberModel = Discord.API.GuildMember;
|
||||
using Model = Discord.API.Guild;
|
||||
using PresenceModel = Discord.API.Presence;
|
||||
using RoleModel = Discord.API.Role;
|
||||
using StickerModel = Discord.API.Sticker;
|
||||
using UserModel = Discord.API.User;
|
||||
using VoiceStateModel = Discord.API.VoiceState;
|
||||
using StickerModel = Discord.API.Sticker;
|
||||
using EventModel = Discord.API.GuildScheduledEvent;
|
||||
using System.IO;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
@@ -403,7 +403,7 @@ namespace Discord.WebSocket
|
||||
IsAvailable = !(model.Unavailable ?? false);
|
||||
if (!IsAvailable)
|
||||
{
|
||||
if(_events == null)
|
||||
if (_events == null)
|
||||
_events = new ConcurrentDictionary<ulong, SocketGuildEvent>();
|
||||
if (_channels == null)
|
||||
_channels = new ConcurrentDictionary<ulong, SocketGuildChannel>();
|
||||
@@ -431,7 +431,7 @@ namespace Discord.WebSocket
|
||||
channels.TryAdd(channel.Id, channel);
|
||||
}
|
||||
|
||||
for(int i = 0; i < model.Threads.Length; i++)
|
||||
for (int i = 0; i < model.Threads.Length; i++)
|
||||
{
|
||||
var threadChannel = SocketThreadChannel.Create(this, state, model.Threads[i]);
|
||||
state.AddChannel(threadChannel);
|
||||
@@ -987,7 +987,7 @@ namespace Discord.WebSocket
|
||||
|
||||
Discord.State.PurgeCommands(x => !x.IsGlobalCommand && x.Guild.Id == Id);
|
||||
|
||||
foreach(var entity in entities)
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
Discord.State.AddCommand(entity);
|
||||
}
|
||||
@@ -1195,7 +1195,7 @@ namespace Discord.WebSocket
|
||||
var membersToKeep = Users.Where(x => !predicate.Invoke(x) || x?.Id == Discord.CurrentUser.Id);
|
||||
|
||||
foreach (var member in membersToPurge)
|
||||
if(_members.TryRemove(member.Id, out _))
|
||||
if (_members.TryRemove(member.Id, out _))
|
||||
member.GlobalUser.RemoveRef(Discord);
|
||||
|
||||
foreach (var member in membersToKeep)
|
||||
@@ -1347,7 +1347,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
case GuildScheduledEventType.Stage:
|
||||
CurrentUser.GuildPermissions.Ensure(GuildPermission.ManageEvents | GuildPermission.ManageChannels | GuildPermission.MuteMembers | GuildPermission.MoveMembers);
|
||||
break;
|
||||
break;
|
||||
case GuildScheduledEventType.Voice:
|
||||
CurrentUser.GuildPermissions.Ensure(GuildPermission.ManageEvents | GuildPermission.ViewChannel | GuildPermission.Connect);
|
||||
break;
|
||||
@@ -2008,7 +2008,7 @@ namespace Discord.WebSocket
|
||||
async Task<IReadOnlyCollection<IWebhook>> IGuild.GetWebhooksAsync(RequestOptions options)
|
||||
=> await GetWebhooksAsync(options).ConfigureAwait(false);
|
||||
/// <inheritdoc />
|
||||
async Task<IReadOnlyCollection<IApplicationCommand>> IGuild.GetApplicationCommandsAsync (bool withLocalizations, string locale, RequestOptions options)
|
||||
async Task<IReadOnlyCollection<IApplicationCommand>> IGuild.GetApplicationCommandsAsync(bool withLocalizations, string locale, RequestOptions options)
|
||||
=> await GetApplicationCommandsAsync(withLocalizations, locale, options).ConfigureAwait(false);
|
||||
/// <inheritdoc />
|
||||
async Task<ICustomSticker> IGuild.CreateStickerAsync(string name, string description, IEnumerable<string> tags, Image image, RequestOptions options)
|
||||
|
||||
@@ -86,9 +86,9 @@ namespace Discord.WebSocket
|
||||
{
|
||||
var guildUser = Guild.GetUser(model.CreatorId.Value);
|
||||
|
||||
if(guildUser != null)
|
||||
if (guildUser != null)
|
||||
{
|
||||
if(model.Creator.IsSpecified)
|
||||
if (model.Creator.IsSpecified)
|
||||
guildUser.Update(Discord.State, model.Creator.Value);
|
||||
|
||||
Creator = guildUser;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Discord.Net.Rest;
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Interaction;
|
||||
using DataModel = Discord.API.MessageComponentInteractionData;
|
||||
using Discord.Rest;
|
||||
using System.Collections.Generic;
|
||||
using Discord.Net.Rest;
|
||||
using System.IO;
|
||||
using Model = Discord.API.Interaction;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Discord.Rest;
|
||||
using Discord.Utils;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Model = Discord.API.MessageComponentInteractionData;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Discord.WebSocket
|
||||
var dataModel = model.Data.IsSpecified
|
||||
? (DataModel)model.Data.Value
|
||||
: null;
|
||||
|
||||
|
||||
Data = new SocketModalData(dataModel, client, client.State, client.State.GetGuild(model.GuildId.GetValueOrDefault()), model.User.GetValueOrDefault());
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ namespace Discord.WebSocket
|
||||
/// <inheritdoc/>
|
||||
public override Task RespondWithModalAsync(Modal modal, RequestOptions options = null)
|
||||
=> throw new NotSupportedException("You cannot respond to a modal with a modal!");
|
||||
|
||||
|
||||
IModalInteractionData IModalInteraction.Data => Data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using Model = Discord.API.ModalInteractionData;
|
||||
using InterationModel = Discord.API.Interaction;
|
||||
using DataModel = Discord.API.MessageComponentInteractionData;
|
||||
using InterationModel = Discord.API.Interaction;
|
||||
using Model = Discord.API.ModalInteractionData;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
|
||||
@@ -3,8 +3,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Interaction;
|
||||
using DataModel = Discord.API.AutocompleteInteractionData;
|
||||
using Model = Discord.API.Interaction;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace Discord.WebSocket
|
||||
|
||||
return await InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<RestFollowupMessage> FollowupWithFilesAsync(
|
||||
IEnumerable<FileAttachment> attachments,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Discord.Net;
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Interaction;
|
||||
using DataModel = Discord.API.ApplicationCommandInteractionData;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using Discord.Net;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using DataModel = Discord.API.ApplicationCommandInteractionData;
|
||||
using Model = Discord.API.Interaction;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
@@ -130,7 +130,7 @@ namespace Discord.WebSocket
|
||||
Data = model.Data.IsSpecified
|
||||
? model.Data.Value
|
||||
: null;
|
||||
|
||||
|
||||
Token = model.Token;
|
||||
Version = model.Version;
|
||||
Type = model.Type;
|
||||
@@ -398,7 +398,7 @@ namespace Discord.WebSocket
|
||||
/// <param name="options">The request options for this <see langword="async"/> request.</param>
|
||||
/// <returns>A task that represents the asynchronous operation of responding to the interaction.</returns>
|
||||
public abstract Task RespondWithModalAsync(Modal modal, RequestOptions options = null);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Attepts to get the channel this interaction was executed in.
|
||||
@@ -407,7 +407,7 @@ namespace Discord.WebSocket
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous operation of fetching the channel.
|
||||
/// </returns>
|
||||
public async ValueTask<IMessageChannel> GetChannelAsync(RequestOptions options = null)
|
||||
public async ValueTask<IMessageChannel> GetChannelAsync(RequestOptions options = null)
|
||||
{
|
||||
if (Channel != null)
|
||||
return Channel;
|
||||
@@ -419,10 +419,10 @@ namespace Discord.WebSocket
|
||||
{
|
||||
return (IMessageChannel)await Discord.GetChannelAsync(ChannelId.Value, options).ConfigureAwait(false);
|
||||
}
|
||||
catch(HttpException ex) when (ex.DiscordCode == DiscordErrorCode.MissingPermissions) { return null; } // bot can't view that channel, return null instead of throwing.
|
||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.MissingPermissions) { return null; } // bot can't view that channel, return null instead of throwing.
|
||||
}
|
||||
|
||||
#region IDiscordInteraction
|
||||
#region IDiscordInteraction
|
||||
/// <inheritdoc/>
|
||||
IUser IDiscordInteraction.User => User;
|
||||
|
||||
@@ -452,6 +452,6 @@ namespace Discord.WebSocket
|
||||
async Task<IUserMessage> IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options)
|
||||
=> await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false);
|
||||
#endif
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,10 @@ namespace Discord.WebSocket
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="limit"/> is less than 0.</exception>
|
||||
public IReadOnlyCollection<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
{
|
||||
if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit));
|
||||
if (limit == 0) return ImmutableArray<SocketMessage>.Empty;
|
||||
if (limit < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(limit));
|
||||
if (limit == 0)
|
||||
return ImmutableArray<SocketMessage>.Empty;
|
||||
|
||||
IEnumerable<ulong> cachedMessageIds;
|
||||
if (fromMessageId == null)
|
||||
|
||||
@@ -309,7 +309,7 @@ namespace Discord.WebSocket
|
||||
/// </returns>
|
||||
public override string ToString() => Content;
|
||||
internal SocketMessage Clone() => MemberwiseClone() as SocketMessage;
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region IMessage
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -86,11 +86,14 @@ namespace Discord.WebSocket
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (other == null) return false;
|
||||
if (other == this) return true;
|
||||
if (other == null)
|
||||
return false;
|
||||
if (other == this)
|
||||
return true;
|
||||
|
||||
var otherReaction = other as SocketReaction;
|
||||
if (otherReaction == null) return false;
|
||||
if (otherReaction == null)
|
||||
return false;
|
||||
|
||||
return UserId == otherReaction.UserId && MessageId == otherReaction.MessageId && Emote.Equals(otherReaction.Emote);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
base.Update(state, model);
|
||||
}
|
||||
|
||||
|
||||
private string DebuggerDisplay => $"{Author}: {Content} ({Id}, {Type})";
|
||||
internal new SocketSystemMessage Clone() => MemberwiseClone() as SocketSystemMessage;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UserModel = Discord.API.User;
|
||||
using MemberModel = Discord.API.GuildMember;
|
||||
using PresenceModel = Discord.API.Presence;
|
||||
using UserModel = Discord.API.User;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.ThreadMember;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
{
|
||||
@@ -142,7 +142,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
Thread = thread;
|
||||
Guild = guild;
|
||||
if(member is not null)
|
||||
if (member is not null)
|
||||
GuildUser = member;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace Discord.WebSocket
|
||||
internal static SocketThreadUser Create(SocketGuild guild, SocketThreadChannel thread, SocketGuildUser owner)
|
||||
{
|
||||
// this is used for creating the owner of the thread.
|
||||
var entity = new SocketThreadUser(guild, thread, owner.Id, owner);
|
||||
var entity = new SocketThreadUser(guild, thread, owner.Id, owner);
|
||||
entity.Update(new Model
|
||||
{
|
||||
JoinTimestamp = thread.CreatedAt,
|
||||
@@ -167,7 +167,7 @@ namespace Discord.WebSocket
|
||||
internal void Update(Model model)
|
||||
{
|
||||
ThreadJoinedAt = model.JoinTimestamp;
|
||||
if(model.GuildMember.IsSpecified)
|
||||
if (model.GuildMember.IsSpecified)
|
||||
GuildUser = Guild.AddOrUpdateUser(model.GuildMember.Value);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Discord.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
@@ -5,7 +6,6 @@ using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Rest;
|
||||
using Model = Discord.API.User;
|
||||
using PresenceModel = Discord.API.Presence;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Discord.WebSocket
|
||||
public bool IsStreaming => (_voiceStates & Flags.SelfStream) != 0;
|
||||
/// <inheritdoc />
|
||||
public bool IsVideoing => (_voiceStates & Flags.SelfVideo) != 0;
|
||||
|
||||
|
||||
|
||||
internal SocketVoiceState(SocketVoiceChannel voiceChannel, DateTimeOffset? requestToSpeak, string sessionId, bool isSelfMuted, bool isSelfDeafened, bool isMuted, bool isDeafened, bool isSuppressed, bool isStream, bool isVideo)
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Discord.WebSocket
|
||||
|
||||
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Webhook)";
|
||||
internal new SocketWebhookUser Clone() => MemberwiseClone() as SocketWebhookUser;
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region IGuildUser
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -18,13 +18,13 @@ namespace Discord.Interactions
|
||||
/// </summary>
|
||||
/// <param name="client">The underlying client.</param>
|
||||
/// <param name="interaction">The underlying interaction.</param>
|
||||
public ShardedInteractionContext (DiscordShardedClient client, TInteraction interaction)
|
||||
: base(client.GetShard(GetShardId(client, ( interaction.User as SocketGuildUser )?.Guild)), interaction)
|
||||
public ShardedInteractionContext(DiscordShardedClient client, TInteraction interaction)
|
||||
: base(client.GetShard(GetShardId(client, (interaction.User as SocketGuildUser)?.Guild)), interaction)
|
||||
{
|
||||
Client = client;
|
||||
}
|
||||
|
||||
private static int GetShardId (DiscordShardedClient client, IGuild guild)
|
||||
private static int GetShardId(DiscordShardedClient client, IGuild guild)
|
||||
=> guild == null ? 0 : client.GetShardIdFor(guild);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,14 +87,17 @@ namespace Discord.Net.Udp
|
||||
}
|
||||
public async Task StopInternalAsync(bool isDisposing = false)
|
||||
{
|
||||
try { _stopCancelTokenSource.Cancel(false); } catch { }
|
||||
try
|
||||
{ _stopCancelTokenSource.Cancel(false); }
|
||||
catch { }
|
||||
|
||||
if (!isDisposing)
|
||||
await (_task ?? Task.Delay(0)).ConfigureAwait(false);
|
||||
|
||||
if (_udp != null)
|
||||
{
|
||||
try { _udp.Dispose(); }
|
||||
try
|
||||
{ _udp.Dispose(); }
|
||||
catch { }
|
||||
_udp = null;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Discord.Net.Udp
|
||||
{
|
||||
public static class DefaultUdpSocketProvider
|
||||
{
|
||||
public static readonly UdpSocketProvider Instance = () =>
|
||||
public static readonly UdpSocketProvider Instance = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -110,7 +110,8 @@ namespace Discord.Net.WebSockets
|
||||
{
|
||||
_isDisconnecting = true;
|
||||
|
||||
try { _disconnectTokenSource.Cancel(false); }
|
||||
try
|
||||
{ _disconnectTokenSource.Cancel(false); }
|
||||
catch { }
|
||||
|
||||
if (_client != null)
|
||||
@@ -118,10 +119,12 @@ namespace Discord.Net.WebSockets
|
||||
if (!isDisposing)
|
||||
{
|
||||
var status = (WebSocketCloseStatus)closeCode;
|
||||
try { await _client.CloseOutputAsync(status, "", new CancellationToken()); }
|
||||
try
|
||||
{ await _client.CloseOutputAsync(status, "", new CancellationToken()); }
|
||||
catch { }
|
||||
}
|
||||
try { _client.Dispose(); }
|
||||
try
|
||||
{ _client.Dispose(); }
|
||||
catch { }
|
||||
|
||||
_client = null;
|
||||
@@ -176,7 +179,8 @@ namespace Discord.Net.WebSockets
|
||||
}
|
||||
try
|
||||
{
|
||||
if (_client == null) return;
|
||||
if (_client == null)
|
||||
return;
|
||||
|
||||
int frameCount = (int)Math.Ceiling((double)count / SendChunkSize);
|
||||
|
||||
@@ -223,7 +227,8 @@ namespace Discord.Net.WebSockets
|
||||
stream.Write(buffer.Array, 0, socketResult.Count);
|
||||
do
|
||||
{
|
||||
if (cancelToken.IsCancellationRequested) return;
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
return;
|
||||
socketResult = await _client.ReceiveAsync(buffer, cancelToken).ConfigureAwait(false);
|
||||
stream.Write(buffer.Array, 0, socketResult.Count);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user