Added remaining gateway events, added IAudioChannel, added CacheModes
This commit is contained in:
8
src/Discord.Net.Core/Entities/CacheMode.cs
Normal file
8
src/Discord.Net.Core/Entities/CacheMode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum CacheMode
|
||||
{
|
||||
AllowDownload,
|
||||
CacheOnly
|
||||
}
|
||||
}
|
||||
6
src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs
Normal file
6
src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Discord
|
||||
{
|
||||
public interface IAudioChannel
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,10 @@ namespace Discord
|
||||
{
|
||||
public interface IChannel : ISnowflakeEntity
|
||||
{
|
||||
IReadOnlyCollection<IUser> CachedUsers { get; }
|
||||
|
||||
/// <summary> Gets a collection of all users in this channel. </summary>
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync();
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload);
|
||||
|
||||
/// <summary> Gets a user in this channel with the provided id.</summary>
|
||||
Task<IUser> GetUserAsync(ulong id);
|
||||
IUser GetCachedUser(ulong id);
|
||||
Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public interface IGroupChannel : IMessageChannel, IPrivateChannel
|
||||
public interface IGroupChannel : IMessageChannel, IPrivateChannel, IAudioChannel
|
||||
{
|
||||
///// <summary> Adds a user to this group. </summary>
|
||||
//Task AddUserAsync(IUser user);
|
||||
|
||||
//new IReadOnlyCollection<IGroupUser> CachedUsers { get; }
|
||||
|
||||
/// <summary> Leaves this group. </summary>
|
||||
Task LeaveAsync();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@ namespace Discord
|
||||
|
||||
/// <summary> Gets the id of the guild this channel is a member of. </summary>
|
||||
ulong GuildId { get; }
|
||||
new IReadOnlyCollection<IGuildUser> CachedUsers { get; }
|
||||
/// <summary> Gets a collection of permission overwrites for this channel. </summary>
|
||||
IReadOnlyCollection<Overwrite> PermissionOverwrites { get; }
|
||||
|
||||
/// <summary> Creates a new invite to this channel. </summary>
|
||||
/// <param name="maxAge"> The time (in seconds) until the invite expires. Set to null to never expire. </param>
|
||||
@@ -23,9 +24,6 @@ namespace Discord
|
||||
Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 1800, int? maxUses = default(int?), bool isTemporary = false);
|
||||
/// <summary> Returns a collection of all invites to this channel. </summary>
|
||||
Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync();
|
||||
|
||||
/// <summary> Gets a collection of permission overwrites for this channel. </summary>
|
||||
IReadOnlyCollection<Overwrite> PermissionOverwrites { get; }
|
||||
|
||||
/// <summary> Modifies this guild channel. </summary>
|
||||
Task ModifyAsync(Action<ModifyGuildChannelParams> func);
|
||||
@@ -44,9 +42,8 @@ namespace Discord
|
||||
Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions);
|
||||
|
||||
/// <summary> Gets a collection of all users in this channel. </summary>
|
||||
new IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync();
|
||||
new IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Gets a user in this channel with the provided id.</summary>
|
||||
new Task<IGuildUser> GetUserAsync(ulong id);
|
||||
new IGuildUser GetCachedUser(ulong id);
|
||||
new Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload);
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,6 @@ namespace Discord
|
||||
{
|
||||
public interface IMessageChannel : IChannel
|
||||
{
|
||||
/// <summary> Gets all messages in this channel's cache. </summary>
|
||||
IReadOnlyCollection<IMessage> CachedMessages { get; }
|
||||
|
||||
/// <summary> Sends a message to this message channel. </summary>
|
||||
Task<IUserMessage> SendMessageAsync(string text, bool isTTS = false);
|
||||
/// <summary> Sends a file to this text channel, with an optional caption. </summary>
|
||||
@@ -18,13 +15,11 @@ namespace Discord
|
||||
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false);
|
||||
|
||||
/// <summary> Gets a message from this message channel with the given id, or null if not found. </summary>
|
||||
Task<IMessage> GetMessageAsync(ulong id);
|
||||
/// <summary> Gets the message from this channel's cache with the given id, or null if not found. </summary>
|
||||
IMessage GetCachedMessage(ulong id);
|
||||
Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Gets the last N messages from this message channel. </summary>
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Gets a collection of messages in this channel. </summary>
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Gets a collection of pinned messages in this channel. </summary>
|
||||
Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync();
|
||||
/// <summary> Bulk deletes multiple messages. </summary>
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public interface IVoiceChannel : IGuildChannel
|
||||
public interface IVoiceChannel : IGuildChannel, IAudioChannel
|
||||
{
|
||||
/// <summary> Gets the bitrate, in bits per second, clients in this voice channel are requested to use. </summary>
|
||||
int Bitrate { get; }
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
//using Discord.Rest;
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.Ban;
|
||||
|
||||
namespace Discord
|
||||
namespace Discord
|
||||
{
|
||||
|
||||
public interface IBan
|
||||
{
|
||||
IUser User { get; }
|
||||
|
||||
@@ -41,7 +41,6 @@ namespace Discord
|
||||
ulong OwnerId { get; }
|
||||
/// <summary> Gets the id of the region hosting this guild's voice channels. </summary>
|
||||
string VoiceRegionId { get; }
|
||||
|
||||
/// <summary> Gets the IAudioClient currently associated with this guild. </summary>
|
||||
IAudioClient AudioClient { get; }
|
||||
/// <summary> Gets the built-in role containing all users in this guild. </summary>
|
||||
@@ -52,7 +51,6 @@ namespace Discord
|
||||
IReadOnlyCollection<string> Features { get; }
|
||||
/// <summary> Gets a collection of all roles in this guild. </summary>
|
||||
IReadOnlyCollection<IRole> Roles { get; }
|
||||
IReadOnlyCollection<IGuildUser> CachedUsers { get; }
|
||||
|
||||
/// <summary> Modifies this guild. </summary>
|
||||
Task ModifyAsync(Action<ModifyGuildParams> func);
|
||||
@@ -77,10 +75,9 @@ namespace Discord
|
||||
Task RemoveBanAsync(ulong userId);
|
||||
|
||||
/// <summary> Gets a collection of all channels in this guild. </summary>
|
||||
Task<IReadOnlyCollection<IGuildChannel>> GetChannelsAsync();
|
||||
Task<IReadOnlyCollection<IGuildChannel>> GetChannelsAsync(CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Gets the channel in this guild with the provided id, or null if not found. </summary>
|
||||
Task<IGuildChannel> GetChannelAsync(ulong id);
|
||||
IGuildChannel GetCachedChannel(ulong id);
|
||||
Task<IGuildChannel> GetChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Creates a new text channel. </summary>
|
||||
Task<ITextChannel> CreateTextChannelAsync(string name);
|
||||
/// <summary> Creates a new voice channel. </summary>
|
||||
@@ -98,12 +95,11 @@ namespace Discord
|
||||
Task<IRole> CreateRoleAsync(string name, GuildPermissions? permissions = null, Color? color = null, bool isHoisted = false);
|
||||
|
||||
/// <summary> Gets a collection of all users in this guild. </summary>
|
||||
Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync();
|
||||
Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload); //TODO: shouldnt this be paged?
|
||||
/// <summary> Gets the user in this guild with the provided id, or null if not found. </summary>
|
||||
Task<IGuildUser> GetUserAsync(ulong id);
|
||||
IGuildUser GetCachedUser(ulong id);
|
||||
Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Gets the current user for this guild. </summary>
|
||||
Task<IGuildUser> GetCurrentUserAsync();
|
||||
Task<IGuildUser> GetCurrentUserAsync(CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Downloads all users for this guild if the current list is incomplete. </summary>
|
||||
Task DownloadUsersAsync();
|
||||
/// <summary> Removes all users from this guild if they have not logged on in a provided number of days or, if simulate is true, returns the number of users that would be removed. </summary>
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace Discord
|
||||
/// <summary> Gets the username for this user. </summary>
|
||||
string Username { get; }
|
||||
|
||||
/// <summary> Returns a private message channel to this user, returning null if one does not exist or is not cached. </summary>
|
||||
IDMChannel GetCachedDMChannel();
|
||||
/// <summary> Returns a private message channel to this user, creating one if it does not already exist. </summary>
|
||||
Task<IDMChannel> GetDMChannelAsync(CacheMode mode = CacheMode.AllowDownload);
|
||||
/// <summary> Returns a private message channel to this user, creating one if it does not already exist. </summary>
|
||||
Task<IDMChannel> CreateDMChannelAsync();
|
||||
}
|
||||
|
||||
@@ -5,10 +5,18 @@ namespace Discord
|
||||
{
|
||||
internal static class TaskCompletionSourceExtensions
|
||||
{
|
||||
public static Task SetResultAsync<T>(this TaskCompletionSource<T> source, T result)
|
||||
=> Task.Run(() => source.SetResult(result));
|
||||
public static Task<bool> TrySetResultAsync<T>(this TaskCompletionSource<T> source, T result)
|
||||
=> Task.Run(() => source.TrySetResult(result));
|
||||
|
||||
public static Task SetExceptionAsync<T>(this TaskCompletionSource<T> source, Exception ex)
|
||||
=> Task.Run(() => source.SetException(ex));
|
||||
public static Task<bool> TrySetExceptionAsync<T>(this TaskCompletionSource<T> source, Exception ex)
|
||||
=> Task.Run(() => source.TrySetException(ex));
|
||||
|
||||
public static Task SetCanceledAsync<T>(this TaskCompletionSource<T> source)
|
||||
=> Task.Run(() => source.SetCanceled());
|
||||
public static Task<bool> TrySetCanceledAsync<T>(this TaskCompletionSource<T> source)
|
||||
=> Task.Run(() => source.TrySetCanceled());
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
internal bool IgnoreState { get; set; }
|
||||
|
||||
public static RequestOptions CreateOrClone(RequestOptions options)
|
||||
internal static RequestOptions CreateOrClone(RequestOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
return new RequestOptions();
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace Discord
|
||||
{
|
||||
//Based on https://github.com/dotnet/corefx/blob/master/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs
|
||||
//Copyright (c) .NET Foundation and Contributors
|
||||
public static class ConcurrentHashSet
|
||||
{
|
||||
public static int DefaultConcurrencyLevel => PlatformHelper.ProcessorCount;
|
||||
}
|
||||
|
||||
[DebuggerDisplay("Count = {Count}")]
|
||||
internal class ConcurrentHashSet<T> : IReadOnlyCollection<T>
|
||||
{
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Discord.Extensions
|
||||
{
|
||||
internal static class Permissions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PermValue GetValue(ulong allow, ulong deny, ChannelPermission bit)
|
||||
=> GetValue(allow, deny, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PermValue GetValue(ulong allow, ulong deny, GuildPermission bit)
|
||||
=> GetValue(allow, deny, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PermValue GetValue(ulong allow, ulong deny, byte bit)
|
||||
{
|
||||
if (HasBit(allow, bit))
|
||||
return PermValue.Allow;
|
||||
else if (HasBit(deny, bit))
|
||||
return PermValue.Deny;
|
||||
else
|
||||
return PermValue.Inherit;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool GetValue(ulong value, ChannelPermission bit)
|
||||
=> GetValue(value, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool GetValue(ulong value, GuildPermission bit)
|
||||
=> GetValue(value, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool GetValue(ulong value, byte bit) => HasBit(value, bit);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SetValue(ref ulong rawValue, bool? value, ChannelPermission bit)
|
||||
=> SetValue(ref rawValue, value, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SetValue(ref ulong rawValue, bool? value, GuildPermission bit)
|
||||
=> SetValue(ref rawValue, value, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SetValue(ref ulong rawValue, bool? value, byte bit)
|
||||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
if (value == true)
|
||||
SetBit(ref rawValue, bit);
|
||||
else
|
||||
UnsetBit(ref rawValue, bit);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, ChannelPermission bit)
|
||||
=> SetValue(ref allow, ref deny, value, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, GuildPermission bit)
|
||||
=> SetValue(ref allow, ref deny, value, (byte)bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, byte bit)
|
||||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case PermValue.Allow:
|
||||
SetBit(ref allow, bit);
|
||||
UnsetBit(ref deny, bit);
|
||||
break;
|
||||
case PermValue.Deny:
|
||||
UnsetBit(ref allow, bit);
|
||||
SetBit(ref deny, bit);
|
||||
break;
|
||||
default:
|
||||
UnsetBit(ref allow, bit);
|
||||
UnsetBit(ref deny, bit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool HasBit(ulong value, byte bit) => (value & (1U << bit)) != 0;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SetBit(ref ulong value, byte bit) => value |= (1U << bit);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void UnsetBit(ref ulong value, byte bit) => value &= ~(1U << bit);
|
||||
|
||||
public static ulong ResolveGuild(IGuild guild, IGuildUser user)
|
||||
{
|
||||
ulong resolvedPermissions = 0;
|
||||
|
||||
if (user.Id == guild.OwnerId)
|
||||
resolvedPermissions = GuildPermissions.All.RawValue; //Owners always have all permissions
|
||||
else
|
||||
{
|
||||
foreach (var role in user.RoleIds)
|
||||
resolvedPermissions |= guild.GetRole(role).Permissions.RawValue;
|
||||
if (GetValue(resolvedPermissions, GuildPermission.Administrator))
|
||||
resolvedPermissions = GuildPermissions.All.RawValue; //Administrators always have all permissions
|
||||
}
|
||||
return resolvedPermissions;
|
||||
}
|
||||
|
||||
/*public static ulong ResolveChannel(IGuildUser user, IGuildChannel channel)
|
||||
{
|
||||
return ResolveChannel(user, channel, ResolveGuild(user));
|
||||
}*/
|
||||
public static ulong ResolveChannel(IGuild guild, IGuildChannel channel, IGuildUser user, ulong guildPermissions)
|
||||
{
|
||||
ulong resolvedPermissions = 0;
|
||||
|
||||
ulong mask = ChannelPermissions.All(channel).RawValue;
|
||||
if (/*user.Id == user.Guild.OwnerId || */GetValue(guildPermissions, GuildPermission.Administrator))
|
||||
resolvedPermissions = mask; //Owners and administrators always have all permissions
|
||||
else
|
||||
{
|
||||
//Start with this user's guild permissions
|
||||
resolvedPermissions = guildPermissions;
|
||||
|
||||
OverwritePermissions? perms;
|
||||
var roleIds = user.RoleIds;
|
||||
if (roleIds.Count > 0)
|
||||
{
|
||||
ulong deniedPermissions = 0UL, allowedPermissions = 0UL;
|
||||
foreach (var roleId in roleIds)
|
||||
{
|
||||
perms = channel.GetPermissionOverwrite(guild.GetRole(roleId));
|
||||
if (perms != null)
|
||||
{
|
||||
deniedPermissions |= perms.Value.DenyValue;
|
||||
allowedPermissions |= perms.Value.AllowValue;
|
||||
}
|
||||
}
|
||||
resolvedPermissions = (resolvedPermissions & ~deniedPermissions) | allowedPermissions;
|
||||
}
|
||||
perms = channel.GetPermissionOverwrite(user);
|
||||
if (perms != null)
|
||||
resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;
|
||||
|
||||
//TODO: C#7 Typeswitch candidate
|
||||
var textChannel = channel as ITextChannel;
|
||||
var voiceChannel = channel as IVoiceChannel;
|
||||
if (textChannel != null && !GetValue(resolvedPermissions, ChannelPermission.ReadMessages))
|
||||
resolvedPermissions = 0; //No read permission on a text channel removes all other permissions
|
||||
else if (voiceChannel != null && !GetValue(resolvedPermissions, ChannelPermission.Connect))
|
||||
resolvedPermissions = 0; //No connect permission on a voice channel removes all other permissions
|
||||
resolvedPermissions &= mask; //Ensure we didnt get any permissions this channel doesnt support (from guildPerms, for example)
|
||||
}
|
||||
|
||||
return resolvedPermissions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
@@ -34,7 +35,7 @@ namespace Discord
|
||||
{
|
||||
if (userMention.Id == id)
|
||||
{
|
||||
user = channel?.GetCachedUser(id) as TUser;
|
||||
user = channel?.GetUserAsync(id, CacheMode.CacheOnly).GetAwaiter().GetResult() as TUser;
|
||||
if (user == null) //User not found, fallback to basic mention info
|
||||
user = userMention;
|
||||
break;
|
||||
@@ -136,7 +137,7 @@ namespace Discord
|
||||
return "";
|
||||
case ChannelMentionHandling.Name:
|
||||
IGuildChannel channel = null;
|
||||
channel = guild.GetCachedChannel(id);
|
||||
channel = guild.GetChannelAsync(id, CacheMode.CacheOnly).GetAwaiter().GetResult();
|
||||
if (channel != null)
|
||||
return $"#{channel.Name}";
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user