Diff
checker
Texto
Texto
Imágenes
Documentos
Excel
Carpetas
Legal
Enterprise
Aplicación de escritorio
Precios
Iniciar sesión
Descargar Diffchecker Desktop
Comparar texto
Encuentra la diferencia entre dos archivos de texto
Herramientas
Historial
Editor live
Ocultar espacios en blanco
Ocultar sin cambios
Sin ajuste de línea
Vista
Dividido
Unificado
Nivel de detalle
Inteligente
Palabra
Letra
Estilos de texto
Cambiar apariencia
Resaltado de sintaxis
Elegir sintaxis
Ignorar
Transformar texto
Ir al primer cambio
Editar entrada
Diffchecker Desktop
La forma más segura de usar Diffchecker. ¡Obtén la app de Diffchecker Desktop: tus diffs nunca salen de tu computadora!
Obtener Desktop
Untitled Diff
Creado
hace 5 años
El diff nunca expira
Borrar
Exportar
Compartir
Explicar
3 eliminaciones
Líneas
Total
Eliminado
Caracteres
Total
Eliminado
Para continuar usando esta función, actualice a
Diff
checker
Pro
Ver precios
201 líneas
Copiar todo
22 adiciones
Líneas
Total
Añadido
Caracteres
Total
Añadido
Para continuar usando esta función, actualice a
Diff
checker
Pro
Ver precios
208 líneas
Copiar todo
/*
/*
Copiar
Copiado
Copiar
Copiado
* File: Discord
ClientWrapper.cs
* File: Discord
Sharded
ClientWrapper.cs
* Author: Angelo Breuer
* Author: Angelo Breuer
*
*
* The MIT License (MIT)
* The MIT License (MIT)
*
*
Copiar
Copiado
Copiar
Copiado
* Copyright (c) Angelo Breuer 202
0
* Copyright (c) Angelo Breuer 202
1
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* THE SOFTWARE.
*/
*/
namespace Lavalink4NET.DSharpPlus
namespace Lavalink4NET.DSharpPlus
{
{
using System;
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks;
using global::DSharpPlus;
using global::DSharpPlus;
using global::DSharpPlus.EventArgs;
using global::DSharpPlus.EventArgs;
using Lavalink4NET.Events;
using Lavalink4NET.Events;
using Newtonsoft.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq;
/// <summary>
/// <summary>
Copiar
Copiado
Copiar
Copiado
/// A wrapper for the discord
client from the "DSharpPlus" discord client library. (https://github.com/DSharpPlus/DSharpPlus)
/// A wrapper for the discord
sharded
client from the "DSharpPlus" discord client library. (https://github.com/DSharpPlus/DSharpPlus)
/// </summary>
/// </summary>
Copiar
Copiado
Copiar
Copiado
public sealed class Discord
ClientWrapper : IDiscordClientWrapper, IDisposable
public sealed class Discord
Sharded
ClientWrapper : IDiscordClientWrapper, IDisposable
{
{
Copiar
Copiado
Copiar
Copiado
private readonly Discord
Client _client;
private readonly Discord
Sharded
Client _client;
private bool _disposed;
private bool _disposed;
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="DiscordClientWrapper"/> class.
/// Initializes a new instance of the <see cref="DiscordClientWrapper"/> class.
/// </summary>
/// </summary>
/// <param name="client">the sharded discord client</param>
/// <param name="client">the sharded discord client</param>
/// <exception cref="ArgumentNullException">
/// <exception cref="ArgumentNullException">
/// thrown if the specified <paramref name="client"/> is <see langword="null"/>.
/// thrown if the specified <paramref name="client"/> is <see langword="null"/>.
/// </exception>
/// </exception>
Copiar
Copiado
Copiar
Copiado
public Discord
ClientWrapper(Discord
Client client)
public Discord
Sharded
ClientWrapper(Discord
Sharded
Client client)
{
{
_client = client ?? throw new ArgumentNullException(nameof(client));
_client = client ?? throw new ArgumentNullException(nameof(client));
_client.VoiceStateUpdated += OnVoiceStateUpdated;
_client.VoiceStateUpdated += OnVoiceStateUpdated;
_client.VoiceServerUpdated += OnVoiceServerUpdated;
_client.VoiceServerUpdated += OnVoiceServerUpdated;
}
}
/// <inheritdoc/>
/// <inheritdoc/>
public event AsyncEventHandler<VoiceServer>? VoiceServerUpdated;
public event AsyncEventHandler<VoiceServer>? VoiceServerUpdated;
/// <inheritdoc/>
/// <inheritdoc/>
public event AsyncEventHandler<Events.VoiceStateUpdateEventArgs>? VoiceStateUpdated;
public event AsyncEventHandler<Events.VoiceStateUpdateEventArgs>? VoiceStateUpdated;
/// <inheritdoc/>
/// <inheritdoc/>
public ulong CurrentUserId
public ulong CurrentUserId
{
{
get
get
{
{
EnsureNotDisposed();
EnsureNotDisposed();
return _client.CurrentUser.Id;
return _client.CurrentUser.Id;
}
}
}
}
/// <inheritdoc/>
/// <inheritdoc/>
public int ShardCount
public int ShardCount
{
{
get
get
{
{
EnsureNotDisposed();
EnsureNotDisposed();
Copiar
Copiado
Copiar
Copiado
return _client.Shard
Count;
return _client.Shard
Clients.
Count;
}
}
}
}
/// <inheritdoc/>
/// <inheritdoc/>
public void Dispose()
public void Dispose()
{
{
if (_disposed)
if (_disposed)
{
{
return;
return;
}
}
_disposed = true;
_disposed = true;
_client.VoiceStateUpdated -= OnVoiceStateUpdated;
_client.VoiceStateUpdated -= OnVoiceStateUpdated;
_client.VoiceServerUpdated -= OnVoiceServerUpdated;
_client.VoiceServerUpdated -= OnVoiceServerUpdated;
}
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
public async Task<IEnumerable<ulong>> GetChannelUsersAsync(ulong guildId, ulong voiceChannelId)
public async Task<IEnumerable<ulong>> GetChannelUsersAsync(ulong guildId, ulong voiceChannelId)
{
{
EnsureNotDisposed();
EnsureNotDisposed();
Copiar
Copiado
Copiar
Copiado
var guild = await
_client
.GetGuildAsync(guildId)
var shard = _client.GetShard(guildId)
?? throw new InvalidOperationException("Shard is not served by this client.");
var guild = await
shard
.GetGuildAsync(guildId)
.ConfigureAwait(false)
?? throw new ArgumentException("Invalid or inaccessible guild: " + guildId, nameof(guildId));
?? throw new ArgumentException("Invalid or inaccessible guild: " + guildId, nameof(guildId));
var channel = guild.GetChannel(voiceChannelId)
var channel = guild.GetChannel(voiceChannelId)
?? throw new ArgumentException("Invalid or inaccessible voice channel: " + voiceChannelId, nameof(voiceChannelId));
?? throw new ArgumentException("Invalid or inaccessible voice channel: " + voiceChannelId, nameof(voiceChannelId));
return channel.Users.Select(s => s.Id);
return channel.Users.Select(s => s.Id);
}
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
public async Task InitializeAsync()
public async Task InitializeAsync()
{
{
EnsureNotDisposed();
EnsureNotDisposed();
var startTime = DateTimeOffset.UtcNow;
var startTime = DateTimeOffset.UtcNow;
// await until current user arrived
// await until current user arrived
while (_client.CurrentUser is null)
while (_client.CurrentUser is null)
{
{
Copiar
Copiado
Copiar
Copiado
await Task.Delay(10)
;
await Task.Delay(10)
.ConfigureAwait(false)
;
// timeout exceeded
// timeout exceeded
if (DateTimeOffset.UtcNow - startTime > TimeSpan.FromSeconds(10))
if (DateTimeOffset.UtcNow - startTime > TimeSpan.FromSeconds(10))
{
{
throw new TimeoutException("Waited 10 seconds for current user to arrive! Make sure you start " +
throw new TimeoutException("Waited 10 seconds for current user to arrive! Make sure you start " +
"the discord client, before initializing the discord wrapper!");
"the discord client, before initializing the discord wrapper!");
}
}
}
}
}
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
public async Task SendVoiceUpdateAsync(ulong guildId, ulong? voiceChannelId, bool selfDeaf = false, bool selfMute = false)
public async Task SendVoiceUpdateAsync(ulong guildId, ulong? voiceChannelId, bool selfDeaf = false, bool selfMute = false)
{
{
EnsureNotDisposed();
EnsureNotDisposed();
var payload = new JObject();
var payload = new JObject();
var data = new VoiceStateUpdatePayload(guildId, voiceChannelId, selfMute, selfDeaf);
var data = new VoiceStateUpdatePayload(guildId, voiceChannelId, selfMute, selfDeaf);
payload.Add("op", 4);
payload.Add("op", 4);
payload.Add("d", JObject.FromObject(data));
payload.Add("d", JObject.FromObject(data));
var message = JsonConvert.SerializeObject(payload, Formatting.None);
var message = JsonConvert.SerializeObject(payload, Formatting.None);
Copiar
Copiado
Copiar
Copiado
await
_client
.GetWebSocketClient().SendMessageAsync(message)
;
var shard = _client.GetShard(guildId)
?? throw new InvalidOperationException("Shard is not served by this client.");
await
shard
.GetWebSocketClient().SendMessageAsync(message)
.ConfigureAwait(false)
;
}
}
/// <summary>
/// <summary>
/// Throws an <see cref="ObjectDisposedException"/> if the <see
/// Throws an <see cref="ObjectDisposedException"/> if the <see
/// cref="DiscordClientWrapper"/> is disposed.
/// cref="DiscordClientWrapper"/> is disposed.
/// </summary>
/// </summary>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
private void EnsureNotDisposed()
private void EnsureNotDisposed()
{
{
if (_disposed)
if (_disposed)
{
{
throw new ObjectDisposedException(nameof(DiscordClientWrapper));
throw new ObjectDisposedException(nameof(DiscordClientWrapper));
}
}
}
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
private Task OnVoiceServerUpdated(DiscordClient _, VoiceServerUpdateEventArgs voiceServer)
private Task OnVoiceServerUpdated(DiscordClient _, VoiceServerUpdateEventArgs voiceServer)
{
{
EnsureNotDisposed();
EnsureNotDisposed();
var args = new VoiceServer(voiceServer.Guild.Id, voiceServer.GetVoiceToken(), voiceServer.Endpoint);
var args = new VoiceServer(voiceServer.Guild.Id, voiceServer.GetVoiceToken(), voiceServer.Endpoint);
return VoiceServerUpdated.InvokeAsync(this, args);
return VoiceServerUpdated.InvokeAsync(this, args);
}
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
/// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
private Task OnVoiceStateUpdated(DiscordClient _, global::DSharpPlus.EventArgs.VoiceStateUpdateEventArgs eventArgs)
private Task OnVoiceStateUpdated(DiscordClient _, global::DSharpPlus.EventArgs.VoiceStateUpdateEventArgs eventArgs)
{
{
EnsureNotDisposed();
EnsureNotDisposed();
// session id is the same as the resume key so DSharpPlus should be able to give us the
// session id is the same as the resume key so DSharpPlus should be able to give us the
// session key in either before or after voice state
// session key in either before or after voice state
var sessionId = eventArgs.Before?.GetSessionId() ?? eventArgs.After.GetSessionId();
var sessionId = eventArgs.Before?.GetSessionId() ?? eventArgs.After.GetSessionId();
// create voice state
// create voice state
var voiceState = new VoiceState(
var voiceState = new VoiceState(
voiceChannelId: eventArgs.After?.Channel?.Id,
voiceChannelId: eventArgs.After?.Channel?.Id,
guildId: eventArgs.Guild.Id,
guildId: eventArgs.Guild.Id,
voiceSessionId: sessionId);
voiceSessionId: sessionId);
// invoke event
// invoke event
return VoiceStateUpdated.InvokeAsync(this,
return VoiceStateUpdated.InvokeAsync(this,
new Events.VoiceStateUpdateEventArgs(eventArgs.User.Id, voiceState));
new Events.VoiceStateUpdateEventArgs(eventArgs.User.Id, voiceState));
}
}
}
}
}
}
Diferencias guardadas
Texto original
Abrir archivo
/* * File: DiscordClientWrapper.cs * Author: Angelo Breuer * * The MIT License (MIT) * * Copyright (c) Angelo Breuer 2020 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ namespace Lavalink4NET.DSharpPlus { using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using global::DSharpPlus; using global::DSharpPlus.EventArgs; using Lavalink4NET.Events; using Newtonsoft.Json; using Newtonsoft.Json.Linq; /// <summary> /// A wrapper for the discord client from the "DSharpPlus" discord client library. (https://github.com/DSharpPlus/DSharpPlus) /// </summary> public sealed class DiscordClientWrapper : IDiscordClientWrapper, IDisposable { private readonly DiscordClient _client; private bool _disposed; /// <summary> /// Initializes a new instance of the <see cref="DiscordClientWrapper"/> class. /// </summary> /// <param name="client">the sharded discord client</param> /// <exception cref="ArgumentNullException"> /// thrown if the specified <paramref name="client"/> is <see langword="null"/>. /// </exception> public DiscordClientWrapper(DiscordClient client) { _client = client ?? throw new ArgumentNullException(nameof(client)); _client.VoiceStateUpdated += OnVoiceStateUpdated; _client.VoiceServerUpdated += OnVoiceServerUpdated; } /// <inheritdoc/> public event AsyncEventHandler<VoiceServer>? VoiceServerUpdated; /// <inheritdoc/> public event AsyncEventHandler<Events.VoiceStateUpdateEventArgs>? VoiceStateUpdated; /// <inheritdoc/> public ulong CurrentUserId { get { EnsureNotDisposed(); return _client.CurrentUser.Id; } } /// <inheritdoc/> public int ShardCount { get { EnsureNotDisposed(); return _client.ShardCount; } } /// <inheritdoc/> public void Dispose() { if (_disposed) { return; } _disposed = true; _client.VoiceStateUpdated -= OnVoiceStateUpdated; _client.VoiceServerUpdated -= OnVoiceServerUpdated; } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> public async Task<IEnumerable<ulong>> GetChannelUsersAsync(ulong guildId, ulong voiceChannelId) { EnsureNotDisposed(); var guild = await _client.GetGuildAsync(guildId) ?? throw new ArgumentException("Invalid or inaccessible guild: " + guildId, nameof(guildId)); var channel = guild.GetChannel(voiceChannelId) ?? throw new ArgumentException("Invalid or inaccessible voice channel: " + voiceChannelId, nameof(voiceChannelId)); return channel.Users.Select(s => s.Id); } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> public async Task InitializeAsync() { EnsureNotDisposed(); var startTime = DateTimeOffset.UtcNow; // await until current user arrived while (_client.CurrentUser is null) { await Task.Delay(10); // timeout exceeded if (DateTimeOffset.UtcNow - startTime > TimeSpan.FromSeconds(10)) { throw new TimeoutException("Waited 10 seconds for current user to arrive! Make sure you start " + "the discord client, before initializing the discord wrapper!"); } } } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> public async Task SendVoiceUpdateAsync(ulong guildId, ulong? voiceChannelId, bool selfDeaf = false, bool selfMute = false) { EnsureNotDisposed(); var payload = new JObject(); var data = new VoiceStateUpdatePayload(guildId, voiceChannelId, selfMute, selfDeaf); payload.Add("op", 4); payload.Add("d", JObject.FromObject(data)); var message = JsonConvert.SerializeObject(payload, Formatting.None); await _client.GetWebSocketClient().SendMessageAsync(message); } /// <summary> /// Throws an <see cref="ObjectDisposedException"/> if the <see /// cref="DiscordClientWrapper"/> is disposed. /// </summary> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> private void EnsureNotDisposed() { if (_disposed) { throw new ObjectDisposedException(nameof(DiscordClientWrapper)); } } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> private Task OnVoiceServerUpdated(DiscordClient _, VoiceServerUpdateEventArgs voiceServer) { EnsureNotDisposed(); var args = new VoiceServer(voiceServer.Guild.Id, voiceServer.GetVoiceToken(), voiceServer.Endpoint); return VoiceServerUpdated.InvokeAsync(this, args); } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> private Task OnVoiceStateUpdated(DiscordClient _, global::DSharpPlus.EventArgs.VoiceStateUpdateEventArgs eventArgs) { EnsureNotDisposed(); // session id is the same as the resume key so DSharpPlus should be able to give us the // session key in either before or after voice state var sessionId = eventArgs.Before?.GetSessionId() ?? eventArgs.After.GetSessionId(); // create voice state var voiceState = new VoiceState( voiceChannelId: eventArgs.After?.Channel?.Id, guildId: eventArgs.Guild.Id, voiceSessionId: sessionId); // invoke event return VoiceStateUpdated.InvokeAsync(this, new Events.VoiceStateUpdateEventArgs(eventArgs.User.Id, voiceState)); } } }
Texto modificado
Abrir archivo
/* * File: DiscordShardedClientWrapper.cs * Author: Angelo Breuer * * The MIT License (MIT) * * Copyright (c) Angelo Breuer 2021 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ namespace Lavalink4NET.DSharpPlus { using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using global::DSharpPlus; using global::DSharpPlus.EventArgs; using Lavalink4NET.Events; using Newtonsoft.Json; using Newtonsoft.Json.Linq; /// <summary> /// A wrapper for the discord sharded client from the "DSharpPlus" discord client library. (https://github.com/DSharpPlus/DSharpPlus) /// </summary> public sealed class DiscordShardedClientWrapper : IDiscordClientWrapper, IDisposable { private readonly DiscordShardedClient _client; private bool _disposed; /// <summary> /// Initializes a new instance of the <see cref="DiscordClientWrapper"/> class. /// </summary> /// <param name="client">the sharded discord client</param> /// <exception cref="ArgumentNullException"> /// thrown if the specified <paramref name="client"/> is <see langword="null"/>. /// </exception> public DiscordShardedClientWrapper(DiscordShardedClient client) { _client = client ?? throw new ArgumentNullException(nameof(client)); _client.VoiceStateUpdated += OnVoiceStateUpdated; _client.VoiceServerUpdated += OnVoiceServerUpdated; } /// <inheritdoc/> public event AsyncEventHandler<VoiceServer>? VoiceServerUpdated; /// <inheritdoc/> public event AsyncEventHandler<Events.VoiceStateUpdateEventArgs>? VoiceStateUpdated; /// <inheritdoc/> public ulong CurrentUserId { get { EnsureNotDisposed(); return _client.CurrentUser.Id; } } /// <inheritdoc/> public int ShardCount { get { EnsureNotDisposed(); return _client.ShardClients.Count; } } /// <inheritdoc/> public void Dispose() { if (_disposed) { return; } _disposed = true; _client.VoiceStateUpdated -= OnVoiceStateUpdated; _client.VoiceServerUpdated -= OnVoiceServerUpdated; } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> public async Task<IEnumerable<ulong>> GetChannelUsersAsync(ulong guildId, ulong voiceChannelId) { EnsureNotDisposed(); var shard = _client.GetShard(guildId) ?? throw new InvalidOperationException("Shard is not served by this client."); var guild = await shard.GetGuildAsync(guildId).ConfigureAwait(false) ?? throw new ArgumentException("Invalid or inaccessible guild: " + guildId, nameof(guildId)); var channel = guild.GetChannel(voiceChannelId) ?? throw new ArgumentException("Invalid or inaccessible voice channel: " + voiceChannelId, nameof(voiceChannelId)); return channel.Users.Select(s => s.Id); } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> public async Task InitializeAsync() { EnsureNotDisposed(); var startTime = DateTimeOffset.UtcNow; // await until current user arrived while (_client.CurrentUser is null) { await Task.Delay(10).ConfigureAwait(false); // timeout exceeded if (DateTimeOffset.UtcNow - startTime > TimeSpan.FromSeconds(10)) { throw new TimeoutException("Waited 10 seconds for current user to arrive! Make sure you start " + "the discord client, before initializing the discord wrapper!"); } } } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> public async Task SendVoiceUpdateAsync(ulong guildId, ulong? voiceChannelId, bool selfDeaf = false, bool selfMute = false) { EnsureNotDisposed(); var payload = new JObject(); var data = new VoiceStateUpdatePayload(guildId, voiceChannelId, selfMute, selfDeaf); payload.Add("op", 4); payload.Add("d", JObject.FromObject(data)); var message = JsonConvert.SerializeObject(payload, Formatting.None); var shard = _client.GetShard(guildId) ?? throw new InvalidOperationException("Shard is not served by this client."); await shard.GetWebSocketClient().SendMessageAsync(message).ConfigureAwait(false); } /// <summary> /// Throws an <see cref="ObjectDisposedException"/> if the <see /// cref="DiscordClientWrapper"/> is disposed. /// </summary> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> private void EnsureNotDisposed() { if (_disposed) { throw new ObjectDisposedException(nameof(DiscordClientWrapper)); } } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> private Task OnVoiceServerUpdated(DiscordClient _, VoiceServerUpdateEventArgs voiceServer) { EnsureNotDisposed(); var args = new VoiceServer(voiceServer.Guild.Id, voiceServer.GetVoiceToken(), voiceServer.Endpoint); return VoiceServerUpdated.InvokeAsync(this, args); } /// <inheritdoc/> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> private Task OnVoiceStateUpdated(DiscordClient _, global::DSharpPlus.EventArgs.VoiceStateUpdateEventArgs eventArgs) { EnsureNotDisposed(); // session id is the same as the resume key so DSharpPlus should be able to give us the // session key in either before or after voice state var sessionId = eventArgs.Before?.GetSessionId() ?? eventArgs.After.GetSessionId(); // create voice state var voiceState = new VoiceState( voiceChannelId: eventArgs.After?.Channel?.Id, guildId: eventArgs.Guild.Id, voiceSessionId: sessionId); // invoke event return VoiceStateUpdated.InvokeAsync(this, new Events.VoiceStateUpdateEventArgs(eventArgs.User.Id, voiceState)); } } }
Encontrar la diferencia