Diff
checker
Testo
Testo
Immagini
Documenti
Excel
Cartelle
Legal
Enterprise
Applicazione per desktop
Prezzi
Accedi
Scarica Diffchecker Desktop
Confronta il testo
Trova la differenza tra due file di testo
Strumenti
Cronologia
Editor live
Nascondi spazi bianchi
Comprimi invariate
Senza a capo
Layout
Diviso
Unificato
Livello di dettaglio
Intelligente
Parola
Carattere
Stili testo
Modifica aspetto
Evidenziazione sintassi
Scegli sintassi
Ignora
Trasforma testo
Vai alla prima modifica
Modifica input
Diffchecker Desktop
Il modo più sicuro per usare Diffchecker. Ottieni l'app Diffchecker Desktop: i tuoi diff non lasciano mai il tuo computer!
Ottieni Desktop
Untitled Diff
Creato
5 anni fa
Il diff non scade mai
Eliminare
Esporta
Condividere
Spiegare
3 rimozioni
Linee
Totale
Rimosso
Caratteri
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
201 linee
Copia tutti
22 aggiunte
Linee
Totale
Aggiunto
Caratteri
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
208 linee
Copia tutti
/*
/*
Copia
Copiato
Copia
Copiato
* File: Discord
ClientWrapper.cs
* File: Discord
Sharded
ClientWrapper.cs
* Author: Angelo Breuer
* Author: Angelo Breuer
*
*
* The MIT License (MIT)
* The MIT License (MIT)
*
*
Copia
Copiato
Copia
Copiato
* 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>
Copia
Copiato
Copia
Copiato
/// 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>
Copia
Copiato
Copia
Copiato
public sealed class Discord
ClientWrapper : IDiscordClientWrapper, IDisposable
public sealed class Discord
Sharded
ClientWrapper : IDiscordClientWrapper, IDisposable
{
{
Copia
Copiato
Copia
Copiato
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>
Copia
Copiato
Copia
Copiato
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();
Copia
Copiato
Copia
Copiato
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();
Copia
Copiato
Copia
Copiato
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)
{
{
Copia
Copiato
Copia
Copiato
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);
Copia
Copiato
Copia
Copiato
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));
}
}
}
}
}
}
Diff salvati
Testo originale
Apri file
/* * 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)); } } }
Testo modificato
Apri file
/* * 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)); } } }
Trovare la differenza