Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
ライブエディター
空白の変更を非表示
未変更行を折りたたむ
折り返しなし
レイアウト
分割
統合
比較精度
スマート
単語
文字
テキストスタイル
外観を変更
シンタックスハイライト
構文を選択
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
Untitled Diff
作成日
5 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
3 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
201 行
すべてコピー
22 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
208 行
すべてコピー
/*
/*
コピー
コピー済み
コピー
コピー済み
* File: Discord
ClientWrapper.cs
* File: Discord
Sharded
ClientWrapper.cs
* Author: Angelo Breuer
* Author: Angelo Breuer
*
*
* The MIT License (MIT)
* The MIT License (MIT)
*
*
コピー
コピー済み
コピー
コピー済み
* 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>
コピー
コピー済み
コピー
コピー済み
/// 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>
コピー
コピー済み
コピー
コピー済み
public sealed class Discord
ClientWrapper : IDiscordClientWrapper, IDisposable
public sealed class Discord
Sharded
ClientWrapper : IDiscordClientWrapper, IDisposable
{
{
コピー
コピー済み
コピー
コピー済み
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>
コピー
コピー済み
コピー
コピー済み
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();
コピー
コピー済み
コピー
コピー済み
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();
コピー
コピー済み
コピー
コピー済み
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)
{
{
コピー
コピー済み
コピー
コピー済み
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);
コピー
コピー済み
コピー
コピー済み
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));
}
}
}
}
}
}
保存された差分
原文
ファイルを開く
/* * 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)); } } }
変更されたテキスト
ファイルを開く
/* * 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)); } } }
違いを見つける