Switched ids to use int64 rather than strings
This commit is contained in:
@@ -4,7 +4,7 @@ namespace Discord.Commands.Permissions.Userlist
|
|||||||
{
|
{
|
||||||
public class BlacklistService : UserlistService
|
public class BlacklistService : UserlistService
|
||||||
{
|
{
|
||||||
public BlacklistService(IEnumerable<string> initialList = null)
|
public BlacklistService(IEnumerable<long> initialList = null)
|
||||||
: base(initialList)
|
: base(initialList)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ namespace Discord.Commands.Permissions.Userlist
|
|||||||
{
|
{
|
||||||
public class UserlistService : IService
|
public class UserlistService : IService
|
||||||
{
|
{
|
||||||
protected readonly ConcurrentDictionary<string, bool> _userList;
|
protected readonly ConcurrentDictionary<long, bool> _userList;
|
||||||
private DiscordClient _client;
|
private DiscordClient _client;
|
||||||
|
|
||||||
public DiscordClient Client => _client;
|
public DiscordClient Client => _client;
|
||||||
public IEnumerable<string> UserIds => _userList.Select(x => x.Key);
|
public IEnumerable<long> UserIds => _userList.Select(x => x.Key);
|
||||||
|
|
||||||
public UserlistService(IEnumerable<string> initialList = null)
|
public UserlistService(IEnumerable<long> initialList = null)
|
||||||
{
|
{
|
||||||
if (initialList != null)
|
if (initialList != null)
|
||||||
_userList = new ConcurrentDictionary<string, bool>(initialList.Select(x => new KeyValuePair<string, bool>(x, true)));
|
_userList = new ConcurrentDictionary<long, bool>(initialList.Select(x => new KeyValuePair<long, bool>(x, true)));
|
||||||
else
|
else
|
||||||
_userList = new ConcurrentDictionary<string, bool>();
|
_userList = new ConcurrentDictionary<long, bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(User user)
|
public void Add(User user)
|
||||||
@@ -26,9 +26,9 @@ namespace Discord.Commands.Permissions.Userlist
|
|||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
_userList[user.Id] = true;
|
_userList[user.Id] = true;
|
||||||
}
|
}
|
||||||
public void Add(string userId)
|
public void Add(long userId)
|
||||||
{
|
{
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
_userList[userId] = true;
|
_userList[userId] = true;
|
||||||
}
|
}
|
||||||
public bool Remove(User user)
|
public bool Remove(User user)
|
||||||
@@ -37,9 +37,9 @@ namespace Discord.Commands.Permissions.Userlist
|
|||||||
bool ignored;
|
bool ignored;
|
||||||
return _userList.TryRemove(user.Id, out ignored);
|
return _userList.TryRemove(user.Id, out ignored);
|
||||||
}
|
}
|
||||||
public bool Remove(string userId)
|
public bool Remove(long userId)
|
||||||
{
|
{
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
bool ignored;
|
bool ignored;
|
||||||
return _userList.TryRemove(userId, out ignored);
|
return _userList.TryRemove(userId, out ignored);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace Discord.Commands.Permissions.Userlist
|
|||||||
{
|
{
|
||||||
public class WhitelistService : UserlistService
|
public class WhitelistService : UserlistService
|
||||||
{
|
{
|
||||||
public WhitelistService(IEnumerable<string> initialList = null)
|
public WhitelistService(IEnumerable<long> initialList = null)
|
||||||
: base(initialList)
|
: base(initialList)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ namespace Discord.Modules
|
|||||||
private readonly string _name, _id;
|
private readonly string _name, _id;
|
||||||
private readonly FilterType _filterType;
|
private readonly FilterType _filterType;
|
||||||
private readonly bool _useServerWhitelist, _useChannelWhitelist, _allowAll, _allowPrivate;
|
private readonly bool _useServerWhitelist, _useChannelWhitelist, _allowAll, _allowPrivate;
|
||||||
private readonly ConcurrentDictionary<string, Server> _enabledServers;
|
private readonly ConcurrentDictionary<long, Server> _enabledServers;
|
||||||
private readonly ConcurrentDictionary<string, Channel> _enabledChannels;
|
private readonly ConcurrentDictionary<long, Channel> _enabledChannels;
|
||||||
private readonly ConcurrentDictionary<string, int> _indirectServers;
|
private readonly ConcurrentDictionary<long, int> _indirectServers;
|
||||||
|
|
||||||
public DiscordClient Client => _client;
|
public DiscordClient Client => _client;
|
||||||
public string Name => _name;
|
public string Name => _name;
|
||||||
@@ -70,9 +70,9 @@ namespace Discord.Modules
|
|||||||
_useChannelWhitelist = filterType.HasFlag(FilterType.ChannelWhitelist);
|
_useChannelWhitelist = filterType.HasFlag(FilterType.ChannelWhitelist);
|
||||||
_allowPrivate = filterType.HasFlag(FilterType.AllowPrivate);
|
_allowPrivate = filterType.HasFlag(FilterType.AllowPrivate);
|
||||||
|
|
||||||
_enabledServers = new ConcurrentDictionary<string, Server>();
|
_enabledServers = new ConcurrentDictionary<long, Server>();
|
||||||
_enabledChannels = new ConcurrentDictionary<string, Channel>();
|
_enabledChannels = new ConcurrentDictionary<long, Channel>();
|
||||||
_indirectServers = new ConcurrentDictionary<string, int>();
|
_indirectServers = new ConcurrentDictionary<long, int>();
|
||||||
|
|
||||||
if (_allowAll || _useServerWhitelist) //Server-only events
|
if (_allowAll || _useServerWhitelist) //Server-only events
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,6 +76,15 @@
|
|||||||
<Compile Include="..\Discord.Net\API\Channels.cs">
|
<Compile Include="..\Discord.Net\API\Channels.cs">
|
||||||
<Link>API\Channels.cs</Link>
|
<Link>API\Channels.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Discord.Net\API\Converters\LongCollectionConverter.cs">
|
||||||
|
<Link>API\Converters\LongCollectionConverter.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Discord.Net\API\Converters\LongStringConverter.cs">
|
||||||
|
<Link>API\Converters\LongStringConverter.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Discord.Net\API\Converters\ShortStringConverter.cs">
|
||||||
|
<Link>API\Converters\ShortStringConverter.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Discord.Net\API\Endpoints.cs">
|
<Compile Include="..\Discord.Net\API\Endpoints.cs">
|
||||||
<Link>API\Endpoints.cs</Link>
|
<Link>API\Endpoints.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -220,6 +229,9 @@
|
|||||||
<Compile Include="..\Discord.Net\Helpers\Format.cs">
|
<Compile Include="..\Discord.Net\Helpers\Format.cs">
|
||||||
<Link>Helpers\Format.cs</Link>
|
<Link>Helpers\Format.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Discord.Net\Helpers\IdConvert.cs">
|
||||||
|
<Link>Helpers\IdConvert.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Discord.Net\Helpers\Mention.cs">
|
<Compile Include="..\Discord.Net\Helpers\Mention.cs">
|
||||||
<Link>Helpers\Mention.cs</Link>
|
<Link>Helpers\Mention.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -12,9 +13,11 @@ namespace Discord.API
|
|||||||
public class ChannelReference
|
public class ChannelReference
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string GuildId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long GuildId;
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name;
|
public string Name;
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
@@ -27,7 +30,8 @@ namespace Discord.API
|
|||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type;
|
public string Type;
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("deny")]
|
[JsonProperty("deny")]
|
||||||
public uint Deny;
|
public uint Deny;
|
||||||
[JsonProperty("allow")]
|
[JsonProperty("allow")]
|
||||||
@@ -35,7 +39,8 @@ namespace Discord.API
|
|||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("last_message_id")]
|
[JsonProperty("last_message_id")]
|
||||||
public string LastMessageId;
|
[JsonConverter(typeof(NullableLongStringConverter))]
|
||||||
|
public long? LastMessageId;
|
||||||
[JsonProperty("is_private")]
|
[JsonProperty("is_private")]
|
||||||
public bool IsPrivate;
|
public bool IsPrivate;
|
||||||
[JsonProperty("position")]
|
[JsonProperty("position")]
|
||||||
@@ -59,7 +64,8 @@ namespace Discord.API
|
|||||||
public class CreatePMChannelRequest
|
public class CreatePMChannelRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("recipient_id")]
|
[JsonProperty("recipient_id")]
|
||||||
public string RecipientId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long RecipientId;
|
||||||
}
|
}
|
||||||
public class CreateChannelResponse : ChannelInfo { }
|
public class CreateChannelResponse : ChannelInfo { }
|
||||||
|
|
||||||
@@ -82,7 +88,8 @@ namespace Discord.API
|
|||||||
public sealed class Channel
|
public sealed class Channel
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("position")]
|
[JsonProperty("position")]
|
||||||
public uint Position;
|
public uint Position;
|
||||||
}
|
}
|
||||||
|
|||||||
75
src/Discord.Net/API/Converters/LongCollectionConverter.cs
Normal file
75
src/Discord.Net/API/Converters/LongCollectionConverter.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Discord.API.Converters
|
||||||
|
{
|
||||||
|
internal class EnumerableLongStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(IEnumerable<long>);
|
||||||
|
}
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
List<long> result = new List<long>();
|
||||||
|
if (reader.TokenType == JsonToken.StartArray)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
while (reader.TokenType != JsonToken.EndArray)
|
||||||
|
{
|
||||||
|
result.Add(IdConvert.ToLong((string)reader.Value));
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
writer.WriteNull();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteStartArray();
|
||||||
|
foreach (var v in (IEnumerable<long>)value)
|
||||||
|
writer.WriteValue(IdConvert.ToString(v));
|
||||||
|
writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class LongArrayStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(IEnumerable<long[]>);
|
||||||
|
}
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
List<long> result = new List<long>();
|
||||||
|
if (reader.TokenType == JsonToken.StartArray)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
while (reader.TokenType != JsonToken.EndArray)
|
||||||
|
{
|
||||||
|
result.Add(IdConvert.ToLong((string)reader.Value));
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
writer.WriteNull();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteStartArray();
|
||||||
|
var a = (long[])value;
|
||||||
|
for (int i = 0; i < a.Length; i++)
|
||||||
|
writer.WriteValue(IdConvert.ToString(a[i]));
|
||||||
|
writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/Discord.Net/API/Converters/LongStringConverter.cs
Normal file
37
src/Discord.Net/API/Converters/LongStringConverter.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Discord.API.Converters
|
||||||
|
{
|
||||||
|
internal class LongStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(long);
|
||||||
|
}
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
return IdConvert.ToLong((string)reader.Value);
|
||||||
|
}
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
writer.WriteValue(IdConvert.ToString((long)value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NullableLongStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(long?);
|
||||||
|
}
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
return IdConvert.ToNullableLong((string)reader.Value);
|
||||||
|
}
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
writer.WriteValue(IdConvert.ToString((long?)value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/Discord.Net/API/Converters/ShortStringConverter.cs
Normal file
37
src/Discord.Net/API/Converters/ShortStringConverter.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Discord.API.Converters
|
||||||
|
{
|
||||||
|
/*internal class ShortStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(short);
|
||||||
|
}
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
return IdConvert.ToShort((string)reader.Value);
|
||||||
|
}
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
writer.WriteValue(IdConvert.ToString((short)value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NullableShortStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(short?);
|
||||||
|
}
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
return IdConvert.ToNullableShort((string)reader.Value);
|
||||||
|
}
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
writer.WriteValue(IdConvert.ToString((short?)value));
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
@@ -12,33 +12,35 @@
|
|||||||
public const string AuthLogout = "auth/logout";
|
public const string AuthLogout = "auth/logout";
|
||||||
|
|
||||||
public const string Channels = "channels";
|
public const string Channels = "channels";
|
||||||
public static string Channel(string channelId) => $"channels/{channelId}";
|
public static string Channel(long channelId) => $"channels/{channelId}";
|
||||||
public static string ChannelInvites(string channelId) => $"channels/{channelId}/invites";
|
public static string ChannelInvites(long channelId) => $"channels/{channelId}/invites";
|
||||||
public static string ChannelMessages(string channelId) => $"channels/{channelId}/messages";
|
public static string ChannelMessages(long channelId) => $"channels/{channelId}/messages";
|
||||||
public static string ChannelMessages(string channelId, int limit) => $"channels/{channelId}/messages?limit={limit}";
|
public static string ChannelMessages(long channelId, int limit) => $"channels/{channelId}/messages?limit={limit}";
|
||||||
public static string ChannelMessages(string channelId, int limit, string relativeId, string relativeDir) => $"channels/{channelId}/messages?limit={limit}&{relativeDir}={relativeId}";
|
public static string ChannelMessages(long channelId, int limit, long relativeId, string relativeDir) => $"channels/{channelId}/messages?limit={limit}&{relativeDir}={relativeId}";
|
||||||
public static string ChannelMessage(string channelId, string msgId) => $"channels/{channelId}/messages/{msgId}";
|
public static string ChannelMessage(long channelId, long msgId) => $"channels/{channelId}/messages/{msgId}";
|
||||||
public static string ChannelMessageAck(string channelId, string msgId) => $"channels/{channelId}/messages/{msgId}/ack";
|
public static string ChannelMessageAck(long channelId, long msgId) => $"channels/{channelId}/messages/{msgId}/ack";
|
||||||
public static string ChannelPermission(string channelId, string userOrRoleId) => $"channels/{channelId}/permissions/{userOrRoleId}";
|
public static string ChannelPermission(long channelId, long userOrRoleId) => $"channels/{channelId}/permissions/{userOrRoleId}";
|
||||||
public static string ChannelTyping(string channelId) => $"channels/{channelId}/typing";
|
public static string ChannelTyping(long channelId) => $"channels/{channelId}/typing";
|
||||||
|
|
||||||
public const string Servers = "guilds";
|
public const string Servers = "guilds";
|
||||||
public static string Server(string serverId) => $"guilds/{serverId}";
|
public static string Server(long serverId) => $"guilds/{serverId}";
|
||||||
public static string ServerBan(string serverId, string userId) => $"guilds/{serverId}/bans/{userId}";
|
public static string ServerBan(long serverId, long userId) => $"guilds/{serverId}/bans/{userId}";
|
||||||
public static string ServerChannels(string serverId) => $"guilds/{serverId}/channels";
|
public static string ServerChannels(long serverId) => $"guilds/{serverId}/channels";
|
||||||
public static string ServerInvites(string serverId) => $"guilds/{serverId}/invites";
|
public static string ServerInvites(long serverId) => $"guilds/{serverId}/invites";
|
||||||
public static string ServerMember(string serverId, string userId) => $"guilds/{serverId}/members/{userId}";
|
public static string ServerMember(long serverId, long userId) => $"guilds/{serverId}/members/{userId}";
|
||||||
public static string ServerPrune(string serverId, int days) => $"guilds/{serverId}/prune?days={days}";
|
public static string ServerPrune(long serverId, int days) => $"guilds/{serverId}/prune?days={days}";
|
||||||
public static string ServerRoles(string serverId) => $"guilds/{serverId}/roles";
|
public static string ServerRoles(long serverId) => $"guilds/{serverId}/roles";
|
||||||
public static string ServerRole(string serverId, string roleId) => $"guilds/{serverId}/roles/{roleId}";
|
public static string ServerRole(long serverId, long roleId) => $"guilds/{serverId}/roles/{roleId}";
|
||||||
|
|
||||||
public const string Invites = "invite";
|
public const string Invites = "invite";
|
||||||
public static string Invite(string inviteId) => $"invite/{inviteId}";
|
public static string Invite(long inviteId) => $"invite/{inviteId}";
|
||||||
public static string InviteUrl(string inviteId) => $"https://discord.gg/{inviteId}";
|
public static string Invite(string inviteIdOrXkcd) => $"invite/{inviteIdOrXkcd}";
|
||||||
|
public static string InviteUrl(long inviteId) => $"https://discord.gg/{inviteId}";
|
||||||
|
public static string InviteUrl(string inviteIdOrXkcd) => $"https://discord.gg/{inviteIdOrXkcd}";
|
||||||
|
|
||||||
public const string Users = "users";
|
public const string Users = "users";
|
||||||
public static string UserAvatar(string userId, string avatarId) => $"users/{userId}/avatars/{avatarId}.jpg";
|
public static string UserAvatar(long userId, string avatarId) => $"users/{userId}/avatars/{avatarId}.jpg";
|
||||||
public static string UserChannels(string userId) => $"users/{userId}/channels";
|
public static string UserChannels(long userId) => $"users/{userId}/channels";
|
||||||
public static string UserMe => $"users/@me";
|
public static string UserMe => $"users/@me";
|
||||||
|
|
||||||
public const string Voice = "voice";
|
public const string Voice = "voice";
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@@ -17,7 +18,8 @@ namespace Discord.API
|
|||||||
public sealed class PageData
|
public sealed class PageData
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name;
|
public string Name;
|
||||||
[JsonProperty("url")]
|
[JsonProperty("url")]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -12,9 +13,11 @@ namespace Discord.API
|
|||||||
public class MemberReference
|
public class MemberReference
|
||||||
{
|
{
|
||||||
[JsonProperty("user_id")]
|
[JsonProperty("user_id")]
|
||||||
public string UserId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long UserId;
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string GuildId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long GuildId;
|
||||||
|
|
||||||
[JsonProperty("user")]
|
[JsonProperty("user")]
|
||||||
private UserReference _user;
|
private UserReference _user;
|
||||||
@@ -33,7 +36,8 @@ namespace Discord.API
|
|||||||
[JsonProperty("joined_at")]
|
[JsonProperty("joined_at")]
|
||||||
public DateTime? JoinedAt;
|
public DateTime? JoinedAt;
|
||||||
[JsonProperty("roles")]
|
[JsonProperty("roles")]
|
||||||
public string[] Roles;
|
[JsonConverter(typeof(LongArrayStringConverter))]
|
||||||
|
public long[] Roles;
|
||||||
}
|
}
|
||||||
public class ExtendedMemberInfo : MemberInfo
|
public class ExtendedMemberInfo : MemberInfo
|
||||||
{
|
{
|
||||||
@@ -49,12 +53,14 @@ namespace Discord.API
|
|||||||
[JsonProperty("status")]
|
[JsonProperty("status")]
|
||||||
public string Status;
|
public string Status;
|
||||||
[JsonProperty("roles")] //TODO: Might be temporary
|
[JsonProperty("roles")] //TODO: Might be temporary
|
||||||
public string[] Roles;
|
[JsonConverter(typeof(LongArrayStringConverter))]
|
||||||
|
public long[] Roles;
|
||||||
}
|
}
|
||||||
public class VoiceMemberInfo : MemberReference
|
public class VoiceMemberInfo : MemberReference
|
||||||
{
|
{
|
||||||
[JsonProperty("channel_id")]
|
[JsonProperty("channel_id")]
|
||||||
public string ChannelId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ChannelId;
|
||||||
[JsonProperty("session_id")]
|
[JsonProperty("session_id")]
|
||||||
public string SessionId;
|
public string SessionId;
|
||||||
[JsonProperty("token")]
|
[JsonProperty("token")]
|
||||||
@@ -79,7 +85,8 @@ namespace Discord.API
|
|||||||
[JsonProperty("deaf", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("deaf", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? Deaf;
|
public bool? Deaf;
|
||||||
[JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public IEnumerable<string> Roles;
|
[JsonConverter(typeof(EnumerableLongStringConverter))]
|
||||||
|
public IEnumerable<long> Roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PruneUsersResponse
|
public class PruneUsersResponse
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -12,11 +13,14 @@ namespace Discord.API
|
|||||||
public class MessageReference
|
public class MessageReference
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("channel_id")]
|
[JsonProperty("channel_id")]
|
||||||
public string ChannelId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ChannelId;
|
||||||
[JsonProperty("message_id")]
|
[JsonProperty("message_id")]
|
||||||
public string MessageId { get { return Id; } set { Id = value; } }
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long MessageId { get { return Id; } set { Id = value; } }
|
||||||
}
|
}
|
||||||
public class MessageInfo : MessageReference
|
public class MessageInfo : MessageReference
|
||||||
{
|
{
|
||||||
@@ -104,7 +108,8 @@ namespace Discord.API
|
|||||||
[JsonProperty("content")]
|
[JsonProperty("content")]
|
||||||
public string Content;
|
public string Content;
|
||||||
[JsonProperty("mentions")]
|
[JsonProperty("mentions")]
|
||||||
public IEnumerable<string> Mentions;
|
[JsonConverter(typeof(EnumerableLongStringConverter))]
|
||||||
|
public IEnumerable<long> Mentions;
|
||||||
[JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Nonce;
|
public string Nonce;
|
||||||
[JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
@@ -118,7 +123,8 @@ namespace Discord.API
|
|||||||
[JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Content;
|
public string Content;
|
||||||
[JsonProperty("mentions", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("mentions", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public IEnumerable<string> Mentions;
|
[JsonConverter(typeof(EnumerableLongStringConverter))]
|
||||||
|
public IEnumerable<long> Mentions;
|
||||||
}
|
}
|
||||||
public sealed class EditMessageResponse : MessageInfo { }
|
public sealed class EditMessageResponse : MessageInfo { }
|
||||||
|
|
||||||
@@ -132,7 +138,8 @@ namespace Discord.API
|
|||||||
public class Data
|
public class Data
|
||||||
{
|
{
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string ServerId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ServerId;
|
||||||
[JsonProperty("query")]
|
[JsonProperty("query")]
|
||||||
public string Query;
|
public string Query;
|
||||||
[JsonProperty("limit")]
|
[JsonProperty("limit")]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Discord.API
|
namespace Discord.API
|
||||||
@@ -10,7 +11,8 @@ namespace Discord.API
|
|||||||
internal sealed class SetChannelPermissionsRequest
|
internal sealed class SetChannelPermissionsRequest
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type;
|
public string Type;
|
||||||
[JsonProperty("allow")]
|
[JsonProperty("allow")]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Discord.API
|
namespace Discord.API
|
||||||
@@ -23,9 +24,11 @@ namespace Discord.API
|
|||||||
internal sealed class TypingStartEvent
|
internal sealed class TypingStartEvent
|
||||||
{
|
{
|
||||||
[JsonProperty("user_id")]
|
[JsonProperty("user_id")]
|
||||||
public string UserId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long UserId;
|
||||||
[JsonProperty("channel_id")]
|
[JsonProperty("channel_id")]
|
||||||
public string ChannelId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ChannelId;
|
||||||
[JsonProperty("timestamp")]
|
[JsonProperty("timestamp")]
|
||||||
public int Timestamp;
|
public int Timestamp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -12,12 +13,17 @@ namespace Discord.API
|
|||||||
public class RoleReference
|
public class RoleReference
|
||||||
{
|
{
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string GuildId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long GuildId;
|
||||||
[JsonProperty("role_id")]
|
[JsonProperty("role_id")]
|
||||||
public string RoleId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long RoleId;
|
||||||
}
|
}
|
||||||
public class RoleInfo
|
public class RoleInfo
|
||||||
{
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("permissions")]
|
[JsonProperty("permissions")]
|
||||||
public uint? Permissions;
|
public uint? Permissions;
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
@@ -28,8 +34,6 @@ namespace Discord.API
|
|||||||
public bool? Hoist;
|
public bool? Hoist;
|
||||||
[JsonProperty("color")]
|
[JsonProperty("color")]
|
||||||
public uint? Color;
|
public uint? Color;
|
||||||
[JsonProperty("id")]
|
|
||||||
public string Id;
|
|
||||||
[JsonProperty("managed")]
|
[JsonProperty("managed")]
|
||||||
public bool? Managed;
|
public bool? Managed;
|
||||||
}
|
}
|
||||||
@@ -57,7 +61,8 @@ namespace Discord.API
|
|||||||
public sealed class Role
|
public sealed class Role
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("position")]
|
[JsonProperty("position")]
|
||||||
public uint Position;
|
public uint Position;
|
||||||
}
|
}
|
||||||
@@ -72,14 +77,16 @@ namespace Discord.API
|
|||||||
internal sealed class RoleCreateEvent
|
internal sealed class RoleCreateEvent
|
||||||
{
|
{
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string GuildId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long GuildId;
|
||||||
[JsonProperty("role")]
|
[JsonProperty("role")]
|
||||||
public RoleInfo Data;
|
public RoleInfo Data;
|
||||||
}
|
}
|
||||||
internal sealed class RoleUpdateEvent
|
internal sealed class RoleUpdateEvent
|
||||||
{
|
{
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string GuildId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long GuildId;
|
||||||
[JsonProperty("role")]
|
[JsonProperty("role")]
|
||||||
public RoleInfo Data;
|
public RoleInfo Data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@@ -11,18 +12,21 @@ namespace Discord.API
|
|||||||
public class GuildReference
|
public class GuildReference
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name;
|
public string Name;
|
||||||
}
|
}
|
||||||
public class GuildInfo : GuildReference
|
public class GuildInfo : GuildReference
|
||||||
{
|
{
|
||||||
[JsonProperty("afk_channel_id")]
|
[JsonProperty("afk_channel_id")]
|
||||||
public string AFKChannelId;
|
[JsonConverter(typeof(NullableLongStringConverter))]
|
||||||
|
public long? AFKChannelId;
|
||||||
[JsonProperty("afk_timeout")]
|
[JsonProperty("afk_timeout")]
|
||||||
public int? AFKTimeout;
|
public int? AFKTimeout;
|
||||||
[JsonProperty("embed_channel_id")]
|
[JsonProperty("embed_channel_id")]
|
||||||
public string EmbedChannelId;
|
[JsonConverter(typeof(NullableLongStringConverter))]
|
||||||
|
public long? EmbedChannelId;
|
||||||
[JsonProperty("embed_enabled")]
|
[JsonProperty("embed_enabled")]
|
||||||
public bool EmbedEnabled;
|
public bool EmbedEnabled;
|
||||||
[JsonProperty("icon")]
|
[JsonProperty("icon")]
|
||||||
@@ -30,7 +34,8 @@ namespace Discord.API
|
|||||||
[JsonProperty("joined_at")]
|
[JsonProperty("joined_at")]
|
||||||
public DateTime? JoinedAt;
|
public DateTime? JoinedAt;
|
||||||
[JsonProperty("owner_id")]
|
[JsonProperty("owner_id")]
|
||||||
public string OwnerId;
|
[JsonConverter(typeof(NullableLongStringConverter))]
|
||||||
|
public long? OwnerId;
|
||||||
[JsonProperty("region")]
|
[JsonProperty("region")]
|
||||||
public string Region;
|
public string Region;
|
||||||
[JsonProperty("roles")]
|
[JsonProperty("roles")]
|
||||||
@@ -70,7 +75,8 @@ namespace Discord.API
|
|||||||
[JsonProperty("icon", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("icon", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Icon;
|
public string Icon;
|
||||||
[JsonProperty("afk_channel_id", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("afk_channel_id", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string AFKChannelId;
|
[JsonConverter(typeof(NullableLongStringConverter))]
|
||||||
|
public long? AFKChannelId;
|
||||||
[JsonProperty("afk_timeout", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("afk_timeout", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public int AFKTimeout;
|
public int AFKTimeout;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Discord.API
|
namespace Discord.API
|
||||||
@@ -12,9 +13,10 @@ namespace Discord.API
|
|||||||
[JsonProperty("username")]
|
[JsonProperty("username")]
|
||||||
public string Username;
|
public string Username;
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public string Id;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long Id;
|
||||||
[JsonProperty("discriminator")]
|
[JsonProperty("discriminator")]
|
||||||
public string Discriminator;
|
public short? Discriminator;
|
||||||
[JsonProperty("avatar")]
|
[JsonProperty("avatar")]
|
||||||
public string Avatar;
|
public string Avatar;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
#pragma warning disable CS0169
|
#pragma warning disable CS0169
|
||||||
|
|
||||||
|
using Discord.API.Converters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ namespace Discord.API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GetIceResponse
|
/*public class GetIceResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("ttl")]
|
[JsonProperty("ttl")]
|
||||||
public string TTL;
|
public string TTL;
|
||||||
@@ -38,7 +39,7 @@ namespace Discord.API
|
|||||||
[JsonProperty("credential")]
|
[JsonProperty("credential")]
|
||||||
public string Credential;
|
public string Credential;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//Commands
|
//Commands
|
||||||
internal sealed class JoinVoiceCommand : WebSocketMessage<JoinVoiceCommand.Data>
|
internal sealed class JoinVoiceCommand : WebSocketMessage<JoinVoiceCommand.Data>
|
||||||
@@ -47,9 +48,11 @@ namespace Discord.API
|
|||||||
public class Data
|
public class Data
|
||||||
{
|
{
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string ServerId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ServerId;
|
||||||
[JsonProperty("channel_id")]
|
[JsonProperty("channel_id")]
|
||||||
public string ChannelId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ChannelId;
|
||||||
[JsonProperty("self_mute")]
|
[JsonProperty("self_mute")]
|
||||||
public string SelfMute;
|
public string SelfMute;
|
||||||
[JsonProperty("self_deaf")]
|
[JsonProperty("self_deaf")]
|
||||||
@@ -61,7 +64,8 @@ namespace Discord.API
|
|||||||
internal sealed class VoiceServerUpdateEvent
|
internal sealed class VoiceServerUpdateEvent
|
||||||
{
|
{
|
||||||
[JsonProperty("guild_id")]
|
[JsonProperty("guild_id")]
|
||||||
public string GuildId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ServerId;
|
||||||
[JsonProperty("endpoint")]
|
[JsonProperty("endpoint")]
|
||||||
public string Endpoint;
|
public string Endpoint;
|
||||||
[JsonProperty("token")]
|
[JsonProperty("token")]
|
||||||
@@ -75,50 +79,52 @@ namespace Discord.API
|
|||||||
public class Data
|
public class Data
|
||||||
{
|
{
|
||||||
[JsonProperty("server_id")]
|
[JsonProperty("server_id")]
|
||||||
public string ServerId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long ServerId;
|
||||||
[JsonProperty("user_id")]
|
[JsonProperty("user_id")]
|
||||||
public string UserId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long UserId;
|
||||||
[JsonProperty("session_id")]
|
[JsonProperty("session_id")]
|
||||||
public string SessionId;
|
public string SessionId;
|
||||||
[JsonProperty("token")]
|
[JsonProperty("token")]
|
||||||
public string Token;
|
public string Token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal sealed class VoiceLogin2Command : WebSocketMessage<VoiceLogin2Command.Data>
|
internal sealed class VoiceLogin2Command : WebSocketMessage<VoiceLogin2Command.Data>
|
||||||
|
{
|
||||||
|
public VoiceLogin2Command() : base(1) { }
|
||||||
|
public class Data
|
||||||
{
|
{
|
||||||
public VoiceLogin2Command() : base(1) { }
|
public class SocketInfo
|
||||||
public class Data
|
|
||||||
{
|
{
|
||||||
public class SocketInfo
|
[JsonProperty("address")]
|
||||||
{
|
public string Address;
|
||||||
[JsonProperty("address")]
|
[JsonProperty("port")]
|
||||||
public string Address;
|
public int Port;
|
||||||
[JsonProperty("port")]
|
[JsonProperty("mode")]
|
||||||
public int Port;
|
public string Mode = "xsalsa20_poly1305";
|
||||||
[JsonProperty("mode")]
|
|
||||||
public string Mode = "xsalsa20_poly1305";
|
|
||||||
}
|
|
||||||
[JsonProperty("protocol")]
|
|
||||||
public string Protocol = "udp";
|
|
||||||
[JsonProperty("data")]
|
|
||||||
public SocketInfo SocketData = new SocketInfo();
|
|
||||||
}
|
}
|
||||||
|
[JsonProperty("protocol")]
|
||||||
|
public string Protocol = "udp";
|
||||||
|
[JsonProperty("data")]
|
||||||
|
public SocketInfo SocketData = new SocketInfo();
|
||||||
}
|
}
|
||||||
internal sealed class VoiceKeepAliveCommand : WebSocketMessage<object>
|
}
|
||||||
|
internal sealed class VoiceKeepAliveCommand : WebSocketMessage<object>
|
||||||
|
{
|
||||||
|
public VoiceKeepAliveCommand() : base(3, null) { }
|
||||||
|
}
|
||||||
|
internal sealed class IsTalkingCommand : WebSocketMessage<IsTalkingCommand.Data>
|
||||||
|
{
|
||||||
|
public IsTalkingCommand() : base(5) { }
|
||||||
|
public class Data
|
||||||
{
|
{
|
||||||
public VoiceKeepAliveCommand() : base(3, null) { }
|
[JsonProperty("delay")]
|
||||||
}
|
public int Delay;
|
||||||
internal sealed class IsTalkingCommand : WebSocketMessage<IsTalkingCommand.Data>
|
[JsonProperty("speaking")]
|
||||||
{
|
public bool IsSpeaking;
|
||||||
public IsTalkingCommand() : base(5) { }
|
|
||||||
public class Data
|
|
||||||
{
|
|
||||||
[JsonProperty("delay")]
|
|
||||||
public int Delay;
|
|
||||||
[JsonProperty("speaking")]
|
|
||||||
public bool IsSpeaking;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Events (Voice)
|
//Events (Voice)
|
||||||
public class VoiceReadyEvent
|
public class VoiceReadyEvent
|
||||||
@@ -144,7 +150,8 @@ namespace Discord.API
|
|||||||
public class IsTalkingEvent
|
public class IsTalkingEvent
|
||||||
{
|
{
|
||||||
[JsonProperty("user_id")]
|
[JsonProperty("user_id")]
|
||||||
public string UserId;
|
[JsonConverter(typeof(LongStringConverter))]
|
||||||
|
public long UserId;
|
||||||
[JsonProperty("ssrc")]
|
[JsonProperty("ssrc")]
|
||||||
public uint SSRC;
|
public uint SSRC;
|
||||||
[JsonProperty("speaking")]
|
[JsonProperty("speaking")]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Discord.Audio
|
|||||||
{
|
{
|
||||||
IDiscordVoiceBuffer OutputBuffer { get; }
|
IDiscordVoiceBuffer OutputBuffer { get; }
|
||||||
|
|
||||||
Task JoinChannel(string channelId);
|
Task JoinChannel(long channelId);
|
||||||
|
|
||||||
void SendVoicePCM(byte[] data, int count);
|
void SendVoicePCM(byte[] data, int count);
|
||||||
void ClearVoicePCM();
|
void ClearVoicePCM();
|
||||||
|
|||||||
@@ -52,39 +52,39 @@ namespace Discord
|
|||||||
=> _rest.Post(Endpoints.AuthLogout);
|
=> _rest.Post(Endpoints.AuthLogout);
|
||||||
|
|
||||||
//Channels
|
//Channels
|
||||||
public Task<CreateChannelResponse> CreateChannel(string serverId, string name, string channelType)
|
public Task<CreateChannelResponse> CreateChannel(long serverId, string name, string channelType)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||||
if (channelType == null) throw new ArgumentNullException(nameof(channelType));
|
if (channelType == null) throw new ArgumentNullException(nameof(channelType));
|
||||||
|
|
||||||
var request = new CreateChannelRequest { Name = name, Type = channelType };
|
var request = new CreateChannelRequest { Name = name, Type = channelType };
|
||||||
return _rest.Post<CreateChannelResponse>(Endpoints.ServerChannels(serverId), request);
|
return _rest.Post<CreateChannelResponse>(Endpoints.ServerChannels(serverId), request);
|
||||||
}
|
}
|
||||||
public Task<CreateChannelResponse> CreatePMChannel(string myId, string recipientId)
|
public Task<CreateChannelResponse> CreatePMChannel(long myId, long recipientId)
|
||||||
{
|
{
|
||||||
if (myId == null) throw new ArgumentNullException(nameof(myId));
|
if (myId <= 0) throw new ArgumentOutOfRangeException(nameof(myId));
|
||||||
if (recipientId == null) throw new ArgumentNullException(nameof(recipientId));
|
if (recipientId <= 0) throw new ArgumentOutOfRangeException(nameof(recipientId));
|
||||||
|
|
||||||
var request = new CreatePMChannelRequest { RecipientId = recipientId };
|
var request = new CreatePMChannelRequest { RecipientId = recipientId };
|
||||||
return _rest.Post<CreateChannelResponse>(Endpoints.UserChannels(myId), request);
|
return _rest.Post<CreateChannelResponse>(Endpoints.UserChannels(myId), request);
|
||||||
}
|
}
|
||||||
public Task<DestroyChannelResponse> DestroyChannel(string channelId)
|
public Task<DestroyChannelResponse> DestroyChannel(long channelId)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
return _rest.Delete<DestroyChannelResponse>(Endpoints.Channel(channelId));
|
return _rest.Delete<DestroyChannelResponse>(Endpoints.Channel(channelId));
|
||||||
}
|
}
|
||||||
public Task<EditChannelResponse> EditChannel(string channelId, string name = null, string topic = null)
|
public Task<EditChannelResponse> EditChannel(long channelId, string name = null, string topic = null)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
var request = new EditChannelRequest { Name = name, Topic = topic };
|
var request = new EditChannelRequest { Name = name, Topic = topic };
|
||||||
return _rest.Patch<EditChannelResponse>(Endpoints.Channel(channelId), request);
|
return _rest.Patch<EditChannelResponse>(Endpoints.Channel(channelId), request);
|
||||||
}
|
}
|
||||||
public Task ReorderChannels(string serverId, IEnumerable<string> channelIds, int startPos = 0)
|
public Task ReorderChannels(long serverId, IEnumerable<long> channelIds, int startPos = 0)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (channelIds == null) throw new ArgumentNullException(nameof(channelIds));
|
if (channelIds == null) throw new ArgumentNullException(nameof(channelIds));
|
||||||
if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer.");
|
if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer.");
|
||||||
|
|
||||||
@@ -93,12 +93,12 @@ namespace Discord
|
|||||||
var request = new ReorderChannelsRequest(channels);
|
var request = new ReorderChannelsRequest(channels);
|
||||||
return _rest.Patch(Endpoints.ServerChannels(serverId), request);
|
return _rest.Patch(Endpoints.ServerChannels(serverId), request);
|
||||||
}
|
}
|
||||||
public Task<GetMessagesResponse> GetMessages(string channelId, int count, string relativeMessageId = null, RelativeDirection relativeDir = RelativeDirection.Before)
|
public Task<GetMessagesResponse> GetMessages(long channelId, int count, long? relativeMessageId = null, RelativeDirection relativeDir = RelativeDirection.Before)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
if (relativeMessageId != null)
|
if (relativeMessageId != null)
|
||||||
return _rest.Get<GetMessagesResponse>(Endpoints.ChannelMessages(channelId, count, relativeMessageId, relativeDir == RelativeDirection.Before ? "before" : "after"));
|
return _rest.Get<GetMessagesResponse>(Endpoints.ChannelMessages(channelId, count, relativeMessageId.Value, relativeDir == RelativeDirection.Before ? "before" : "after"));
|
||||||
else
|
else
|
||||||
return _rest.Get<GetMessagesResponse>(Endpoints.ChannelMessages(channelId, count));
|
return _rest.Get<GetMessagesResponse>(Endpoints.ChannelMessages(channelId, count));
|
||||||
}
|
}
|
||||||
@@ -114,9 +114,9 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Invites
|
//Invites
|
||||||
public Task<CreateInviteResponse> CreateInvite(string channelId, int maxAge, int maxUses, bool tempMembership, bool hasXkcd)
|
public Task<CreateInviteResponse> CreateInvite(long channelId, int maxAge, int maxUses, bool tempMembership, bool hasXkcd)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
var request = new CreateInviteRequest { MaxAge = maxAge, MaxUses = maxUses, IsTemporary = tempMembership, WithXkcdPass = hasXkcd };
|
var request = new CreateInviteRequest { MaxAge = maxAge, MaxUses = maxUses, IsTemporary = tempMembership, WithXkcdPass = hasXkcd };
|
||||||
return _rest.Post<CreateInviteResponse>(Endpoints.ChannelInvites(channelId), request);
|
return _rest.Post<CreateInviteResponse>(Endpoints.ChannelInvites(channelId), request);
|
||||||
@@ -127,9 +127,9 @@ namespace Discord
|
|||||||
|
|
||||||
return _rest.Get<GetInviteResponse>(Endpoints.Invite(inviteIdOrXkcd));
|
return _rest.Get<GetInviteResponse>(Endpoints.Invite(inviteIdOrXkcd));
|
||||||
}
|
}
|
||||||
public Task<GetInvitesResponse> GetInvites(string serverId)
|
public Task<GetInvitesResponse> GetInvites(long serverId)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
|
|
||||||
return _rest.Get<GetInvitesResponse>(Endpoints.ServerInvites(serverId));
|
return _rest.Get<GetInvitesResponse>(Endpoints.ServerInvites(serverId));
|
||||||
}
|
}
|
||||||
@@ -147,38 +147,38 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Users
|
//Users
|
||||||
public Task EditUser(string serverId, string userId, bool? mute = null, bool? deaf = null, IEnumerable<string> roles = null)
|
public Task EditUser(long serverId, long userId, bool? mute = null, bool? deaf = null, IEnumerable<long> roleIds = null)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
|
|
||||||
var request = new EditMemberRequest { Mute = mute, Deaf = deaf, Roles = roles };
|
var request = new EditMemberRequest { Mute = mute, Deaf = deaf, Roles = roleIds };
|
||||||
return _rest.Patch(Endpoints.ServerMember(serverId, userId), request);
|
return _rest.Patch(Endpoints.ServerMember(serverId, userId), request);
|
||||||
}
|
}
|
||||||
public Task KickUser(string serverId, string userId)
|
public Task KickUser(long serverId, long userId)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
|
|
||||||
return _rest.Delete(Endpoints.ServerMember(serverId, userId));
|
return _rest.Delete(Endpoints.ServerMember(serverId, userId));
|
||||||
}
|
}
|
||||||
public Task BanUser(string serverId, string userId)
|
public Task BanUser(long serverId, long userId)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
|
|
||||||
return _rest.Put(Endpoints.ServerBan(serverId, userId));
|
return _rest.Put(Endpoints.ServerBan(serverId, userId));
|
||||||
}
|
}
|
||||||
public Task UnbanUser(string serverId, string userId)
|
public Task UnbanUser(long serverId, long userId)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
|
|
||||||
return _rest.Delete(Endpoints.ServerBan(serverId, userId));
|
return _rest.Delete(Endpoints.ServerBan(serverId, userId));
|
||||||
}
|
}
|
||||||
public Task<PruneUsersResponse> PruneUsers(string serverId, int days, bool simulate)
|
public Task<PruneUsersResponse> PruneUsers(long serverId, int days, bool simulate)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days));
|
if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days));
|
||||||
|
|
||||||
if (simulate)
|
if (simulate)
|
||||||
@@ -188,93 +188,93 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Messages
|
//Messages
|
||||||
public Task<SendMessageResponse> SendMessage(string channelId, string message, IEnumerable<string> mentionedUserIds = null, string nonce = null, bool isTTS = false)
|
public Task<SendMessageResponse> SendMessage(long channelId, string message, IEnumerable<long> mentionedUserIds = null, string nonce = null, bool isTTS = false)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||||
|
|
||||||
var request = new SendMessageRequest { Content = message, Mentions = mentionedUserIds ?? new string[0], Nonce = nonce, IsTTS = isTTS ? true : false };
|
var request = new SendMessageRequest { Content = message, Mentions = mentionedUserIds ?? new long[0], Nonce = nonce, IsTTS = isTTS ? true : false };
|
||||||
return _rest.Post<SendMessageResponse>(Endpoints.ChannelMessages(channelId), request);
|
return _rest.Post<SendMessageResponse>(Endpoints.ChannelMessages(channelId), request);
|
||||||
}
|
}
|
||||||
public Task<SendMessageResponse> SendFile(string channelId, string filePath)
|
public Task<SendMessageResponse> SendFile(long channelId, string filePath)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
if (filePath == null) throw new ArgumentNullException(nameof(filePath));
|
if (filePath == null) throw new ArgumentNullException(nameof(filePath));
|
||||||
|
|
||||||
return _rest.PostFile<SendMessageResponse>(Endpoints.ChannelMessages(channelId), filePath);
|
return _rest.PostFile<SendMessageResponse>(Endpoints.ChannelMessages(channelId), filePath);
|
||||||
}
|
}
|
||||||
public Task DeleteMessage(string messageId, string channelId)
|
public Task DeleteMessage(long messageId, long channelId)
|
||||||
{
|
{
|
||||||
if (messageId == null) throw new ArgumentNullException(nameof(messageId));
|
if (messageId <= 0) throw new ArgumentOutOfRangeException(nameof(messageId));
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
return _rest.Delete(Endpoints.ChannelMessage(channelId, messageId));
|
return _rest.Delete(Endpoints.ChannelMessage(channelId, messageId));
|
||||||
}
|
}
|
||||||
public Task<EditMessageResponse> EditMessage(string messageId, string channelId, string message = null, IEnumerable<string> mentionedUserIds = null)
|
public Task<EditMessageResponse> EditMessage(long messageId, long channelId, string message = null, IEnumerable<long> mentionedUserIds = null)
|
||||||
{
|
{
|
||||||
if (messageId == null) throw new ArgumentNullException(nameof(messageId));
|
if (messageId <= 0) throw new ArgumentOutOfRangeException(nameof(messageId));
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
var request = new EditMessageRequest { Content = message, Mentions = mentionedUserIds };
|
var request = new EditMessageRequest { Content = message, Mentions = mentionedUserIds };
|
||||||
return _rest.Patch<EditMessageResponse>(Endpoints.ChannelMessage(channelId, messageId), request);
|
return _rest.Patch<EditMessageResponse>(Endpoints.ChannelMessage(channelId, messageId), request);
|
||||||
}
|
}
|
||||||
public Task AckMessage(string messageId, string channelId)
|
public Task AckMessage(long messageId, long channelId)
|
||||||
{
|
{
|
||||||
if (messageId == null) throw new ArgumentNullException(nameof(messageId));
|
if (messageId <= 0) throw new ArgumentOutOfRangeException(nameof(messageId));
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
return _rest.Post(Endpoints.ChannelMessageAck(channelId, messageId));
|
return _rest.Post(Endpoints.ChannelMessageAck(channelId, messageId));
|
||||||
}
|
}
|
||||||
public Task SendIsTyping(string channelId)
|
public Task SendIsTyping(long channelId)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
return _rest.Post(Endpoints.ChannelTyping(channelId));
|
return _rest.Post(Endpoints.ChannelTyping(channelId));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Permissions
|
//Permissions
|
||||||
public Task SetChannelPermissions(string channelId, string userOrRoleId, string idType, uint allow = 0, uint deny = 0)
|
public Task SetChannelPermissions(long channelId, long userOrRoleId, string idType, uint allow = 0, uint deny = 0)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
if (userOrRoleId == null) throw new ArgumentNullException(nameof(userOrRoleId));
|
if (userOrRoleId <= 0) throw new ArgumentOutOfRangeException(nameof(userOrRoleId));
|
||||||
if (idType == null) throw new ArgumentNullException(nameof(idType));
|
if (idType == null) throw new ArgumentNullException(nameof(idType));
|
||||||
|
|
||||||
var request = new SetChannelPermissionsRequest { Id = userOrRoleId, Type = idType, Allow = allow, Deny = deny };
|
var request = new SetChannelPermissionsRequest { Id = userOrRoleId, Type = idType, Allow = allow, Deny = deny };
|
||||||
return _rest.Put(Endpoints.ChannelPermission(channelId, userOrRoleId), request);
|
return _rest.Put(Endpoints.ChannelPermission(channelId, userOrRoleId), request);
|
||||||
}
|
}
|
||||||
public Task DeleteChannelPermissions(string channelId, string userOrRoleId)
|
public Task DeleteChannelPermissions(long channelId, long userOrRoleId)
|
||||||
{
|
{
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
if (userOrRoleId == null) throw new ArgumentNullException(nameof(userOrRoleId));
|
if (userOrRoleId <= 0) throw new ArgumentOutOfRangeException(nameof(userOrRoleId));
|
||||||
|
|
||||||
return _rest.Delete(Endpoints.ChannelPermission(channelId, userOrRoleId), null);
|
return _rest.Delete(Endpoints.ChannelPermission(channelId, userOrRoleId), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Roles
|
//Roles
|
||||||
public Task<RoleInfo> CreateRole(string serverId)
|
public Task<RoleInfo> CreateRole(long serverId)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
|
|
||||||
return _rest.Post<RoleInfo>(Endpoints.ServerRoles(serverId));
|
return _rest.Post<RoleInfo>(Endpoints.ServerRoles(serverId));
|
||||||
}
|
}
|
||||||
public Task DeleteRole(string serverId, string roleId)
|
public Task DeleteRole(long serverId, long roleId)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (roleId == null) throw new ArgumentNullException(nameof(roleId));
|
if (roleId <= 0) throw new ArgumentOutOfRangeException(nameof(roleId));
|
||||||
|
|
||||||
return _rest.Delete(Endpoints.ServerRole(serverId, roleId));
|
return _rest.Delete(Endpoints.ServerRole(serverId, roleId));
|
||||||
}
|
}
|
||||||
public Task<RoleInfo> EditRole(string serverId, string roleId, string name = null, uint? permissions = null, uint? color = null, bool? hoist = null)
|
public Task<RoleInfo> EditRole(long serverId, long roleId, string name = null, uint? permissions = null, uint? color = null, bool? hoist = null)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (roleId == null) throw new ArgumentNullException(nameof(roleId));
|
if (roleId <= 0) throw new ArgumentOutOfRangeException(nameof(roleId));
|
||||||
|
|
||||||
var request = new EditRoleRequest { Name = name, Permissions = permissions, Hoist = hoist, Color = color };
|
var request = new EditRoleRequest { Name = name, Permissions = permissions, Hoist = hoist, Color = color };
|
||||||
return _rest.Patch<RoleInfo>(Endpoints.ServerRole(serverId, roleId), request);
|
return _rest.Patch<RoleInfo>(Endpoints.ServerRole(serverId, roleId), request);
|
||||||
}
|
}
|
||||||
public Task ReorderRoles(string serverId, IEnumerable<string> roleIds, int startPos = 0)
|
public Task ReorderRoles(long serverId, IEnumerable<long> roleIds, int startPos = 0)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
if (roleIds == null) throw new ArgumentNullException(nameof(roleIds));
|
if (roleIds == null) throw new ArgumentNullException(nameof(roleIds));
|
||||||
if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer.");
|
if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer.");
|
||||||
|
|
||||||
@@ -293,15 +293,15 @@ namespace Discord
|
|||||||
var request = new CreateServerRequest { Name = name, Region = region };
|
var request = new CreateServerRequest { Name = name, Region = region };
|
||||||
return _rest.Post<CreateServerResponse>(Endpoints.Servers, request);
|
return _rest.Post<CreateServerResponse>(Endpoints.Servers, request);
|
||||||
}
|
}
|
||||||
public Task LeaveServer(string serverId)
|
public Task LeaveServer(long serverId)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
|
|
||||||
return _rest.Delete<DeleteServerResponse>(Endpoints.Server(serverId));
|
return _rest.Delete<DeleteServerResponse>(Endpoints.Server(serverId));
|
||||||
}
|
}
|
||||||
public Task<EditServerResponse> EditServer(string serverId, string name = null, string region = null, ImageType iconType = ImageType.Png, byte[] icon = null)
|
public Task<EditServerResponse> EditServer(long serverId, string name = null, string region = null, ImageType iconType = ImageType.Png, byte[] icon = null)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId));
|
||||||
|
|
||||||
var request = new EditServerRequest { Name = name, Region = region, Icon = Base64Picture(iconType, icon) };
|
var request = new EditServerRequest { Name = name, Region = region, Icon = Base64Picture(iconType, icon) };
|
||||||
return _rest.Patch<EditServerResponse>(Endpoints.Server(serverId), request);
|
return _rest.Patch<EditServerResponse>(Endpoints.Server(serverId), request);
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
public class BanEventArgs : EventArgs
|
public class BanEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public string UserId { get; }
|
public long UserId { get; }
|
||||||
public Server Server { get; }
|
public Server Server { get; }
|
||||||
|
|
||||||
public BanEventArgs(string userId, Server server)
|
public BanEventArgs(long userId, Server server)
|
||||||
{
|
{
|
||||||
UserId = userId;
|
UserId = userId;
|
||||||
Server = server;
|
Server = server;
|
||||||
@@ -19,13 +19,13 @@ namespace Discord
|
|||||||
public partial class DiscordClient
|
public partial class DiscordClient
|
||||||
{
|
{
|
||||||
public event EventHandler<BanEventArgs> UserBanned;
|
public event EventHandler<BanEventArgs> UserBanned;
|
||||||
private void RaiseUserBanned(string userId, Server server)
|
private void RaiseUserBanned(long userId, Server server)
|
||||||
{
|
{
|
||||||
if (UserBanned != null)
|
if (UserBanned != null)
|
||||||
RaiseEvent(nameof(UserBanned), () => UserBanned(this, new BanEventArgs(userId, server)));
|
RaiseEvent(nameof(UserBanned), () => UserBanned(this, new BanEventArgs(userId, server)));
|
||||||
}
|
}
|
||||||
public event EventHandler<BanEventArgs> UserUnbanned;
|
public event EventHandler<BanEventArgs> UserUnbanned;
|
||||||
private void RaiseUserUnbanned(string userId, Server server)
|
private void RaiseUserUnbanned(long userId, Server server)
|
||||||
{
|
{
|
||||||
if (UserUnbanned != null)
|
if (UserUnbanned != null)
|
||||||
RaiseEvent(nameof(UserUnbanned), () => UserUnbanned(this, new BanEventArgs(userId, server)));
|
RaiseEvent(nameof(UserUnbanned), () => UserUnbanned(this, new BanEventArgs(userId, server)));
|
||||||
@@ -42,10 +42,10 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Unbans a user from the provided server. </summary>
|
/// <summary> Unbans a user from the provided server. </summary>
|
||||||
public async Task Unban(Server server, string userId)
|
public async Task Unban(Server server, long userId)
|
||||||
{
|
{
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
try { await _api.UnbanUser(server.Id, userId).ConfigureAwait(false); }
|
try { await _api.UnbanUser(server.Id, userId).ConfigureAwait(false); }
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal sealed class Channels : AsyncCollection<Channel>
|
internal sealed class Channels : AsyncCollection<long, Channel>
|
||||||
{
|
{
|
||||||
public IEnumerable<Channel> PrivateChannels => _privateChannels.Select(x => x.Value);
|
public IEnumerable<Channel> PrivateChannels => _privateChannels.Select(x => x.Value);
|
||||||
private ConcurrentDictionary<string, Channel> _privateChannels;
|
private ConcurrentDictionary<long, Channel> _privateChannels;
|
||||||
|
|
||||||
public Channels(DiscordClient client, object writerLock)
|
public Channels(DiscordClient client, object writerLock)
|
||||||
: base(client, writerLock)
|
: base(client, writerLock)
|
||||||
{
|
{
|
||||||
_privateChannels = new ConcurrentDictionary<string, Channel>();
|
_privateChannels = new ConcurrentDictionary<long, Channel>();
|
||||||
ItemCreated += (s, e) =>
|
ItemCreated += (s, e) =>
|
||||||
{
|
{
|
||||||
if (e.Item.IsPrivate)
|
if (e.Item.IsPrivate)
|
||||||
@@ -31,8 +31,8 @@ namespace Discord
|
|||||||
};
|
};
|
||||||
Cleared += (s, e) => _privateChannels.Clear();
|
Cleared += (s, e) => _privateChannels.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Channel GetOrAdd(string id, string serverId, string recipientId = null)
|
public Channel GetOrAdd(long id, long? serverId, long? recipientId = null)
|
||||||
=> GetOrAdd(id, () => new Channel(_client, id, serverId, recipientId));
|
=> GetOrAdd(id, () => new Channel(_client, id, serverId, recipientId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +71,9 @@ namespace Discord
|
|||||||
private readonly Channels _channels;
|
private readonly Channels _channels;
|
||||||
|
|
||||||
/// <summary> Returns the channel with the specified id, or null if none was found. </summary>
|
/// <summary> Returns the channel with the specified id, or null if none was found. </summary>
|
||||||
public Channel GetChannel(string id)
|
public Channel GetChannel(long id)
|
||||||
{
|
{
|
||||||
if (id == null) throw new ArgumentNullException(nameof(id));
|
if (id <= 0) throw new ArgumentOutOfRangeException(nameof(id));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return _channels[id];
|
return _channels[id];
|
||||||
@@ -93,7 +93,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (name[0] == '<' && name[1] == '#' && name[name.Length - 1] == '>') //Parse mention
|
if (name[0] == '<' && name[1] == '#' && name[name.Length - 1] == '>') //Parse mention
|
||||||
{
|
{
|
||||||
string id = name.Substring(2, name.Length - 3);
|
long id = IdConvert.ToLong(name.Substring(2, name.Length - 3));
|
||||||
var channel = _channels[id];
|
var channel = _channels[id];
|
||||||
if (channel != null)
|
if (channel != null)
|
||||||
query = query.Concat(new Channel[] { channel });
|
query = query.Concat(new Channel[] { channel });
|
||||||
@@ -135,10 +135,10 @@ namespace Discord
|
|||||||
channel = user.GlobalUser.PrivateChannel;
|
channel = user.GlobalUser.PrivateChannel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
{
|
{
|
||||||
var response = await _api.CreatePMChannel(_userId, user.Id).ConfigureAwait(false);
|
var response = await _api.CreatePMChannel(_userId.Value, user.Id).ConfigureAwait(false);
|
||||||
var recipient = _users.GetOrAdd(response.Recipient?.Id, null);
|
var recipient = _users.GetOrAdd(response.Recipient.Id, null);
|
||||||
recipient.Update(response.Recipient);
|
recipient.Update(response.Recipient);
|
||||||
channel = _channels.GetOrAdd(response.Id, response.GuildId, response.Recipient?.Id);
|
channel = _channels.GetOrAdd(response.Id, response.GuildId, response.Recipient.Id);
|
||||||
channel.Update(response);
|
channel.Update(response);
|
||||||
}
|
}
|
||||||
return channel;
|
return channel;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Discord
|
|||||||
inviteIdOrXkcd = inviteIdOrXkcd.Substring(index + 1);
|
inviteIdOrXkcd = inviteIdOrXkcd.Substring(index + 1);
|
||||||
|
|
||||||
var response = await _api.GetInvite(inviteIdOrXkcd).ConfigureAwait(false);
|
var response = await _api.GetInvite(inviteIdOrXkcd).ConfigureAwait(false);
|
||||||
var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id, response.Inviter?.Id, response.Channel?.Id);
|
var invite = new Invite(this, response.Code, response.XkcdPass);
|
||||||
invite.Cache(); //Builds references
|
invite.Cache(); //Builds references
|
||||||
invite.Update(response);
|
invite.Update(response);
|
||||||
return invite;
|
return invite;
|
||||||
@@ -38,7 +38,7 @@ namespace Discord
|
|||||||
var response = await _api.GetInvites(server.Id).ConfigureAwait(false);
|
var response = await _api.GetInvites(server.Id).ConfigureAwait(false);
|
||||||
return response.Select(x =>
|
return response.Select(x =>
|
||||||
{
|
{
|
||||||
var invite = new Invite(this, x.Code, x.XkcdPass, x.Guild.Id, x.Inviter?.Id, x.Channel?.Id);
|
var invite = new Invite(this, x.Code, x.XkcdPass);
|
||||||
invite.Cache(); //Builds references
|
invite.Cache(); //Builds references
|
||||||
invite.Update(x);
|
invite.Update(x);
|
||||||
return invite;
|
return invite;
|
||||||
@@ -71,7 +71,7 @@ namespace Discord
|
|||||||
|
|
||||||
var response = await _api.CreateInvite(channel.Id, maxAge: maxAge, maxUses: maxUses,
|
var response = await _api.CreateInvite(channel.Id, maxAge: maxAge, maxUses: maxUses,
|
||||||
tempMembership: tempMembership, hasXkcd: hasXkcd).ConfigureAwait(false);
|
tempMembership: tempMembership, hasXkcd: hasXkcd).ConfigureAwait(false);
|
||||||
var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id, response.Inviter?.Id, response.Channel?.Id);
|
var invite = new Invite(this, response.Code, response.XkcdPass);
|
||||||
invite.Cache(); //Builds references
|
invite.Cache(); //Builds references
|
||||||
return invite;
|
return invite;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Discord.API;
|
using Discord.API;
|
||||||
using Discord.Net;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -8,7 +7,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal sealed class Messages : AsyncCollection<Message>
|
internal sealed class Messages : AsyncCollection<long, Message>
|
||||||
{
|
{
|
||||||
private bool _isEnabled;
|
private bool _isEnabled;
|
||||||
|
|
||||||
@@ -17,8 +16,8 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
_isEnabled = isEnabled;
|
_isEnabled = isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message GetOrAdd(string id, string channelId, string userId)
|
public Message GetOrAdd(long id, long channelId, long userId)
|
||||||
{
|
{
|
||||||
if (_isEnabled)
|
if (_isEnabled)
|
||||||
return GetOrAdd(id, () => new Message(_client, id, channelId, userId));
|
return GetOrAdd(id, () => new Message(_client, id, channelId, userId));
|
||||||
@@ -80,9 +79,9 @@ namespace Discord
|
|||||||
private readonly Messages _messages;
|
private readonly Messages _messages;
|
||||||
|
|
||||||
/// <summary> Returns the message with the specified id, or null if none was found. </summary>
|
/// <summary> Returns the message with the specified id, or null if none was found. </summary>
|
||||||
public Message GetMessage(string id)
|
public Message GetMessage(long id)
|
||||||
{
|
{
|
||||||
if (id == null) throw new ArgumentNullException(nameof(id));
|
if (id <= 0) throw new ArgumentOutOfRangeException(nameof(id));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return _messages[id];
|
return _messages[id];
|
||||||
@@ -124,17 +123,16 @@ namespace Discord
|
|||||||
if (Config.UseMessageQueue)
|
if (Config.UseMessageQueue)
|
||||||
{
|
{
|
||||||
var nonce = GenerateNonce();
|
var nonce = GenerateNonce();
|
||||||
msg = _messages.GetOrAdd("nonce_" + nonce, channel.Id, _userId);
|
msg = _messages.GetOrAdd(nonce, channel.Id, _userId.Value);
|
||||||
var currentUser = msg.User;
|
var currentUser = msg.User;
|
||||||
msg.Update(new MessageInfo
|
msg.Update(new MessageInfo
|
||||||
{
|
{
|
||||||
Content = text,
|
Content = text,
|
||||||
Timestamp = DateTime.UtcNow,
|
Timestamp = DateTime.UtcNow,
|
||||||
Author = new UserReference { Avatar = currentUser.AvatarId, Discriminator = currentUser.Discriminator, Id = _userId, Username = currentUser.Name },
|
Author = new UserReference { Avatar = currentUser.AvatarId, Discriminator = currentUser.Discriminator, Id = _userId.Value, Username = currentUser.Name },
|
||||||
ChannelId = channel.Id,
|
ChannelId = channel.Id,
|
||||||
IsTextToSpeech = isTextToSpeech
|
IsTextToSpeech = isTextToSpeech
|
||||||
});
|
});
|
||||||
msg.Nonce = nonce;
|
|
||||||
msg.IsQueued = true;
|
msg.IsQueued = true;
|
||||||
|
|
||||||
if (text.Length > MaxMessageSize)
|
if (text.Length > MaxMessageSize)
|
||||||
@@ -217,7 +215,7 @@ namespace Discord
|
|||||||
|
|
||||||
|
|
||||||
/// <summary> Downloads last count messages from the server, returning all messages before or after relativeMessageId, if it's provided. </summary>
|
/// <summary> Downloads last count messages from the server, returning all messages before or after relativeMessageId, if it's provided. </summary>
|
||||||
public async Task<Message[]> DownloadMessages(Channel channel, int count, string relativeMessageId = null, RelativeDirection relativeDir = RelativeDirection.Before, bool useCache = true)
|
public async Task<Message[]> DownloadMessages(Channel channel, int count, long? relativeMessageId = null, RelativeDirection relativeDir = RelativeDirection.Before, bool useCache = true)
|
||||||
{
|
{
|
||||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||||
if (count < 0) throw new ArgumentNullException(nameof(count));
|
if (count < 0) throw new ArgumentNullException(nameof(count));
|
||||||
@@ -274,7 +272,7 @@ namespace Discord
|
|||||||
SendMessageResponse response = null;
|
SendMessageResponse response = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = await _api.SendMessage(msg.Channel.Id, msg.RawText, msg.MentionedUsers.Select(x => x.Id), msg.Nonce, msg.IsTTS).ConfigureAwait(false);
|
response = await _api.SendMessage(msg.Channel.Id, msg.RawText, msg.MentionedUsers.Select(x => x.Id), IdConvert.ToString(msg.Id), msg.IsTTS).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (WebException) { break; }
|
catch (WebException) { break; }
|
||||||
catch (HttpException) { hasFailed = true; }
|
catch (HttpException) { hasFailed = true; }
|
||||||
@@ -293,10 +291,10 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private string GenerateNonce()
|
private long GenerateNonce()
|
||||||
{
|
{
|
||||||
lock (_rand)
|
lock (_rand)
|
||||||
return _rand.Next().ToString();
|
return -_rand.Next(1, int.MaxValue - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ namespace Discord
|
|||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return SetChannelPermissions(channel, user?.Id, PermissionTarget.User, allow, deny);
|
return SetChannelPermissions(channel, user.Id, PermissionTarget.User, allow, deny);
|
||||||
}
|
}
|
||||||
public Task SetChannelPermissions(Channel channel, User user, DualChannelPermissions permissions = null)
|
public Task SetChannelPermissions(Channel channel, User user, DualChannelPermissions permissions = null)
|
||||||
{
|
{
|
||||||
@@ -44,7 +44,7 @@ namespace Discord
|
|||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return SetChannelPermissions(channel, user?.Id, PermissionTarget.User, permissions?.Allow, permissions?.Deny);
|
return SetChannelPermissions(channel, user.Id, PermissionTarget.User, permissions?.Allow, permissions?.Deny);
|
||||||
}
|
}
|
||||||
public Task SetChannelPermissions(Channel channel, Role role, ChannelPermissions allow = null, ChannelPermissions deny = null)
|
public Task SetChannelPermissions(Channel channel, Role role, ChannelPermissions allow = null, ChannelPermissions deny = null)
|
||||||
{
|
{
|
||||||
@@ -52,7 +52,7 @@ namespace Discord
|
|||||||
if (role == null) throw new ArgumentNullException(nameof(role));
|
if (role == null) throw new ArgumentNullException(nameof(role));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return SetChannelPermissions(channel, role?.Id, PermissionTarget.Role, allow, deny);
|
return SetChannelPermissions(channel, role.Id, PermissionTarget.Role, allow, deny);
|
||||||
}
|
}
|
||||||
public Task SetChannelPermissions(Channel channel, Role role, DualChannelPermissions permissions = null)
|
public Task SetChannelPermissions(Channel channel, Role role, DualChannelPermissions permissions = null)
|
||||||
{
|
{
|
||||||
@@ -60,9 +60,9 @@ namespace Discord
|
|||||||
if (role == null) throw new ArgumentNullException(nameof(role));
|
if (role == null) throw new ArgumentNullException(nameof(role));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return SetChannelPermissions(channel, role?.Id, PermissionTarget.Role, permissions?.Allow, permissions?.Deny);
|
return SetChannelPermissions(channel, role.Id, PermissionTarget.Role, permissions?.Allow, permissions?.Deny);
|
||||||
}
|
}
|
||||||
private Task SetChannelPermissions(Channel channel, string targetId, PermissionTarget targetType, ChannelPermissions allow = null, ChannelPermissions deny = null)
|
private Task SetChannelPermissions(Channel channel, long targetId, PermissionTarget targetType, ChannelPermissions allow = null, ChannelPermissions deny = null)
|
||||||
=> _api.SetChannelPermissions(channel.Id, targetId, targetType.Value, allow?.RawValue ?? 0, deny?.RawValue ?? 0);
|
=> _api.SetChannelPermissions(channel.Id, targetId, targetType.Value, allow?.RawValue ?? 0, deny?.RawValue ?? 0);
|
||||||
|
|
||||||
public Task RemoveChannelPermissions(Channel channel, User user)
|
public Task RemoveChannelPermissions(Channel channel, User user)
|
||||||
@@ -71,7 +71,7 @@ namespace Discord
|
|||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return RemoveChannelPermissions(channel, user?.Id, PermissionTarget.User);
|
return RemoveChannelPermissions(channel, user.Id, PermissionTarget.User);
|
||||||
}
|
}
|
||||||
public Task RemoveChannelPermissions(Channel channel, Role role)
|
public Task RemoveChannelPermissions(Channel channel, Role role)
|
||||||
{
|
{
|
||||||
@@ -79,9 +79,9 @@ namespace Discord
|
|||||||
if (role == null) throw new ArgumentNullException(nameof(role));
|
if (role == null) throw new ArgumentNullException(nameof(role));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return RemoveChannelPermissions(channel, role?.Id, PermissionTarget.Role);
|
return RemoveChannelPermissions(channel, role.Id, PermissionTarget.Role);
|
||||||
}
|
}
|
||||||
private async Task RemoveChannelPermissions(Channel channel, string userOrRoleId, PermissionTarget targetType)
|
private async Task RemoveChannelPermissions(Channel channel, long userOrRoleId, PermissionTarget targetType)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal sealed class Roles : AsyncCollection<Role>
|
internal sealed class Roles : AsyncCollection<long, Role>
|
||||||
{
|
{
|
||||||
public Roles(DiscordClient client, object writerLock)
|
public Roles(DiscordClient client, object writerLock)
|
||||||
: base(client, writerLock) { }
|
: base(client, writerLock) { }
|
||||||
|
|
||||||
public Role GetOrAdd(string id, string serverId)
|
public Role GetOrAdd(long id, long serverId)
|
||||||
=> GetOrAdd(id, () => new Role(_client, id, serverId));
|
=> GetOrAdd(id, () => new Role(_client, id, serverId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,9 +48,9 @@ namespace Discord
|
|||||||
private readonly Roles _roles;
|
private readonly Roles _roles;
|
||||||
|
|
||||||
/// <summary> Returns the role with the specified id, or null if none was found. </summary>
|
/// <summary> Returns the role with the specified id, or null if none was found. </summary>
|
||||||
public Role GetRole(string id)
|
public Role GetRole(long id)
|
||||||
{
|
{
|
||||||
if (id == null) throw new ArgumentNullException(nameof(id));
|
if (id <= 0) throw new ArgumentOutOfRangeException(nameof(id));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return _roles[id];
|
return _roles[id];
|
||||||
|
|||||||
@@ -6,19 +6,18 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal sealed class Servers : AsyncCollection<Server>
|
internal sealed class Servers : AsyncCollection<long, Server>
|
||||||
{
|
{
|
||||||
public Servers(DiscordClient client, object writerLock)
|
public Servers(DiscordClient client, object writerLock)
|
||||||
: base(client, writerLock) { }
|
: base(client, writerLock) { }
|
||||||
|
|
||||||
public Server GetOrAdd(string id)
|
public Server GetOrAdd(long id)
|
||||||
=> GetOrAdd(id, () => new Server(_client, id));
|
=> GetOrAdd(id, () => new Server(_client, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ServerEventArgs : EventArgs
|
public class ServerEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public Server Server { get; }
|
public Server Server { get; }
|
||||||
public string ServerId => Server.Id;
|
|
||||||
|
|
||||||
public ServerEventArgs(Server server) { Server = server; }
|
public ServerEventArgs(Server server) { Server = server; }
|
||||||
}
|
}
|
||||||
@@ -62,9 +61,9 @@ namespace Discord
|
|||||||
private readonly Servers _servers;
|
private readonly Servers _servers;
|
||||||
|
|
||||||
/// <summary> Returns the server with the specified id, or null if none was found. </summary>
|
/// <summary> Returns the server with the specified id, or null if none was found. </summary>
|
||||||
public Server GetServer(string id)
|
public Server GetServer(long id)
|
||||||
{
|
{
|
||||||
if (id == null) throw new ArgumentNullException(nameof(id));
|
if (id <= 0) throw new ArgumentOutOfRangeException(nameof(id));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return _servers[id];
|
return _servers[id];
|
||||||
|
|||||||
@@ -5,27 +5,25 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal sealed class GlobalUsers : AsyncCollection<GlobalUser>
|
internal sealed class GlobalUsers : AsyncCollection<long, GlobalUser>
|
||||||
{
|
{
|
||||||
public GlobalUsers(DiscordClient client, object writerLock)
|
public GlobalUsers(DiscordClient client, object writerLock)
|
||||||
: base(client, writerLock) { }
|
: base(client, writerLock) { }
|
||||||
|
|
||||||
public GlobalUser GetOrAdd(string id) => GetOrAdd(id, () => new GlobalUser(_client, id));
|
public GlobalUser GetOrAdd(long id) => GetOrAdd(id, () => new GlobalUser(_client, id));
|
||||||
}
|
}
|
||||||
internal sealed class Users : AsyncCollection<User>
|
internal sealed class Users : AsyncCollection<User.CompositeKey, User>
|
||||||
{
|
{
|
||||||
public Users(DiscordClient client, object writerLock)
|
public Users(DiscordClient client, object writerLock)
|
||||||
: base(client, writerLock)
|
: base(client, writerLock)
|
||||||
{ }
|
{ }
|
||||||
private string GetKey(string userId, string serverId)
|
|
||||||
=> User.GetId(userId, serverId);
|
|
||||||
|
|
||||||
public User this[string userId, string serverId]
|
public User this[long userId, long? serverId]
|
||||||
=> this[GetKey(userId, serverId)];
|
=> base[new User.CompositeKey(userId, serverId)];
|
||||||
public User GetOrAdd(string userId, string serverId)
|
public User GetOrAdd(long userId, long? serverId)
|
||||||
=> GetOrAdd(GetKey(userId, serverId), () => new User(_client, userId, serverId));
|
=> GetOrAdd(new User.CompositeKey(userId, serverId), () => new User(_client, userId, serverId));
|
||||||
public User TryRemove(string userId, string serverId)
|
public User TryRemove(long userId, long? serverId)
|
||||||
=> TryRemove(GetKey(userId, serverId));
|
=> TryRemove(new User.CompositeKey(userId, serverId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserEventArgs : EventArgs
|
public class UserEventArgs : EventArgs
|
||||||
@@ -38,7 +36,6 @@ namespace Discord
|
|||||||
public class UserChannelEventArgs : UserEventArgs
|
public class UserChannelEventArgs : UserEventArgs
|
||||||
{
|
{
|
||||||
public Channel Channel { get; }
|
public Channel Channel { get; }
|
||||||
public string ChannelId => Channel.Id;
|
|
||||||
|
|
||||||
public UserChannelEventArgs(User user, Channel channel)
|
public UserChannelEventArgs(User user, Channel channel)
|
||||||
: base(user)
|
: base(user)
|
||||||
@@ -123,30 +120,29 @@ namespace Discord
|
|||||||
private readonly Users _users;
|
private readonly Users _users;
|
||||||
|
|
||||||
/// <summary> Returns the user with the specified id, along with their server-specific data, or null if none was found. </summary>
|
/// <summary> Returns the user with the specified id, along with their server-specific data, or null if none was found. </summary>
|
||||||
public User GetUser(Server server, string userId)
|
public User GetUser(Server server, long userId)
|
||||||
{
|
{
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return _users[userId, server.Id];
|
return _users[userId, server.Id];
|
||||||
}
|
}
|
||||||
/// <summary> Returns the user with the specified name and discriminator, along withtheir server-specific data, or null if they couldn't be found. </summary>
|
/// <summary> Returns the user with the specified name and discriminator, along withtheir server-specific data, or null if they couldn't be found. </summary>
|
||||||
/// <remarks> Name formats supported: Name and @Name. Search is case-insensitive. </remarks>
|
/// <remarks> Name formats supported: Name and @Name. Search is case-insensitive. </remarks>
|
||||||
public User GetUser(Server server, string username, string discriminator)
|
public User GetUser(Server server, string username, short discriminator)
|
||||||
{
|
{
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
if (username == null) throw new ArgumentNullException(nameof(username));
|
if (username == null) throw new ArgumentNullException(nameof(username));
|
||||||
if (discriminator == null) throw new ArgumentNullException(nameof(discriminator));
|
if (discriminator <= 0) throw new ArgumentOutOfRangeException(nameof(discriminator));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
User user = FindUsers(server, username, discriminator, true).FirstOrDefault();
|
return FindUsers(server, username, discriminator, true).FirstOrDefault();
|
||||||
return _users[user?.Id, server.Id];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Returns all users with the specified server and name, along with their server-specific data. </summary>
|
/// <summary> Returns all users with the specified server and name, along with their server-specific data. </summary>
|
||||||
/// <remarks> Name formats supported: Name and @Name. Search is case-insensitive.</remarks>
|
/// <remarks> Name formats supported: Name and @Name. Search is case-insensitive.</remarks>
|
||||||
public IEnumerable<User> FindUsers(Server server, string name, string discriminator = null, bool exactMatch = false)
|
public IEnumerable<User> FindUsers(Server server, string name, short? discriminator = null, bool exactMatch = false)
|
||||||
{
|
{
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||||
@@ -156,16 +152,16 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
/// <summary> Returns all users with the specified channel and name, along with their server-specific data. </summary>
|
/// <summary> Returns all users with the specified channel and name, along with their server-specific data. </summary>
|
||||||
/// <remarks> Name formats supported: Name and @Name. Search is case-insensitive.</remarks>
|
/// <remarks> Name formats supported: Name and @Name. Search is case-insensitive.</remarks>
|
||||||
public IEnumerable<User> FindUsers(Channel channel, string name, string discriminator = null, bool exactMatch = false)
|
public IEnumerable<User> FindUsers(Channel channel, string name, short? discriminator = null, bool exactMatch = false)
|
||||||
{
|
{
|
||||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return FindUsers(channel.Members, channel.IsPrivate ? null : channel.Server.Id, name, discriminator, exactMatch);
|
return FindUsers(channel.Members, channel.IsPrivate ? (long?)null : channel.Server.Id, name, discriminator, exactMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<User> FindUsers(IEnumerable<User> users, string serverId, string name, string discriminator = null, bool exactMatch = false)
|
private IEnumerable<User> FindUsers(IEnumerable<User> users, long? serverId, string name, short? discriminator = null, bool exactMatch = false)
|
||||||
{
|
{
|
||||||
var query = users.Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase));
|
var query = users.Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
@@ -173,7 +169,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (name[0] == '<' && name[1] == '@' && name[name.Length - 1] == '>') //Parse mention
|
if (name[0] == '<' && name[1] == '@' && name[name.Length - 1] == '>') //Parse mention
|
||||||
{
|
{
|
||||||
string id = name.Substring(2, name.Length - 3);
|
long id = IdConvert.ToLong(name.Substring(2, name.Length - 3));
|
||||||
var channel = _users[id, serverId];
|
var channel = _users[id, serverId];
|
||||||
if (channel != null)
|
if (channel != null)
|
||||||
query = query.Concat(new User[] { channel });
|
query = query.Concat(new User[] { channel });
|
||||||
@@ -186,57 +182,60 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (discriminator != null)
|
if (discriminator != null)
|
||||||
query = query.Where(x => x.Discriminator == discriminator);
|
query = query.Where(x => x.Discriminator == discriminator.Value);
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task EditUser(User user, bool? mute = null, bool? deaf = null, IEnumerable<Role> roles = null)
|
public Task EditUser(User user, bool? mute = null, bool? deaf = null, IEnumerable<Role> roles = null)
|
||||||
{
|
{
|
||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
|
if (user.IsPrivate) throw new InvalidOperationException("Unable to edit users in a private channel");
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
var serverId = user.Server?.Id;
|
var serverId = user.Server.Id;
|
||||||
return _api.EditUser(serverId, user.Id,
|
return _api.EditUser(serverId, user.Id,
|
||||||
mute: mute, deaf: deaf,
|
mute: mute, deaf: deaf,
|
||||||
roles: roles.Select(x => x.Id).Where(x => x != serverId));
|
roleIds: roles.Select(x => x.Id).Where(x => x != serverId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task KickUser(User user)
|
public Task KickUser(User user)
|
||||||
{
|
{
|
||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
|
if (user.IsPrivate) throw new InvalidOperationException("Unable to kick users from a private channel");
|
||||||
|
|
||||||
return _api.KickUser(user.Server?.Id, user.Id);
|
return _api.KickUser(user.Server.Id, user.Id);
|
||||||
}
|
}
|
||||||
public Task BanUser(User user)
|
public Task BanUser(User user)
|
||||||
{
|
{
|
||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
|
if (user.IsPrivate) throw new InvalidOperationException("Unable to ban users from a private channel");
|
||||||
|
|
||||||
return _api.BanUser(user.Server?.Id, user.Id);
|
return _api.BanUser(user.Server.Id, user.Id);
|
||||||
}
|
}
|
||||||
public Task UnbanUser(Server server, string userId)
|
public Task UnbanUser(Server server, long userId)
|
||||||
{
|
{
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
|
||||||
|
|
||||||
return _api.UnbanUser(server.Id, userId);
|
return _api.UnbanUser(server.Id, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> PruneUsers(string serverId, int days, bool simulate = false)
|
public async Task<int> PruneUsers(Server server, int days, bool simulate = false)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days));
|
if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
var response = await _api.PruneUsers(serverId, days, simulate);
|
var response = await _api.PruneUsers(server.Id, days, simulate);
|
||||||
return response.Pruned ?? 0;
|
return response.Pruned ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>When Config.UseLargeThreshold is enabled, running this command will request the Discord server to provide you with all offline users for a particular server.</summary>
|
/// <summary>When Config.UseLargeThreshold is enabled, running this command will request the Discord server to provide you with all offline users for a particular server.</summary>
|
||||||
public void RequestOfflineUsers(string serverId)
|
public void RequestOfflineUsers(Server server)
|
||||||
{
|
{
|
||||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
|
|
||||||
_dataSocket.SendGetUsers(serverId);
|
_dataSocket.SendGetUsers(server.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task EditProfile(string currentPassword = "",
|
public Task EditProfile(string currentPassword = "",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
public IDiscordVoiceClient GetVoiceClient(Server server)
|
public IDiscordVoiceClient GetVoiceClient(Server server)
|
||||||
{
|
{
|
||||||
if (server.Id == null) throw new ArgumentNullException(nameof(server.Id));
|
if (server.Id <= 0) throw new ArgumentOutOfRangeException(nameof(server.Id));
|
||||||
|
|
||||||
if (!Config.EnableVoiceMultiserver)
|
if (!Config.EnableVoiceMultiserver)
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@ namespace Discord
|
|||||||
return this;
|
return this;
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiscordWSClient client;
|
DiscordWSClient client;
|
||||||
if (_voiceClients.TryGetValue(server.Id, out client))
|
if (_voiceClients.TryGetValue(server.Id, out client))
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Discord
|
|||||||
private readonly Random _rand;
|
private readonly Random _rand;
|
||||||
private readonly JsonSerializer _serializer;
|
private readonly JsonSerializer _serializer;
|
||||||
private readonly ConcurrentQueue<Message> _pendingMessages;
|
private readonly ConcurrentQueue<Message> _pendingMessages;
|
||||||
private readonly ConcurrentDictionary<string, DiscordWSClient> _voiceClients;
|
private readonly ConcurrentDictionary<long, DiscordWSClient> _voiceClients;
|
||||||
private readonly Dictionary<Type, IService> _services;
|
private readonly Dictionary<Type, IService> _services;
|
||||||
private bool _sentInitialLog;
|
private bool _sentInitialLog;
|
||||||
private uint _nextVoiceClientId;
|
private uint _nextVoiceClientId;
|
||||||
@@ -38,7 +38,7 @@ namespace Discord
|
|||||||
if (Config.UseMessageQueue)
|
if (Config.UseMessageQueue)
|
||||||
_pendingMessages = new ConcurrentQueue<Message>();
|
_pendingMessages = new ConcurrentQueue<Message>();
|
||||||
if (Config.EnableVoiceMultiserver)
|
if (Config.EnableVoiceMultiserver)
|
||||||
_voiceClients = new ConcurrentDictionary<string, DiscordWSClient>();
|
_voiceClients = new ConcurrentDictionary<long, DiscordWSClient>();
|
||||||
|
|
||||||
object cacheLock = new object();
|
object cacheLock = new object();
|
||||||
_channels = new Channels(this, cacheLock);
|
_channels = new Channels(this, cacheLock);
|
||||||
@@ -139,18 +139,18 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
if (_config.LogLevel >= LogMessageSeverity.Debug)
|
if (_config.LogLevel >= LogMessageSeverity.Debug)
|
||||||
{
|
{
|
||||||
_channels.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
|
_channels.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Channel {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Id}");
|
||||||
_channels.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
|
_channels.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Channel {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Id}");
|
||||||
_channels.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Channels");
|
_channels.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Channels");
|
||||||
_users.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
|
_users.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Id}");
|
||||||
_users.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
|
_users.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Id}");
|
||||||
_users.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users");
|
_users.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users");
|
||||||
_messages.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
|
_messages.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Message {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
|
||||||
_messages.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
|
_messages.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Message {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
|
||||||
_messages.ItemRemapped += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Remapped Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/[{e.OldId} -> {e.NewId}]");
|
_messages.ItemRemapped += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Remapped Message {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Channel.Id}/[{e.OldId} -> {e.NewId}]");
|
||||||
_messages.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Messages");
|
_messages.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Messages");
|
||||||
_roles.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Role {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
|
_roles.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Role {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Id}");
|
||||||
_roles.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Role {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
|
_roles.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Role {IdConvert.ToString(e.Item.Server?.Id) ?? "[Private]"}/{e.Item.Id}");
|
||||||
_roles.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Roles");
|
_roles.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Roles");
|
||||||
_servers.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Server {e.Item.Id}");
|
_servers.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Server {e.Item.Id}");
|
||||||
_servers.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Server {e.Item.Id}");
|
_servers.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Server {e.Item.Id}");
|
||||||
@@ -498,8 +498,9 @@ namespace Discord
|
|||||||
var server = _servers[data.GuildId];
|
var server = _servers[data.GuildId];
|
||||||
if (server != null)
|
if (server != null)
|
||||||
{
|
{
|
||||||
server.AddBan(data.User?.Id);
|
var id = data.User?.Id ?? data.UserId;
|
||||||
RaiseUserBanned(data.User?.Id, server);
|
server.AddBan(id);
|
||||||
|
RaiseUserBanned(id, server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -507,8 +508,12 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
var data = e.Payload.ToObject<BanRemoveEvent>(_serializer);
|
var data = e.Payload.ToObject<BanRemoveEvent>(_serializer);
|
||||||
var server = _servers[data.GuildId];
|
var server = _servers[data.GuildId];
|
||||||
if (server != null && server.RemoveBan(data.User?.Id))
|
if (server != null)
|
||||||
RaiseUserUnbanned(data.User?.Id, server);
|
{
|
||||||
|
var id = data.User?.Id ?? data.UserId;
|
||||||
|
if (server.RemoveBan(id))
|
||||||
|
RaiseUserUnbanned(id, server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
public class VoiceDisconnectedEventArgs : DisconnectedEventArgs
|
public class VoiceDisconnectedEventArgs : DisconnectedEventArgs
|
||||||
{
|
{
|
||||||
public readonly string ServerId;
|
public readonly long ServerId;
|
||||||
|
|
||||||
internal VoiceDisconnectedEventArgs(string serverId, DisconnectedEventArgs e)
|
internal VoiceDisconnectedEventArgs(long serverId, DisconnectedEventArgs e)
|
||||||
: base(e.WasUnexpected, e.Error)
|
: base(e.WasUnexpected, e.Error)
|
||||||
{
|
{
|
||||||
ServerId = serverId;
|
ServerId = serverId;
|
||||||
@@ -60,13 +60,13 @@ namespace Discord
|
|||||||
|
|
||||||
public sealed class VoicePacketEventArgs
|
public sealed class VoicePacketEventArgs
|
||||||
{
|
{
|
||||||
public string UserId { get; }
|
public long UserId { get; }
|
||||||
public string ChannelId { get; }
|
public long ChannelId { get; }
|
||||||
public byte[] Buffer { get; }
|
public byte[] Buffer { get; }
|
||||||
public int Offset { get; }
|
public int Offset { get; }
|
||||||
public int Count { get; }
|
public int Count { get; }
|
||||||
|
|
||||||
internal VoicePacketEventArgs(string userId, string channelId, byte[] buffer, int offset, int count)
|
internal VoicePacketEventArgs(long userId, long channelId, byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
UserId = userId;
|
UserId = userId;
|
||||||
Buffer = buffer;
|
Buffer = buffer;
|
||||||
@@ -103,7 +103,7 @@ namespace Discord
|
|||||||
RaiseEvent(nameof(VoiceConnected), () => VoiceConnected(this, EventArgs.Empty));
|
RaiseEvent(nameof(VoiceConnected), () => VoiceConnected(this, EventArgs.Empty));
|
||||||
}
|
}
|
||||||
public event EventHandler<VoiceDisconnectedEventArgs> VoiceDisconnected;
|
public event EventHandler<VoiceDisconnectedEventArgs> VoiceDisconnected;
|
||||||
private void RaiseVoiceDisconnected(string serverId, DisconnectedEventArgs e)
|
private void RaiseVoiceDisconnected(long serverId, DisconnectedEventArgs e)
|
||||||
{
|
{
|
||||||
if (VoiceDisconnected != null)
|
if (VoiceDisconnected != null)
|
||||||
RaiseEvent(nameof(VoiceDisconnected), () => VoiceDisconnected(this, new VoiceDisconnectedEventArgs(serverId, e)));
|
RaiseEvent(nameof(VoiceDisconnected), () => VoiceDisconnected(this, new VoiceDisconnectedEventArgs(serverId, e)));
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
IDiscordVoiceBuffer IDiscordVoiceClient.OutputBuffer => _voiceSocket.OutputBuffer;
|
IDiscordVoiceBuffer IDiscordVoiceClient.OutputBuffer => _voiceSocket.OutputBuffer;
|
||||||
|
|
||||||
async Task IDiscordVoiceClient.JoinChannel(string channelId)
|
async Task IDiscordVoiceClient.JoinChannel(long channelId)
|
||||||
{
|
{
|
||||||
CheckReady(checkVoice: true);
|
CheckReady(checkVoice: true);
|
||||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId));
|
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
|
||||||
|
|
||||||
await _voiceSocket.Disconnect().ConfigureAwait(false);
|
await _voiceSocket.Disconnect().ConfigureAwait(false);
|
||||||
|
|
||||||
await _voiceSocket.SetChannel(_voiceServerId, channelId).ConfigureAwait(false);
|
await _voiceSocket.SetChannel(_voiceServerId.Value, channelId).ConfigureAwait(false);
|
||||||
_dataSocket.SendJoinVoice(_voiceServerId, channelId);
|
_dataSocket.SendJoinVoice(_voiceServerId.Value, channelId);
|
||||||
await _voiceSocket.WaitForConnection(_config.ConnectionTimeout).ConfigureAwait(false);
|
await _voiceSocket.WaitForConnection(_config.ConnectionTimeout).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ namespace Discord
|
|||||||
internal readonly VoiceWebSocket _voiceSocket;
|
internal readonly VoiceWebSocket _voiceSocket;
|
||||||
protected ExceptionDispatchInfo _disconnectReason;
|
protected ExceptionDispatchInfo _disconnectReason;
|
||||||
protected string _gateway, _token;
|
protected string _gateway, _token;
|
||||||
protected string _userId, _voiceServerId;
|
protected long? _userId, _voiceServerId;
|
||||||
private Task _runTask;
|
private Task _runTask;
|
||||||
private bool _wasDisconnectUnexpected;
|
private bool _wasDisconnectUnexpected;
|
||||||
|
|
||||||
public string CurrentUserId => _userId;
|
public long CurrentUserId => _userId.Value;
|
||||||
|
|
||||||
/// <summary> Returns the configuration object used to make this client. Note that this object cannot be edited directly - to change the configuration of this client, use the DiscordClient(DiscordClientConfig config) constructor. </summary>
|
/// <summary> Returns the configuration object used to make this client. Note that this object cannot be edited directly - to change the configuration of this client, use the DiscordClient(DiscordClientConfig config) constructor. </summary>
|
||||||
public DiscordWSClientConfig Config => _config;
|
public DiscordWSClientConfig Config => _config;
|
||||||
@@ -59,7 +59,7 @@ namespace Discord
|
|||||||
if (_config.EnableVoice)
|
if (_config.EnableVoice)
|
||||||
_voiceSocket = CreateVoiceSocket();
|
_voiceSocket = CreateVoiceSocket();
|
||||||
}
|
}
|
||||||
internal DiscordWSClient(DiscordWSClientConfig config = null, string voiceServerId = null)
|
internal DiscordWSClient(DiscordWSClientConfig config = null, long? voiceServerId = null)
|
||||||
: this(config)
|
: this(config)
|
||||||
{
|
{
|
||||||
_voiceServerId = voiceServerId;
|
_voiceServerId = voiceServerId;
|
||||||
@@ -100,7 +100,7 @@ namespace Discord
|
|||||||
socket.Connected += (s, e) => RaiseVoiceConnected();
|
socket.Connected += (s, e) => RaiseVoiceConnected();
|
||||||
socket.Disconnected += async (s, e) =>
|
socket.Disconnected += async (s, e) =>
|
||||||
{
|
{
|
||||||
RaiseVoiceDisconnected(socket.CurrentServerId, e);
|
RaiseVoiceDisconnected(socket.CurrentServerId.Value, e);
|
||||||
if (e.WasUnexpected)
|
if (e.WasUnexpected)
|
||||||
await socket.Reconnect().ConfigureAwait(false);
|
await socket.Reconnect().ConfigureAwait(false);
|
||||||
};
|
};
|
||||||
@@ -241,9 +241,9 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (_config.EnableVoice)
|
if (_config.EnableVoice)
|
||||||
{
|
{
|
||||||
string voiceServerId = _voiceSocket.CurrentServerId;
|
var voiceServerId = _voiceSocket.CurrentServerId;
|
||||||
if (voiceServerId != null)
|
if (voiceServerId != null)
|
||||||
_dataSocket.SendLeaveVoice(voiceServerId);
|
_dataSocket.SendLeaveVoice(voiceServerId.Value);
|
||||||
await _voiceSocket.Disconnect().ConfigureAwait(false);
|
await _voiceSocket.Disconnect().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await _dataSocket.Disconnect().ConfigureAwait(false);
|
await _dataSocket.Disconnect().ConfigureAwait(false);
|
||||||
@@ -303,17 +303,17 @@ namespace Discord
|
|||||||
switch (e.Type)
|
switch (e.Type)
|
||||||
{
|
{
|
||||||
case "READY":
|
case "READY":
|
||||||
_userId = e.Payload["user"].Value<string>("id");
|
_userId = IdConvert.ToLong(e.Payload["user"].Value<string>("id"));
|
||||||
break;
|
break;
|
||||||
case "VOICE_SERVER_UPDATE":
|
case "VOICE_SERVER_UPDATE":
|
||||||
{
|
{
|
||||||
string guildId = e.Payload.Value<string>("guild_id");
|
long guildId = IdConvert.ToLong(e.Payload.Value<string>("guild_id"));
|
||||||
|
|
||||||
if (_config.EnableVoice && guildId == _voiceSocket.CurrentServerId)
|
if (_config.EnableVoice && guildId == _voiceSocket.CurrentServerId)
|
||||||
{
|
{
|
||||||
string token = e.Payload.Value<string>("token");
|
string token = e.Payload.Value<string>("token");
|
||||||
_voiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
|
_voiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
|
||||||
await _voiceSocket.Login(_userId, _dataSocket.SessionId, token, _cancelToken).ConfigureAwait(false);
|
await _voiceSocket.Login(_userId.Value, _dataSocket.SessionId, token, _cancelToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal abstract class AsyncCollection<TValue> : IEnumerable<TValue>
|
internal abstract class AsyncCollection<TKey, TValue> : IEnumerable<TValue>
|
||||||
|
where TKey : struct, IEquatable<TKey>
|
||||||
where TValue : CachedObject
|
where TValue : CachedObject
|
||||||
{
|
{
|
||||||
private readonly object _writerLock;
|
private readonly object _writerLock;
|
||||||
@@ -19,9 +20,9 @@ namespace Discord
|
|||||||
public class CollectionItemRemappedEventArgs : EventArgs
|
public class CollectionItemRemappedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public TValue Item { get; }
|
public TValue Item { get; }
|
||||||
public string OldId { get; }
|
public TKey OldId { get; }
|
||||||
public string NewId { get; }
|
public TKey NewId { get; }
|
||||||
public CollectionItemRemappedEventArgs(TValue item, string oldId, string newId) { Item = item; OldId = oldId; NewId = newId; }
|
public CollectionItemRemappedEventArgs(TValue item, TKey oldId, TKey newId) { Item = item; OldId = oldId; NewId = newId; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventHandler<CollectionItemEventArgs> ItemCreated;
|
public EventHandler<CollectionItemEventArgs> ItemCreated;
|
||||||
@@ -37,7 +38,7 @@ namespace Discord
|
|||||||
ItemDestroyed(this, new CollectionItemEventArgs(item));
|
ItemDestroyed(this, new CollectionItemEventArgs(item));
|
||||||
}
|
}
|
||||||
public EventHandler<CollectionItemRemappedEventArgs> ItemRemapped;
|
public EventHandler<CollectionItemRemappedEventArgs> ItemRemapped;
|
||||||
private void RaiseItemRemapped(TValue item, string oldId, string newId)
|
private void RaiseItemRemapped(TValue item, TKey oldId, TKey newId)
|
||||||
{
|
{
|
||||||
if (ItemRemapped != null)
|
if (ItemRemapped != null)
|
||||||
ItemRemapped(this, new CollectionItemRemappedEventArgs(item, oldId, newId));
|
ItemRemapped(this, new CollectionItemRemappedEventArgs(item, oldId, newId));
|
||||||
@@ -51,20 +52,22 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected readonly DiscordClient _client;
|
protected readonly DiscordClient _client;
|
||||||
protected readonly ConcurrentDictionary<string, TValue> _dictionary;
|
protected readonly ConcurrentDictionary<TKey, TValue> _dictionary;
|
||||||
|
|
||||||
protected AsyncCollection(DiscordClient client, object writerLock)
|
protected AsyncCollection(DiscordClient client, object writerLock)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_writerLock = writerLock;
|
_writerLock = writerLock;
|
||||||
_dictionary = new ConcurrentDictionary<string, TValue>();
|
_dictionary = new ConcurrentDictionary<TKey, TValue>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TValue this[string key]
|
public TValue this[TKey? key]
|
||||||
|
=> key == null ? null : this[key.Value];
|
||||||
|
public TValue this[TKey key]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (key == null)
|
if (key.Equals(default(TKey)))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
TValue result;
|
TValue result;
|
||||||
@@ -73,7 +76,7 @@ namespace Discord
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected TValue GetOrAdd(string key, Func<TValue> createFunc)
|
protected TValue GetOrAdd(TKey key, Func<TValue> createFunc)
|
||||||
{
|
{
|
||||||
TValue result;
|
TValue result;
|
||||||
if (_dictionary.TryGetValue(key, out result))
|
if (_dictionary.TryGetValue(key, out result))
|
||||||
@@ -91,7 +94,7 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
public TValue TryRemove(string key)
|
public TValue TryRemove(TKey key)
|
||||||
{
|
{
|
||||||
if (_dictionary.ContainsKey(key))
|
if (_dictionary.ContainsKey(key))
|
||||||
{
|
{
|
||||||
@@ -107,7 +110,7 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public TValue Remap(string oldKey, string newKey)
|
public TValue Remap(TKey oldKey, TKey newKey)
|
||||||
{
|
{
|
||||||
if (_dictionary.ContainsKey(oldKey))
|
if (_dictionary.ContainsKey(oldKey))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,23 +1,35 @@
|
|||||||
namespace Discord
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Discord
|
||||||
{
|
{
|
||||||
public abstract class CachedObject
|
public abstract class CachedObject<TKey> : CachedObject
|
||||||
|
{
|
||||||
|
private TKey _id;
|
||||||
|
|
||||||
|
internal CachedObject(DiscordClient client, TKey id)
|
||||||
|
: base(client)
|
||||||
|
{
|
||||||
|
_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Returns the unique identifier for this object. </summary>
|
||||||
|
public TKey Id { get { return _id; } internal set { _id = value; } }
|
||||||
|
|
||||||
|
public override string ToString() => $"{this.GetType().Name} {Id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class CachedObject
|
||||||
{
|
{
|
||||||
protected readonly DiscordClient _client;
|
protected readonly DiscordClient _client;
|
||||||
private bool _isCached;
|
private bool _isCached;
|
||||||
|
|
||||||
internal bool IsCached => _isCached;
|
internal bool IsCached => _isCached;
|
||||||
|
|
||||||
internal CachedObject(DiscordClient client, string id)
|
internal CachedObject(DiscordClient client)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
Id = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Returns the unique identifier for this object. </summary>
|
|
||||||
public string Id { get; internal set; }
|
|
||||||
|
|
||||||
public override string ToString() => $"{this.GetType().Name} {Id}";
|
|
||||||
|
|
||||||
internal void Cache()
|
internal void Cache()
|
||||||
{
|
{
|
||||||
LoadReferences();
|
LoadReferences();
|
||||||
|
|||||||
28
src/Discord.Net/Helpers/IdConvert.cs
Normal file
28
src/Discord.Net/Helpers/IdConvert.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Discord
|
||||||
|
{
|
||||||
|
internal static class IdConvert
|
||||||
|
{
|
||||||
|
internal static readonly IFormatProvider _format = CultureInfo.InvariantCulture;
|
||||||
|
|
||||||
|
public static short ToShort(string value)
|
||||||
|
=> short.Parse(value, NumberStyles.None, _format);
|
||||||
|
public static short? ToNullableShort(string value)
|
||||||
|
=> value == null ? (short?)null : short.Parse(value, NumberStyles.None, _format);
|
||||||
|
public static long ToLong(string value)
|
||||||
|
=> long.Parse(value, NumberStyles.None, _format);
|
||||||
|
public static long? ToNullableLong(string value)
|
||||||
|
=> value == null ? (long?)null : long.Parse(value, NumberStyles.None, _format);
|
||||||
|
|
||||||
|
public static string ToString(short value)
|
||||||
|
=> value.ToString(_format);
|
||||||
|
public static string ToString(short? value)
|
||||||
|
=> value?.ToString(_format);
|
||||||
|
public static string ToString(long value)
|
||||||
|
=> value.ToString(_format);
|
||||||
|
public static string ToString(long? value)
|
||||||
|
=> value?.ToString(_format);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
return _userRegex.Replace(text, new MatchEvaluator(e =>
|
return _userRegex.Replace(text, new MatchEvaluator(e =>
|
||||||
{
|
{
|
||||||
string id = e.Value.Substring(2, e.Value.Length - 3);
|
long id = IdConvert.ToLong(e.Value.Substring(2, e.Value.Length - 3));
|
||||||
var user = client.Users[id, server?.Id];
|
var user = client.Users[id, server?.Id];
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
@@ -40,7 +40,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
return _channelRegex.Replace(text, new MatchEvaluator(e =>
|
return _channelRegex.Replace(text, new MatchEvaluator(e =>
|
||||||
{
|
{
|
||||||
string id = e.Value.Substring(2, e.Value.Length - 3);
|
long id = IdConvert.ToLong(e.Value.Substring(2, e.Value.Length - 3));
|
||||||
var channel = client.Channels[id];
|
var channel = client.Channels[id];
|
||||||
if (channel != null && channel.Server.Id == server.Id)
|
if (channel != null && channel.Server.Id == server.Id)
|
||||||
{
|
{
|
||||||
@@ -52,7 +52,7 @@ namespace Discord
|
|||||||
return '#' + e.Value;
|
return '#' + e.Value;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
internal static string CleanRoleMentions(DiscordClient client, User user, Channel channel, string text, List<Role> roles = null)
|
/*internal static string CleanRoleMentions(DiscordClient client, User user, Channel channel, string text, List<Role> roles = null)
|
||||||
{
|
{
|
||||||
return _roleRegex.Replace(text, new MatchEvaluator(e =>
|
return _roleRegex.Replace(text, new MatchEvaluator(e =>
|
||||||
{
|
{
|
||||||
@@ -60,6 +60,6 @@ namespace Discord
|
|||||||
roles.Add(channel.Server.EveryoneRole);
|
roles.Add(channel.Server.EveryoneRole);
|
||||||
return e.Value;
|
return e.Value;
|
||||||
}));
|
}));
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal struct Reference<T>
|
internal struct Reference<T>
|
||||||
where T : CachedObject
|
where T : CachedObject<long>
|
||||||
{
|
{
|
||||||
private Action<T> _onCache, _onUncache;
|
private Action<T> _onCache, _onUncache;
|
||||||
private Func<string, T> _getItem;
|
private Func<long, T> _getItem;
|
||||||
private string _id;
|
private long? _id;
|
||||||
public string Id
|
public long? Id
|
||||||
{
|
{
|
||||||
get { return _id; }
|
get { return _id; }
|
||||||
set
|
set
|
||||||
@@ -24,14 +24,15 @@ namespace Discord
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
var v = _value; //A little trickery to make this threadsafe
|
var v = _value; //A little trickery to make this threadsafe
|
||||||
|
var id = _id;
|
||||||
if (v != null && !_value.IsCached)
|
if (v != null && !_value.IsCached)
|
||||||
{
|
{
|
||||||
v = null;
|
v = null;
|
||||||
_value = null;
|
_value = null;
|
||||||
}
|
}
|
||||||
if (v == null && _id != null)
|
if (v == null && id != null)
|
||||||
{
|
{
|
||||||
v = _getItem(_id);
|
v = _getItem(id.Value);
|
||||||
if (v != null && _onCache != null)
|
if (v != null && _onCache != null)
|
||||||
_onCache(v);
|
_onCache(v);
|
||||||
_value = v;
|
_value = v;
|
||||||
@@ -55,9 +56,9 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Reference(Func<string, T> onUpdate, Action<T> onCache = null, Action<T> onUncache = null)
|
public Reference(Func<long, T> onUpdate, Action<T> onCache = null, Action<T> onUncache = null)
|
||||||
: this(null, onUpdate, onCache, onUncache) { }
|
: this(null, onUpdate, onCache, onUncache) { }
|
||||||
public Reference(string id, Func<string, T> getItem, Action<T> onCache = null, Action<T> onUncache = null)
|
public Reference(long? id, Func<long, T> getItem, Action<T> onCache = null, Action<T> onUncache = null)
|
||||||
{
|
{
|
||||||
_id = id;
|
_id = id;
|
||||||
_getItem = getItem;
|
_getItem = getItem;
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
public sealed class Channel : CachedObject
|
public sealed class Channel : CachedObject<long>
|
||||||
{
|
{
|
||||||
public sealed class PermissionOverwrite
|
public sealed class PermissionOverwrite
|
||||||
{
|
{
|
||||||
public PermissionTarget TargetType { get; }
|
public PermissionTarget TargetType { get; }
|
||||||
public string TargetId { get; }
|
public long TargetId { get; }
|
||||||
public DualChannelPermissions Permissions { get; }
|
public DualChannelPermissions Permissions { get; }
|
||||||
|
|
||||||
internal PermissionOverwrite(PermissionTarget targetType, string targetId, uint allow, uint deny)
|
internal PermissionOverwrite(PermissionTarget targetType, long targetId, uint allow, uint deny)
|
||||||
{
|
{
|
||||||
TargetType = targetType;
|
TargetType = targetType;
|
||||||
TargetId = targetId;
|
TargetId = targetId;
|
||||||
@@ -55,20 +55,20 @@ namespace Discord
|
|||||||
return _members.Select(x => x.Value);
|
return _members.Select(x => x.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private Dictionary<string, User> _members;
|
private Dictionary<long, User> _members;
|
||||||
private bool _areMembersStale;
|
private bool _areMembersStale;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all messages the client has seen posted in this channel. This collection does not guarantee any ordering. </summary>
|
/// <summary> Returns a collection of all messages the client has seen posted in this channel. This collection does not guarantee any ordering. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Message> Messages => _messages.Values;
|
public IEnumerable<Message> Messages => _messages?.Values ?? Enumerable.Empty<Message>();
|
||||||
private readonly ConcurrentDictionary<string, Message> _messages;
|
private readonly ConcurrentDictionary<long, Message> _messages;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all custom permissions used for this channel. </summary>
|
/// <summary> Returns a collection of all custom permissions used for this channel. </summary>
|
||||||
private static readonly PermissionOverwrite[] _initialPermissionsOverwrites = new PermissionOverwrite[0];
|
private static readonly PermissionOverwrite[] _initialPermissionsOverwrites = new PermissionOverwrite[0];
|
||||||
private PermissionOverwrite[] _permissionOverwrites;
|
private PermissionOverwrite[] _permissionOverwrites;
|
||||||
public IEnumerable<PermissionOverwrite> PermissionOverwrites { get { return _permissionOverwrites; } internal set { _permissionOverwrites = value.ToArray(); } }
|
public IEnumerable<PermissionOverwrite> PermissionOverwrites { get { return _permissionOverwrites; } internal set { _permissionOverwrites = value.ToArray(); } }
|
||||||
|
|
||||||
internal Channel(DiscordClient client, string id, string serverId, string recipientId)
|
internal Channel(DiscordClient client, long id, long? serverId, long? recipientId)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
{
|
{
|
||||||
_server = new Reference<Server>(serverId,
|
_server = new Reference<Server>(serverId,
|
||||||
@@ -92,7 +92,8 @@ namespace Discord
|
|||||||
_areMembersStale = true;
|
_areMembersStale = true;
|
||||||
|
|
||||||
//Local Cache
|
//Local Cache
|
||||||
_messages = new ConcurrentDictionary<string, Message>();
|
if (client.Config.MessageCacheLength > 0)
|
||||||
|
_messages = new ConcurrentDictionary<long, Message>();
|
||||||
}
|
}
|
||||||
internal override void LoadReferences()
|
internal override void LoadReferences()
|
||||||
{
|
{
|
||||||
@@ -164,10 +165,10 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (IsPrivate)
|
if (IsPrivate)
|
||||||
{
|
{
|
||||||
_members = new Dictionary<string, User>()
|
_members = new Dictionary<long, User>()
|
||||||
{
|
{
|
||||||
{ _client.CurrentUserId, _client.PrivateUser },
|
{ _client.CurrentUserId, _client.PrivateUser },
|
||||||
{ _recipient.Id, _recipient.Value }
|
{ _recipient.Id.Value, _recipient.Value }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (Type == ChannelType.Text)
|
else if (Type == ChannelType.Text)
|
||||||
@@ -205,6 +206,6 @@ namespace Discord
|
|||||||
|
|
||||||
public override bool Equals(object obj) => obj is Channel && (obj as Channel).Id == Id;
|
public override bool Equals(object obj) => obj is Channel && (obj as Channel).Id == Id;
|
||||||
public override int GetHashCode() => unchecked(Id.GetHashCode() + 5658);
|
public override int GetHashCode() => unchecked(Id.GetHashCode() + 5658);
|
||||||
public override string ToString() => Name ?? Id;
|
public override string ToString() => Name ?? IdConvert.ToString(Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
public sealed class GlobalUser : CachedObject
|
public sealed class GlobalUser : CachedObject<long>
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, User> _users;
|
private readonly ConcurrentDictionary<long, User> _users;
|
||||||
|
|
||||||
/// <summary> Returns the email for this user. </summary>
|
/// <summary> Returns the email for this user. </summary>
|
||||||
/// <remarks> This field is only ever populated for the current logged in user. </remarks>
|
/// <remarks> This field is only ever populated for the current logged in user. </remarks>
|
||||||
@@ -35,12 +35,12 @@ namespace Discord
|
|||||||
|
|
||||||
/// <summary> Returns a collection of all server-specific data for every server this user is a member of. </summary>
|
/// <summary> Returns a collection of all server-specific data for every server this user is a member of. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
internal IEnumerable<User> Memberships => _users.Select(x => _client.Users[Id, x.Key]);
|
internal IEnumerable<User> Memberships => _users.Select(x => x.Value);
|
||||||
|
|
||||||
internal GlobalUser(DiscordClient client, string id)
|
internal GlobalUser(DiscordClient client, long id)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
{
|
{
|
||||||
_users = new ConcurrentDictionary<string, User>();
|
_users = new ConcurrentDictionary<long, User>();
|
||||||
}
|
}
|
||||||
internal override void LoadReferences() { }
|
internal override void LoadReferences() { }
|
||||||
internal override void UnloadReferences()
|
internal override void UnloadReferences()
|
||||||
@@ -56,10 +56,10 @@ namespace Discord
|
|||||||
IsVerified = model.IsVerified;
|
IsVerified = model.IsVerified;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddUser(User user) => _users.TryAdd(user.UniqueId, user);
|
internal void AddUser(User user) => _users.TryAdd(user.Server?.Id ?? 0, user);
|
||||||
internal void RemoveUser(User user)
|
internal void RemoveUser(User user)
|
||||||
{
|
{
|
||||||
if (_users.TryRemove(user.UniqueId, out user))
|
if (_users.TryRemove(user.Server?.Id ?? 0, out user))
|
||||||
CheckUser();
|
CheckUser();
|
||||||
}
|
}
|
||||||
internal void CheckUser()
|
internal void CheckUser()
|
||||||
@@ -70,6 +70,6 @@ namespace Discord
|
|||||||
|
|
||||||
public override bool Equals(object obj) => obj is GlobalUser && (obj as GlobalUser).Id == Id;
|
public override bool Equals(object obj) => obj is GlobalUser && (obj as GlobalUser).Id == Id;
|
||||||
public override int GetHashCode() => unchecked(Id.GetHashCode() + 7891);
|
public override int GetHashCode() => unchecked(Id.GetHashCode() + 7891);
|
||||||
public override string ToString() => Id;
|
public override string ToString() => IdConvert.ToString(Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using Discord.API;
|
using Discord.API;
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
public sealed class Invite : CachedObject
|
public sealed class Invite : CachedObject<string>
|
||||||
{
|
{
|
||||||
public sealed class ServerInfo
|
public sealed class ServerInfo
|
||||||
{
|
{
|
||||||
/// <summary> Returns the unique identifier of this server. </summary>
|
/// <summary> Returns the unique identifier of this server. </summary>
|
||||||
public string Id { get; }
|
public long Id { get; }
|
||||||
/// <summary> Returns the name of this server. </summary>
|
/// <summary> Returns the name of this server. </summary>
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
internal ServerInfo(string id, string name)
|
internal ServerInfo(long id, string name)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Name = name;
|
Name = name;
|
||||||
@@ -22,11 +21,11 @@ namespace Discord
|
|||||||
public sealed class ChannelInfo
|
public sealed class ChannelInfo
|
||||||
{
|
{
|
||||||
/// <summary> Returns the unique identifier of this channel. </summary>
|
/// <summary> Returns the unique identifier of this channel. </summary>
|
||||||
public string Id { get; }
|
public long Id { get; }
|
||||||
/// <summary> Returns the name of this channel. </summary>
|
/// <summary> Returns the name of this channel. </summary>
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
internal ChannelInfo(string id, string name)
|
internal ChannelInfo(long id, string name)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Name = name;
|
Name = name;
|
||||||
@@ -35,17 +34,17 @@ namespace Discord
|
|||||||
public sealed class InviterInfo
|
public sealed class InviterInfo
|
||||||
{
|
{
|
||||||
/// <summary> Returns the unique identifier for this user. </summary>
|
/// <summary> Returns the unique identifier for this user. </summary>
|
||||||
public string Id { get; }
|
public long Id { get; }
|
||||||
/// <summary> Returns the name of this user. </summary>
|
/// <summary> Returns the name of this user. </summary>
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
/// <summary> Returns the by-name unique identifier for this user. </summary>
|
/// <summary> Returns the by-name unique identifier for this user. </summary>
|
||||||
public string Discriminator { get; }
|
public int Discriminator { get; }
|
||||||
/// <summary> Returns the unique identifier for this user's avatar. </summary>
|
/// <summary> Returns the unique identifier for this user's avatar. </summary>
|
||||||
public string AvatarId { get; }
|
public string AvatarId { get; }
|
||||||
/// <summary> Returns the full path to this user's avatar. </summary>
|
/// <summary> Returns the full path to this user's avatar. </summary>
|
||||||
public string AvatarUrl => User.GetAvatarUrl(Id, AvatarId);
|
public string AvatarUrl => User.GetAvatarUrl(Id, AvatarId);
|
||||||
|
|
||||||
internal InviterInfo(string id, string name, string discriminator, string avatarId)
|
internal InviterInfo(long id, string name, int discriminator, string avatarId)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Name = name;
|
Name = name;
|
||||||
@@ -76,9 +75,9 @@ namespace Discord
|
|||||||
public DateTime CreatedAt { get; private set; }
|
public DateTime CreatedAt { get; private set; }
|
||||||
|
|
||||||
/// <summary> Returns a URL for this invite using XkcdCode if available or Id if not. </summary>
|
/// <summary> Returns a URL for this invite using XkcdCode if available or Id if not. </summary>
|
||||||
public string Url => API.Endpoints.InviteUrl(XkcdCode ?? Id);
|
public string Url => API.Endpoints.InviteUrl(XkcdCode ?? Id.ToString());
|
||||||
|
|
||||||
internal Invite(DiscordClient client, string code, string xkcdPass, string serverId, string inviterId, string channelId)
|
internal Invite(DiscordClient client, string code, string xkcdPass)
|
||||||
: base(client, code)
|
: base(client, code)
|
||||||
{
|
{
|
||||||
XkcdCode = xkcdPass;
|
XkcdCode = xkcdPass;
|
||||||
@@ -93,7 +92,7 @@ namespace Discord
|
|||||||
if (model.Channel != null)
|
if (model.Channel != null)
|
||||||
Channel = new ChannelInfo(model.Channel.Id, model.Channel.Name);
|
Channel = new ChannelInfo(model.Channel.Id, model.Channel.Name);
|
||||||
if (model.Inviter != null)
|
if (model.Inviter != null)
|
||||||
Inviter = new InviterInfo(model.Inviter.Id, model.Inviter.Username, model.Inviter.Discriminator, model.Inviter.Avatar);
|
Inviter = new InviterInfo(model.Inviter.Id, model.Inviter.Username, model.Inviter.Discriminator.Value, model.Inviter.Avatar);
|
||||||
}
|
}
|
||||||
internal void Update(InviteInfo model)
|
internal void Update(InviteInfo model)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
public sealed class Message : CachedObject
|
public sealed class Message : CachedObject<long>
|
||||||
{
|
{
|
||||||
public sealed class Attachment : File
|
public sealed class Attachment : File
|
||||||
{
|
{
|
||||||
@@ -90,9 +90,6 @@ namespace Discord
|
|||||||
Height = height;
|
Height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Returns the local unique identifier for this message. </summary>
|
|
||||||
public string Nonce { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary> Returns true if the logged-in user was mentioned. </summary>
|
/// <summary> Returns true if the logged-in user was mentioned. </summary>
|
||||||
/// <remarks> This is not set to true if the user was mentioned with @everyone (see IsMentioningEverone). </remarks>
|
/// <remarks> This is not set to true if the user was mentioned with @everyone (see IsMentioningEverone). </remarks>
|
||||||
@@ -145,7 +142,7 @@ namespace Discord
|
|||||||
public User User => _user.Value;
|
public User User => _user.Value;
|
||||||
private readonly Reference<User> _user;
|
private readonly Reference<User> _user;
|
||||||
|
|
||||||
internal Message(DiscordClient client, string id, string channelId, string userId)
|
internal Message(DiscordClient client, long id, long channelId, long userId)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
{
|
{
|
||||||
_channel = new Reference<Channel>(channelId,
|
_channel = new Reference<Channel>(channelId,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
public sealed class Role : CachedObject
|
public sealed class Role : CachedObject<long>
|
||||||
{
|
{
|
||||||
/// <summary> Returns the name of this role. </summary>
|
/// <summary> Returns the name of this role. </summary>
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
@@ -33,7 +33,7 @@ namespace Discord
|
|||||||
public IEnumerable<User> Members => _server.Id != null ? (IsEveryone ? Server.Members : Server.Members.Where(x => x.HasRole(this))) : new User[0];
|
public IEnumerable<User> Members => _server.Id != null ? (IsEveryone ? Server.Members : Server.Members.Where(x => x.HasRole(this))) : new User[0];
|
||||||
//TODO: Add local members cache
|
//TODO: Add local members cache
|
||||||
|
|
||||||
internal Role(DiscordClient client, string id, string serverId)
|
internal Role(DiscordClient client, long id, long serverId)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
{
|
{
|
||||||
_server = new Reference<Server>(serverId, x => _client.Servers[x], x => x.AddRole(this), x => x.RemoveRole(this));
|
_server = new Reference<Server>(serverId, x => _client.Servers[x], x => x.AddRole(this), x => x.RemoveRole(this));
|
||||||
@@ -72,6 +72,6 @@ namespace Discord
|
|||||||
|
|
||||||
public override bool Equals(object obj) => obj is Role && (obj as Role).Id == Id;
|
public override bool Equals(object obj) => obj is Role && (obj as Role).Id == Id;
|
||||||
public override int GetHashCode() => unchecked(Id.GetHashCode() + 6653);
|
public override int GetHashCode() => unchecked(Id.GetHashCode() + 6653);
|
||||||
public override string ToString() => Name ?? Id;
|
public override string ToString() => Name ?? IdConvert.ToString(Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
public sealed class Server : CachedObject
|
public sealed class Server : CachedObject<long>
|
||||||
{
|
{
|
||||||
/// <summary> Returns the name of this channel. </summary>
|
/// <summary> Returns the name of this channel. </summary>
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
@@ -28,7 +28,7 @@ namespace Discord
|
|||||||
/// <summary> Returns the user that first created this server. </summary>
|
/// <summary> Returns the user that first created this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public User Owner { get; private set; }
|
public User Owner { get; private set; }
|
||||||
private string _ownerId;
|
private long _ownerId;
|
||||||
|
|
||||||
/// <summary> Returns the AFK voice channel for this server (see AFKTimeout). </summary>
|
/// <summary> Returns the AFK voice channel for this server (see AFKTimeout). </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
@@ -41,8 +41,8 @@ namespace Discord
|
|||||||
|
|
||||||
/// <summary> Returns a collection of the ids of all users banned on this server. </summary>
|
/// <summary> Returns a collection of the ids of all users banned on this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<string> Bans => _bans.Select(x => x.Key);
|
public IEnumerable<long> Bans => _bans.Select(x => x.Key);
|
||||||
private ConcurrentDictionary<string, bool> _bans;
|
private ConcurrentDictionary<long, bool> _bans;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all channels within this server. </summary>
|
/// <summary> Returns a collection of all channels within this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
@@ -53,12 +53,12 @@ namespace Discord
|
|||||||
/// <summary> Returns a collection of all channels within this server. </summary>
|
/// <summary> Returns a collection of all channels within this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Channel> VoiceChannels => _channels.Select(x => x.Value).Where(x => x.Type == ChannelType.Voice);
|
public IEnumerable<Channel> VoiceChannels => _channels.Select(x => x.Value).Where(x => x.Type == ChannelType.Voice);
|
||||||
private ConcurrentDictionary<string, Channel> _channels;
|
private ConcurrentDictionary<long, Channel> _channels;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all users within this server with their server-specific data. </summary>
|
/// <summary> Returns a collection of all users within this server with their server-specific data. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<User> Members => _members.Select(x => x.Value);
|
public IEnumerable<User> Members => _members.Select(x => x.Value);
|
||||||
private ConcurrentDictionary<string, User> _members;
|
private ConcurrentDictionary<long, User> _members;
|
||||||
|
|
||||||
/// <summary> Return the the role representing all users in a server. </summary>
|
/// <summary> Return the the role representing all users in a server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
@@ -66,20 +66,20 @@ namespace Discord
|
|||||||
/// <summary> Returns a collection of all roles within this server. </summary>
|
/// <summary> Returns a collection of all roles within this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Role> Roles => _roles.Select(x => x.Value);
|
public IEnumerable<Role> Roles => _roles.Select(x => x.Value);
|
||||||
private ConcurrentDictionary<string, Role> _roles;
|
private ConcurrentDictionary<long, Role> _roles;
|
||||||
|
|
||||||
internal Server(DiscordClient client, string id)
|
internal Server(DiscordClient client, long id)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
{
|
{
|
||||||
_afkChannel = new Reference<Channel>(x => _client.Channels[x]);
|
_afkChannel = new Reference<Channel>(x => _client.Channels[x]);
|
||||||
|
|
||||||
//Global Cache
|
//Global Cache
|
||||||
_channels = new ConcurrentDictionary<string, Channel>();
|
_channels = new ConcurrentDictionary<long, Channel>();
|
||||||
_members = new ConcurrentDictionary<string, User>();
|
_members = new ConcurrentDictionary<long, User>();
|
||||||
_roles = new ConcurrentDictionary<string, Role>();
|
_roles = new ConcurrentDictionary<long, Role>();
|
||||||
|
|
||||||
//Local Cache
|
//Local Cache
|
||||||
_bans = new ConcurrentDictionary<string, bool>();
|
_bans = new ConcurrentDictionary<long, bool>();
|
||||||
}
|
}
|
||||||
internal override void LoadReferences()
|
internal override void LoadReferences()
|
||||||
{
|
{
|
||||||
@@ -129,7 +129,7 @@ namespace Discord
|
|||||||
JoinedAt = model.JoinedAt.Value;
|
JoinedAt = model.JoinedAt.Value;
|
||||||
if (model.OwnerId != null && _ownerId != model.OwnerId)
|
if (model.OwnerId != null && _ownerId != model.OwnerId)
|
||||||
{
|
{
|
||||||
_ownerId = model.OwnerId;
|
_ownerId = model.OwnerId.Value;
|
||||||
Owner = _client.Users[_ownerId, Id];
|
Owner = _client.Users[_ownerId, Id];
|
||||||
}
|
}
|
||||||
if (model.Region != null)
|
if (model.Region != null)
|
||||||
@@ -178,11 +178,11 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddBan(string banId)
|
internal void AddBan(long banId)
|
||||||
{
|
{
|
||||||
_bans.TryAdd(banId, true);
|
_bans.TryAdd(banId, true);
|
||||||
}
|
}
|
||||||
internal bool RemoveBan(string banId)
|
internal bool RemoveBan(long banId)
|
||||||
{
|
{
|
||||||
bool ignored;
|
bool ignored;
|
||||||
return _bans.TryRemove(banId, out ignored);
|
return _bans.TryRemove(banId, out ignored);
|
||||||
@@ -254,6 +254,6 @@ namespace Discord
|
|||||||
|
|
||||||
public override bool Equals(object obj) => obj is Server && (obj as Server).Id == Id;
|
public override bool Equals(object obj) => obj is Server && (obj as Server).Id == Id;
|
||||||
public override int GetHashCode() => unchecked(Id.GetHashCode() + 5175);
|
public override int GetHashCode() => unchecked(Id.GetHashCode() + 5175);
|
||||||
public override string ToString() => Name ?? Id;
|
public override string ToString() => Name ?? IdConvert.ToString(Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,20 +20,34 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class User : CachedObject
|
public class User : CachedObject<long>
|
||||||
{
|
{
|
||||||
internal static string GetId(string userId, string serverId) => (serverId ?? "Private") + '_' + userId;
|
internal struct CompositeKey : IEquatable<CompositeKey>
|
||||||
internal static string GetAvatarUrl(string userId, string avatarId) => avatarId != null ? Endpoints.UserAvatar(userId, avatarId) : null;
|
{
|
||||||
|
public long ServerId, UserId;
|
||||||
|
public CompositeKey(long userId, long? serverId)
|
||||||
|
{
|
||||||
|
ServerId = serverId ?? 0;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(CompositeKey other)
|
||||||
|
=> UserId == other.UserId && ServerId == other.ServerId;
|
||||||
|
public override int GetHashCode()
|
||||||
|
=> unchecked(ServerId.GetHashCode() + UserId.GetHashCode() + 23);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetAvatarUrl(long userId, string avatarId) => avatarId != null ? Endpoints.UserAvatar(userId, avatarId) : null;
|
||||||
|
|
||||||
private ConcurrentDictionary<string, ChannelPermissionsPair> _permissions;
|
private ConcurrentDictionary<long, ChannelPermissionsPair> _permissions;
|
||||||
private ServerPermissions _serverPermissions;
|
private ServerPermissions _serverPermissions;
|
||||||
|
|
||||||
/// <summary> Returns a unique identifier combining this user's id with its server's. </summary>
|
/// <summary> Returns a unique identifier combining this user's id with its server's. </summary>
|
||||||
internal string UniqueId => GetId(Id, _server.Id);
|
internal CompositeKey UniqueId => new CompositeKey(_server.Id ?? 0, Id);
|
||||||
/// <summary> Returns the name of this user on this server. </summary>
|
/// <summary> Returns the name of this user on this server. </summary>
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
/// <summary> Returns a by-name unique identifier separating this user from others with the same name. </summary>
|
/// <summary> Returns a by-name unique identifier separating this user from others with the same name. </summary>
|
||||||
public string Discriminator { get; private set; }
|
public short Discriminator { get; private set; }
|
||||||
/// <summary> Returns the unique identifier for this user's current avatar. </summary>
|
/// <summary> Returns the unique identifier for this user's current avatar. </summary>
|
||||||
public string AvatarId { get; private set; }
|
public string AvatarId { get; private set; }
|
||||||
/// <summary> Returns the URL to this user's current avatar. </summary>
|
/// <summary> Returns the URL to this user's current avatar. </summary>
|
||||||
@@ -47,6 +61,7 @@ namespace Discord
|
|||||||
public bool IsServerDeafened { get; private set; }
|
public bool IsServerDeafened { get; private set; }
|
||||||
public bool IsServerSuppressed { get; private set; }
|
public bool IsServerSuppressed { get; private set; }
|
||||||
public bool IsSpeaking { get; internal set; }
|
public bool IsSpeaking { get; internal set; }
|
||||||
|
public bool IsPrivate => _server.Id == null;
|
||||||
|
|
||||||
public string SessionId { get; private set; }
|
public string SessionId { get; private set; }
|
||||||
public string Token { get; private set; }
|
public string Token { get; private set; }
|
||||||
@@ -79,7 +94,7 @@ namespace Discord
|
|||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Role> Roles => _roles.Select(x => x.Value);
|
public IEnumerable<Role> Roles => _roles.Select(x => x.Value);
|
||||||
private Dictionary<string, Role> _roles;
|
private Dictionary<long, Role> _roles;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all messages this user has sent on this server that are still in cache. </summary>
|
/// <summary> Returns a collection of all messages this user has sent on this server that are still in cache. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
@@ -118,7 +133,7 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal User(DiscordClient client, string id, string serverId)
|
internal User(DiscordClient client, long id, long? serverId)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
{
|
{
|
||||||
_globalUser = new Reference<GlobalUser>(id,
|
_globalUser = new Reference<GlobalUser>(id,
|
||||||
@@ -140,13 +155,13 @@ namespace Discord
|
|||||||
x.CurrentUser = null;
|
x.CurrentUser = null;
|
||||||
});
|
});
|
||||||
_voiceChannel = new Reference<Channel>(x => _client.Channels[x]);
|
_voiceChannel = new Reference<Channel>(x => _client.Channels[x]);
|
||||||
_roles = new Dictionary<string, Role>();
|
_roles = new Dictionary<long, Role>();
|
||||||
|
|
||||||
Status = UserStatus.Offline;
|
Status = UserStatus.Offline;
|
||||||
//_channels = new ConcurrentDictionary<string, Channel>();
|
//_channels = new ConcurrentDictionary<string, Channel>();
|
||||||
if (serverId != null)
|
if (serverId != null)
|
||||||
{
|
{
|
||||||
_permissions = new ConcurrentDictionary<string, ChannelPermissionsPair>();
|
_permissions = new ConcurrentDictionary<long, ChannelPermissionsPair>();
|
||||||
_serverPermissions = new ServerPermissions();
|
_serverPermissions = new ServerPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +184,7 @@ namespace Discord
|
|||||||
if (model.Avatar != null)
|
if (model.Avatar != null)
|
||||||
AvatarId = model.Avatar;
|
AvatarId = model.Avatar;
|
||||||
if (model.Discriminator != null)
|
if (model.Discriminator != null)
|
||||||
Discriminator = model.Discriminator;
|
Discriminator = model.Discriminator.Value;
|
||||||
if (model.Username != null)
|
if (model.Username != null)
|
||||||
Name = model.Username;
|
Name = model.Username;
|
||||||
}
|
}
|
||||||
@@ -243,11 +258,11 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
private void UpdateRoles(IEnumerable<Role> roles)
|
private void UpdateRoles(IEnumerable<Role> roles)
|
||||||
{
|
{
|
||||||
Dictionary<string, Role> newRoles;
|
Dictionary<long, Role> newRoles;
|
||||||
if (roles != null)
|
if (roles != null)
|
||||||
newRoles = roles.ToDictionary(x => x.Id, x => x);
|
newRoles = roles.ToDictionary(x => x.Id, x => x);
|
||||||
else
|
else
|
||||||
newRoles = new Dictionary<string, Role>();
|
newRoles = new Dictionary<long, Role>();
|
||||||
|
|
||||||
if (_server.Id != null)
|
if (_server.Id != null)
|
||||||
{
|
{
|
||||||
@@ -378,6 +393,6 @@ namespace Discord
|
|||||||
|
|
||||||
public override bool Equals(object obj) => obj is User && (obj as User).Id == Id;
|
public override bool Equals(object obj) => obj is User && (obj as User).Id == Id;
|
||||||
public override int GetHashCode() => unchecked(Id.GetHashCode() + 7230);
|
public override int GetHashCode() => unchecked(Id.GetHashCode() + 7230);
|
||||||
public override string ToString() => Name ?? Id;
|
public override string ToString() => Name ?? IdConvert.ToString(Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,20 +128,20 @@ namespace Discord.Net.WebSockets
|
|||||||
QueueMessage(updateStatus);
|
QueueMessage(updateStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendJoinVoice(string serverId, string channelId)
|
public void SendJoinVoice(long serverId, long channelId)
|
||||||
{
|
{
|
||||||
var joinVoice = new JoinVoiceCommand();
|
var joinVoice = new JoinVoiceCommand();
|
||||||
joinVoice.Payload.ServerId = serverId;
|
joinVoice.Payload.ServerId = serverId;
|
||||||
joinVoice.Payload.ChannelId = channelId;
|
joinVoice.Payload.ChannelId = channelId;
|
||||||
QueueMessage(joinVoice);
|
QueueMessage(joinVoice);
|
||||||
}
|
}
|
||||||
public void SendLeaveVoice(string serverId)
|
public void SendLeaveVoice(long serverId)
|
||||||
{
|
{
|
||||||
var leaveVoice = new JoinVoiceCommand();
|
var leaveVoice = new JoinVoiceCommand();
|
||||||
leaveVoice.Payload.ServerId = serverId;
|
leaveVoice.Payload.ServerId = serverId;
|
||||||
QueueMessage(leaveVoice);
|
QueueMessage(leaveVoice);
|
||||||
}
|
}
|
||||||
public void SendGetUsers(string serverId, string query = "", int limit = 0)
|
public void SendGetUsers(long serverId, string query = "", int limit = 0)
|
||||||
{
|
{
|
||||||
var getOfflineUsers = new GetUsersCommand();
|
var getOfflineUsers = new GetUsersCommand();
|
||||||
getOfflineUsers.Payload.ServerId = serverId;
|
getOfflineUsers.Payload.ServerId = serverId;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ namespace Discord.Net.WebSockets
|
|||||||
{
|
{
|
||||||
internal sealed class IsTalkingEventArgs : EventArgs
|
internal sealed class IsTalkingEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public readonly string UserId;
|
public readonly long UserId;
|
||||||
public readonly bool IsSpeaking;
|
public readonly bool IsSpeaking;
|
||||||
internal IsTalkingEventArgs(string userId, bool isTalking)
|
internal IsTalkingEventArgs(long userId, bool isTalking)
|
||||||
{
|
{
|
||||||
UserId = userId;
|
UserId = userId;
|
||||||
IsSpeaking = isTalking;
|
IsSpeaking = isTalking;
|
||||||
@@ -16,14 +16,14 @@ namespace Discord.Net.WebSockets
|
|||||||
internal partial class VoiceWebSocket
|
internal partial class VoiceWebSocket
|
||||||
{
|
{
|
||||||
public event EventHandler<IsTalkingEventArgs> IsSpeaking;
|
public event EventHandler<IsTalkingEventArgs> IsSpeaking;
|
||||||
private void RaiseIsSpeaking(string userId, bool isSpeaking)
|
private void RaiseIsSpeaking(long userId, bool isSpeaking)
|
||||||
{
|
{
|
||||||
if (IsSpeaking != null)
|
if (IsSpeaking != null)
|
||||||
IsSpeaking(this, new IsTalkingEventArgs(userId, isSpeaking));
|
IsSpeaking(this, new IsTalkingEventArgs(userId, isSpeaking));
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<VoicePacketEventArgs> OnPacket;
|
public event EventHandler<VoicePacketEventArgs> OnPacket;
|
||||||
internal void RaiseOnPacket(string userId, string channelId, byte[] buffer, int offset, int count)
|
internal void RaiseOnPacket(long userId, long channelId, byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (OnPacket != null)
|
if (OnPacket != null)
|
||||||
OnPacket(this, new VoicePacketEventArgs(userId, channelId, buffer, offset, count));
|
OnPacket(this, new VoicePacketEventArgs(userId, channelId, buffer, offset, count));
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Discord.Net.WebSockets
|
|||||||
private OpusEncoder _encoder;
|
private OpusEncoder _encoder;
|
||||||
private readonly ConcurrentDictionary<uint, OpusDecoder> _decoders;
|
private readonly ConcurrentDictionary<uint, OpusDecoder> _decoders;
|
||||||
private uint _ssrc;
|
private uint _ssrc;
|
||||||
private ConcurrentDictionary<uint, string> _ssrcMapping;
|
private ConcurrentDictionary<uint, long> _ssrcMapping;
|
||||||
|
|
||||||
private VoiceBuffer _sendBuffer;
|
private VoiceBuffer _sendBuffer;
|
||||||
private UdpClient _udp;
|
private UdpClient _udp;
|
||||||
@@ -34,12 +34,13 @@ namespace Discord.Net.WebSockets
|
|||||||
private bool _isEncrypted;
|
private bool _isEncrypted;
|
||||||
private byte[] _secretKey, _encodingBuffer;
|
private byte[] _secretKey, _encodingBuffer;
|
||||||
private ushort _sequence;
|
private ushort _sequence;
|
||||||
private string _serverId, _channelId, _userId, _sessionId, _token, _encryptionMode;
|
private long? _serverId, _channelId, _userId;
|
||||||
|
private string _sessionId, _token, _encryptionMode;
|
||||||
|
|
||||||
private Thread _sendThread, _receiveThread;
|
private Thread _sendThread, _receiveThread;
|
||||||
|
|
||||||
public string CurrentServerId => _serverId;
|
public long? CurrentServerId => _serverId;
|
||||||
public string CurrentChannelId => _channelId;
|
public long? CurrentChannelId => _channelId;
|
||||||
public VoiceBuffer OutputBuffer => _sendBuffer;
|
public VoiceBuffer OutputBuffer => _sendBuffer;
|
||||||
|
|
||||||
public VoiceWebSocket(DiscordWSClient client)
|
public VoiceWebSocket(DiscordWSClient client)
|
||||||
@@ -49,19 +50,19 @@ namespace Discord.Net.WebSockets
|
|||||||
_decoders = new ConcurrentDictionary<uint, OpusDecoder>();
|
_decoders = new ConcurrentDictionary<uint, OpusDecoder>();
|
||||||
_targetAudioBufferLength = client.Config.VoiceBufferLength / 20; //20 ms frames
|
_targetAudioBufferLength = client.Config.VoiceBufferLength / 20; //20 ms frames
|
||||||
_encodingBuffer = new byte[MaxOpusSize];
|
_encodingBuffer = new byte[MaxOpusSize];
|
||||||
_ssrcMapping = new ConcurrentDictionary<uint, string>();
|
_ssrcMapping = new ConcurrentDictionary<uint, long>();
|
||||||
_encoder = new OpusEncoder(48000, 1, 20, Opus.Application.Audio);
|
_encoder = new OpusEncoder(48000, 1, 20, Opus.Application.Audio);
|
||||||
_sendBuffer = new VoiceBuffer((int)Math.Ceiling(client.Config.VoiceBufferLength / (double)_encoder.FrameLength), _encoder.FrameSize);
|
_sendBuffer = new VoiceBuffer((int)Math.Ceiling(client.Config.VoiceBufferLength / (double)_encoder.FrameLength), _encoder.FrameSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SetChannel(string serverId, string channelId)
|
public Task SetChannel(long serverId, long channelId)
|
||||||
{
|
{
|
||||||
_serverId = serverId;
|
_serverId = serverId;
|
||||||
_channelId = channelId;
|
_channelId = channelId;
|
||||||
|
|
||||||
return base.BeginConnect();
|
return base.BeginConnect();
|
||||||
}
|
}
|
||||||
public async Task Login(string userId, string sessionId, string token, CancellationToken cancelToken)
|
public async Task Login(long userId, string sessionId, string token, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
if ((WebSocketState)_state == WebSocketState.Connected)
|
if ((WebSocketState)_state == WebSocketState.Connected)
|
||||||
{
|
{
|
||||||
@@ -108,10 +109,10 @@ namespace Discord.Net.WebSockets
|
|||||||
_udp = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
|
_udp = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
|
||||||
|
|
||||||
VoiceLoginCommand msg = new VoiceLoginCommand();
|
VoiceLoginCommand msg = new VoiceLoginCommand();
|
||||||
msg.Payload.ServerId = _serverId;
|
msg.Payload.ServerId = _serverId.Value;
|
||||||
msg.Payload.SessionId = _sessionId;
|
msg.Payload.SessionId = _sessionId;
|
||||||
msg.Payload.Token = _token;
|
msg.Payload.Token = _token;
|
||||||
msg.Payload.UserId = _userId;
|
msg.Payload.UserId = _userId.Value;
|
||||||
QueueMessage(msg);
|
QueueMessage(msg);
|
||||||
|
|
||||||
List<Task> tasks = new List<Task>();
|
List<Task> tasks = new List<Task>();
|
||||||
@@ -232,16 +233,9 @@ namespace Discord.Net.WebSockets
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Parse RTP Data
|
//Parse RTP Data
|
||||||
if (packetLength < 12)
|
if (packetLength < 12) return;
|
||||||
return;
|
if (packet[0] != 0x80) return; //Flags
|
||||||
|
if (packet[1] != 0x78) return; //Payload Type
|
||||||
byte flags = packet[0];
|
|
||||||
if (flags != 0x80)
|
|
||||||
return;
|
|
||||||
|
|
||||||
byte payloadType = packet[1];
|
|
||||||
if (payloadType != 0x78)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ushort sequenceNumber = (ushort)((packet[2] << 8) |
|
ushort sequenceNumber = (ushort)((packet[2] << 8) |
|
||||||
packet[3] << 0);
|
packet[3] << 0);
|
||||||
@@ -278,9 +272,9 @@ namespace Discord.Net.WebSockets
|
|||||||
/*if (_logLevel >= LogMessageSeverity.Debug)
|
/*if (_logLevel >= LogMessageSeverity.Debug)
|
||||||
RaiseOnLog(LogMessageSeverity.Debug, $"Received {buffer.Length - 12} bytes.");*/
|
RaiseOnLog(LogMessageSeverity.Debug, $"Received {buffer.Length - 12} bytes.");*/
|
||||||
|
|
||||||
string userId;
|
long userId;
|
||||||
if (_ssrcMapping.TryGetValue(ssrc, out userId))
|
if (_ssrcMapping.TryGetValue(ssrc, out userId))
|
||||||
RaiseOnPacket(userId, _channelId, result, resultOffset, resultLength);
|
RaiseOnPacket(userId, _channelId.Value, result, resultOffset, resultLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,9 +296,9 @@ namespace Discord.Net.WebSockets
|
|||||||
|
|
||||||
byte[] frame = new byte[_encoder.FrameSize];
|
byte[] frame = new byte[_encoder.FrameSize];
|
||||||
byte[] encodedFrame = new byte[MaxOpusSize];
|
byte[] encodedFrame = new byte[MaxOpusSize];
|
||||||
byte[] udpPacket, nonce = null;
|
byte[] voicePacket, pingPacket, nonce = null;
|
||||||
uint timestamp = 0;
|
uint timestamp = 0;
|
||||||
double nextTicks = 0.0;
|
double nextTicks = 0.0, nextPingTicks = 0.0;
|
||||||
double ticksPerMillisecond = Stopwatch.Frequency / 1000.0;
|
double ticksPerMillisecond = Stopwatch.Frequency / 1000.0;
|
||||||
double ticksPerFrame = ticksPerMillisecond * _encoder.FrameLength;
|
double ticksPerFrame = ticksPerMillisecond * _encoder.FrameLength;
|
||||||
double spinLockThreshold = 3 * ticksPerMillisecond;
|
double spinLockThreshold = 3 * ticksPerMillisecond;
|
||||||
@@ -314,38 +308,58 @@ namespace Discord.Net.WebSockets
|
|||||||
if (_isEncrypted)
|
if (_isEncrypted)
|
||||||
{
|
{
|
||||||
nonce = new byte[24];
|
nonce = new byte[24];
|
||||||
udpPacket = new byte[MaxOpusSize + 12 + 16];
|
voicePacket = new byte[MaxOpusSize + 12 + 16];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
udpPacket = new byte[MaxOpusSize + 12];
|
voicePacket = new byte[MaxOpusSize + 12];
|
||||||
|
|
||||||
|
pingPacket = new byte[8];
|
||||||
|
pingPacket[0] = 0x80; //Flags;
|
||||||
|
pingPacket[1] = 0x78; //Payload Type
|
||||||
|
pingPacket[3] = 0x00; //Length
|
||||||
|
pingPacket[4] = 0x01; //Length (1*8 bytes)
|
||||||
|
pingPacket[5] = (byte)((_ssrc >> 24) & 0xFF);
|
||||||
|
pingPacket[6] = (byte)((_ssrc >> 16) & 0xFF);
|
||||||
|
pingPacket[7] = (byte)((_ssrc >> 8) & 0xFF);
|
||||||
|
pingPacket[8] = (byte)((_ssrc >> 0) & 0xFF);
|
||||||
|
if (_isEncrypted)
|
||||||
|
{
|
||||||
|
Buffer.BlockCopy(pingPacket, 0, nonce, 0, 8);
|
||||||
|
int ret = Sodium.Encrypt(pingPacket, 8, encodedFrame, 0, nonce, _secretKey);
|
||||||
|
if (ret != 0)
|
||||||
|
throw new InvalidOperationException("Failed to encrypt ping packet");
|
||||||
|
pingPacket = new byte[ret];
|
||||||
|
Buffer.BlockCopy(encodedFrame, 0, pingPacket, 0, ret);
|
||||||
|
}
|
||||||
|
|
||||||
int rtpPacketLength = 0;
|
int rtpPacketLength = 0;
|
||||||
udpPacket[0] = 0x80; //Flags;
|
voicePacket[0] = 0x80; //Flags;
|
||||||
udpPacket[1] = 0x78; //Payload Type
|
voicePacket[1] = 0xC9; //Payload Type
|
||||||
udpPacket[8] = (byte)((_ssrc >> 24) & 0xFF);
|
voicePacket[8] = (byte)((_ssrc >> 24) & 0xFF);
|
||||||
udpPacket[9] = (byte)((_ssrc >> 16) & 0xFF);
|
voicePacket[9] = (byte)((_ssrc >> 16) & 0xFF);
|
||||||
udpPacket[10] = (byte)((_ssrc >> 8) & 0xFF);
|
voicePacket[10] = (byte)((_ssrc >> 8) & 0xFF);
|
||||||
udpPacket[11] = (byte)((_ssrc >> 0) & 0xFF);
|
voicePacket[11] = (byte)((_ssrc >> 0) & 0xFF);
|
||||||
|
|
||||||
if (_isEncrypted)
|
if (_isEncrypted)
|
||||||
Buffer.BlockCopy(udpPacket, 0, nonce, 0, 12);
|
Buffer.BlockCopy(voicePacket, 0, nonce, 0, 12);
|
||||||
|
|
||||||
while (!cancelToken.IsCancellationRequested)
|
while (!cancelToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
double ticksToNextFrame = nextTicks - sw.ElapsedTicks;
|
double ticksToNextFrame = nextTicks - sw.ElapsedTicks;
|
||||||
if (ticksToNextFrame <= 0.0)
|
if (ticksToNextFrame <= 0.0)
|
||||||
{
|
{
|
||||||
while (sw.ElapsedTicks > nextTicks)
|
long currentTicks = sw.ElapsedTicks;
|
||||||
|
while (currentTicks > nextTicks)
|
||||||
{
|
{
|
||||||
if (_sendBuffer.Pop(frame))
|
if (_sendBuffer.Pop(frame))
|
||||||
{
|
{
|
||||||
ushort sequence = unchecked(_sequence++);
|
ushort sequence = unchecked(_sequence++);
|
||||||
udpPacket[2] = (byte)((sequence >> 8) & 0xFF);
|
voicePacket[2] = (byte)((sequence >> 8) & 0xFF);
|
||||||
udpPacket[3] = (byte)((sequence >> 0) & 0xFF);
|
voicePacket[3] = (byte)((sequence >> 0) & 0xFF);
|
||||||
udpPacket[4] = (byte)((timestamp >> 24) & 0xFF);
|
voicePacket[4] = (byte)((timestamp >> 24) & 0xFF);
|
||||||
udpPacket[5] = (byte)((timestamp >> 16) & 0xFF);
|
voicePacket[5] = (byte)((timestamp >> 16) & 0xFF);
|
||||||
udpPacket[6] = (byte)((timestamp >> 8) & 0xFF);
|
voicePacket[6] = (byte)((timestamp >> 8) & 0xFF);
|
||||||
udpPacket[7] = (byte)((timestamp >> 0) & 0xFF);
|
voicePacket[7] = (byte)((timestamp >> 0) & 0xFF);
|
||||||
|
|
||||||
//Encode
|
//Encode
|
||||||
int encodedLength = _encoder.EncodeFrame(frame, 0, encodedFrame);
|
int encodedLength = _encoder.EncodeFrame(frame, 0, encodedFrame);
|
||||||
@@ -353,23 +367,28 @@ namespace Discord.Net.WebSockets
|
|||||||
//Encrypt
|
//Encrypt
|
||||||
if (_isEncrypted)
|
if (_isEncrypted)
|
||||||
{
|
{
|
||||||
Buffer.BlockCopy(udpPacket, 2, nonce, 2, 6); //Update nonce
|
Buffer.BlockCopy(voicePacket, 2, nonce, 2, 6); //Update nonce
|
||||||
int ret = Sodium.Encrypt(encodedFrame, encodedLength, udpPacket, 12, nonce, _secretKey);
|
int ret = Sodium.Encrypt(encodedFrame, encodedLength, voicePacket, 12, nonce, _secretKey);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
continue;
|
continue;
|
||||||
rtpPacketLength = encodedLength + 12 + 16;
|
rtpPacketLength = encodedLength + 12 + 16;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Buffer.BlockCopy(encodedFrame, 0, udpPacket, 12, encodedLength);
|
Buffer.BlockCopy(encodedFrame, 0, voicePacket, 12, encodedLength);
|
||||||
rtpPacketLength = encodedLength + 12;
|
rtpPacketLength = encodedLength + 12;
|
||||||
}
|
}
|
||||||
_udp.Send(udpPacket, rtpPacketLength);
|
_udp.Send(voicePacket, rtpPacketLength);
|
||||||
}
|
}
|
||||||
timestamp = unchecked(timestamp + samplesPerFrame);
|
timestamp = unchecked(timestamp + samplesPerFrame);
|
||||||
nextTicks += ticksPerFrame;
|
nextTicks += ticksPerFrame;
|
||||||
}
|
}
|
||||||
}
|
if (currentTicks > nextPingTicks)
|
||||||
|
{
|
||||||
|
_udp.Send(pingPacket, pingPacket.Length);
|
||||||
|
nextPingTicks = currentTicks + 5 * Stopwatch.Frequency;
|
||||||
|
}
|
||||||
|
}
|
||||||
//Dont sleep if we need to output audio in the next spinLockThreshold
|
//Dont sleep if we need to output audio in the next spinLockThreshold
|
||||||
else if (ticksToNextFrame > spinLockThreshold)
|
else if (ticksToNextFrame > spinLockThreshold)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user