| @@ -4,7 +4,7 @@ using Newtonsoft.Json; | |||
| namespace Discord.API.Rest | |||
| { | |||
| [JsonObject(MemberSerialization.OptIn)] | |||
| public class CreateChannelRequest : IRestRequest<Channel> | |||
| public class CreateGuildChannelRequest : IRestRequest<Channel> | |||
| { | |||
| string IRestRequest.Method => "POST"; | |||
| string IRestRequest.Endpoint => $"guilds/{GuildId}/channels"; | |||
| @@ -19,7 +19,7 @@ namespace Discord.API.Rest | |||
| [JsonProperty("bitrate")] | |||
| public int Bitrate { get; set; } | |||
| public CreateChannelRequest(ulong guildId) | |||
| public CreateGuildChannelRequest(ulong guildId) | |||
| { | |||
| GuildId = guildId; | |||
| } | |||
| @@ -2,7 +2,7 @@ | |||
| namespace Discord.API.Rest | |||
| { | |||
| public class CreateRoleRequest : IRestRequest<Role> | |||
| public class CreateGuildRoleRequest : IRestRequest<Role> | |||
| { | |||
| string IRestRequest.Method => "POST"; | |||
| string IRestRequest.Endpoint => $"guilds/{GuildId}/roles"; | |||
| @@ -10,7 +10,7 @@ namespace Discord.API.Rest | |||
| public ulong GuildId { get; } | |||
| public CreateRoleRequest(ulong guildId) | |||
| public CreateGuildRoleRequest(ulong guildId) | |||
| { | |||
| GuildId = guildId; | |||
| } | |||
| @@ -27,7 +27,7 @@ namespace Discord.API.Rest | |||
| [JsonProperty("icon"), JsonConverter(typeof(ImageConverter))] | |||
| public Stream Icon { get; set; } | |||
| [JsonProperty("owner_id")] | |||
| public GuildPresence Owner { get; set; } | |||
| public GuildMember Owner { get; set; } | |||
| [JsonProperty("splash"), JsonConverter(typeof(ImageConverter))] | |||
| public Stream Splash { get; set; } | |||
| @@ -4,7 +4,7 @@ using Newtonsoft.Json; | |||
| namespace Discord.API.Rest | |||
| { | |||
| [JsonObject(MemberSerialization.OptIn)] | |||
| public class UpdateMemberRequest : IRestRequest | |||
| public class ModifyGuildMemberRequest : IRestRequest | |||
| { | |||
| string IRestRequest.Method => "PATCH"; | |||
| string IRestRequest.Endpoint => $"guilds/{GuildId}/members/{UserId}"; | |||
| @@ -22,7 +22,7 @@ namespace Discord.API.Rest | |||
| [JsonProperty("channel_id")] | |||
| public ulong? ChannelId { get; set; } | |||
| public UpdateMemberRequest(ulong guildId, ulong userId) | |||
| public ModifyGuildMemberRequest(ulong guildId, ulong userId) | |||
| { | |||
| GuildId = guildId; | |||
| UserId = userId; | |||
| @@ -4,7 +4,7 @@ using Newtonsoft.Json; | |||
| namespace Discord.API.Rest | |||
| { | |||
| [JsonObject(MemberSerialization.OptIn)] | |||
| public class UpdateMessageRequest : IRestRequest<Message> | |||
| public class ModifyMessageRequest : IRestRequest<Message> | |||
| { | |||
| string IRestRequest.Method => "PATCH"; | |||
| string IRestRequest.Endpoint => $"channels/{ChannelId}/messages/{MessageId}"; | |||
| @@ -16,7 +16,7 @@ namespace Discord.API.Rest | |||
| [JsonProperty("content")] | |||
| public string Content { get; set; } = ""; | |||
| public UpdateMessageRequest(ulong channelId, ulong messageId) | |||
| public ModifyMessageRequest(ulong channelId, ulong messageId) | |||
| { | |||
| ChannelId = channelId; | |||
| MessageId = messageId; | |||
| @@ -212,15 +212,13 @@ | |||
| <Compile Include="Entities\Permissions\GuildPermissions.cs" /> | |||
| <Compile Include="Entities\Permissions\Overwrite.cs" /> | |||
| <Compile Include="Entities\Permissions\OverwritePermissions.cs" /> | |||
| <Compile Include="Entities\Presences\GuildPresence.cs" /> | |||
| <Compile Include="Entities\Presences\Presence.cs" /> | |||
| <Compile Include="Entities\Presences\VoiceState.cs" /> | |||
| <Compile Include="Entities\Role.cs" /> | |||
| <Compile Include="Entities\Users\DMUser.cs" /> | |||
| <Compile Include="Entities\Users\GlobalUser.cs" /> | |||
| <Compile Include="Entities\Users\GuildUser.cs" /> | |||
| <Compile Include="Entities\Users\PublicUser.cs" /> | |||
| <Compile Include="Entities\Users\IUser.cs" /> | |||
| <Compile Include="Entities\Users\VoiceState.cs" /> | |||
| <Compile Include="Entities\Role.cs" /> | |||
| <Compile Include="Entities\Users\SelfUser.cs" /> | |||
| <Compile Include="Entities\Users\User.cs" /> | |||
| <Compile Include="Entities\VoiceRegion.cs" /> | |||
| <Compile Include="Enums\ChannelType.cs" /> | |||
| <Compile Include="Enums\ConnectionState.cs" /> | |||
| @@ -49,7 +49,7 @@ namespace Discord | |||
| _connectionLock = new SemaphoreSlim(1, 1); | |||
| _restClientProvider = config.RestClientProvider; | |||
| UserAgent = GetUserAgent(config.AppName, config.AppVersion, config.AppUrl); | |||
| UserAgent = $"DiscordBot ({DiscordConfig.LibUrl}, v{DiscordConfig.LibVersion})"; | |||
| _logManager = new LogManager(config.LogLevel); | |||
| _logManager.Message += (s, e) => Log(this, e); | |||
| @@ -165,18 +165,18 @@ namespace Discord | |||
| result[i] = CreateGuild(response[i]); | |||
| return result.ToImmutable(); | |||
| } | |||
| public virtual async Task<User> GetUser(ulong id) | |||
| public virtual async Task<IUser> GetUser(ulong id) | |||
| { | |||
| var response = await RestClient.Send(new GetUserRequest(id)); | |||
| var user = CreatePublicUser(response); | |||
| var user = CreateGlobalUser(response); | |||
| return user; | |||
| } | |||
| public virtual async Task<User> GetUser(string username, ushort discriminator) | |||
| public virtual async Task<IUser> GetUser(string username, ushort discriminator) | |||
| { | |||
| var response = await RestClient.Send(new QueryUserRequest() { Query = $"{username}#{discriminator}", Limit = 1 }); | |||
| if (response.Length > 0) | |||
| { | |||
| var user = CreatePublicUser(response[0]); | |||
| var user = CreateGlobalUser(response[0]); | |||
| return user; | |||
| } | |||
| return null; | |||
| @@ -265,7 +265,7 @@ namespace Discord | |||
| guild.Update(model); | |||
| return guild; | |||
| } | |||
| internal virtual Message CreateMessage(IMessageChannel channel, User user, API.Message model) | |||
| internal virtual Message CreateMessage(IMessageChannel channel, IUser user, API.Message model) | |||
| { | |||
| var msg = new Message(model.Id, channel, user); | |||
| msg.Update(model); | |||
| @@ -277,33 +277,33 @@ namespace Discord | |||
| role.Update(model); | |||
| return role; | |||
| } | |||
| internal virtual GuildUser CreateBannedUser(Guild guild, API.User model) | |||
| internal virtual DMUser CreateDMUser(DMChannel channel, API.User model) | |||
| { | |||
| var user = new GuildUser(model.Id, guild, null, null); | |||
| var user = new DMUser(CreateGlobalUser(model), channel); | |||
| user.Update(model); | |||
| return user; | |||
| } | |||
| internal virtual DMUser CreateDMUser(DMChannel channel, API.User model) | |||
| internal virtual GuildUser CreateGuildUser(Guild guild, API.GuildMember model) | |||
| { | |||
| var user = new DMUser(model.Id, channel); | |||
| var user = new GuildUser(CreateGlobalUser(model.User), guild); | |||
| user.Update(model); | |||
| return user; | |||
| } | |||
| internal virtual GuildUser CreateGuildUser(Guild guild, GuildPresence presence, VoiceState voiceState, API.GuildMember model) | |||
| internal virtual GuildUser CreateBannedUser(Guild guild, API.User model) | |||
| { | |||
| var user = new GuildUser(model.User.Id, guild, presence, voiceState); | |||
| user.Update(model); | |||
| var user = new GuildUser(CreateGlobalUser(model), guild); | |||
| //user.Update(model); | |||
| return user; | |||
| } | |||
| internal virtual PublicUser CreatePublicUser(API.User model) | |||
| internal virtual SelfUser CreateSelfUser(API.User model) | |||
| { | |||
| var user = new PublicUser(model.Id, this); | |||
| var user = new SelfUser(model.Id, this); | |||
| user.Update(model); | |||
| return user; | |||
| } | |||
| internal virtual SelfUser CreateSelfUser(API.User model) | |||
| internal virtual GlobalUser CreateGlobalUser(API.User model) | |||
| { | |||
| var user = new SelfUser(model.Id, this); | |||
| var user = new GlobalUser(model.Id, this); | |||
| user.Update(model); | |||
| return user; | |||
| } | |||
| @@ -314,6 +314,8 @@ namespace Discord | |||
| return region; | |||
| } | |||
| internal virtual void RemoveUser(GlobalUser user) { } | |||
| protected virtual void Dispose(bool disposing) | |||
| { | |||
| if (!_isDisposed) | |||
| @@ -329,22 +331,6 @@ namespace Discord | |||
| } | |||
| public void Dispose() => Dispose(true); | |||
| private static string GetUserAgent(string appName, string appVersion, string appUrl) | |||
| { | |||
| var sb = new StringBuilder(); | |||
| if (!string.IsNullOrEmpty(appName)) | |||
| { | |||
| sb.Append(appName); | |||
| if (!string.IsNullOrEmpty(appVersion)) | |||
| sb.Append($"/{appVersion}"); | |||
| if (!string.IsNullOrEmpty(appUrl)) | |||
| sb.Append($" ({appUrl})"); | |||
| sb.Append(' '); | |||
| } | |||
| sb.Append($"DiscordBot ({DiscordConfig.LibUrl}, v{DiscordConfig.LibVersion})"); | |||
| return sb.ToString(); | |||
| } | |||
| protected void RaiseEvent(EventHandler eventHandler) | |||
| => eventHandler?.Invoke(this, EventArgs.Empty); | |||
| protected void RaiseEvent<T>(EventHandler<T> eventHandler, T eventArgs) where T : EventArgs | |||
| @@ -21,13 +21,6 @@ namespace Discord | |||
| internal const int MessageQueueInterval = 100; | |||
| internal const int WebSocketQueueInterval = 100; | |||
| /// <summary> Gets or sets name of your application, used in the user agent. </summary> | |||
| public string AppName { get; set; } = null; | |||
| /// <summary> Gets or sets url to your application, used in the user agent. </summary> | |||
| public string AppUrl { get; set; } = null; | |||
| /// <summary> Gets or sets the version of your application, used in the user agent. </summary> | |||
| public string AppVersion { get; set; } = null; | |||
| /// <summary> Gets or sets the minimum log level severity that will be sent to the LogMessage event. </summary> | |||
| public LogSeverity LogLevel { get; set; } = LogSeverity.Info; | |||
| @@ -22,11 +22,9 @@ namespace Discord | |||
| /// <inheritdoc /> | |||
| public string Name => $"@{Recipient.Username}#{Recipient.Discriminator}"; | |||
| /// <inheritdoc /> | |||
| public IEnumerable<User> Users => ImmutableArray.Create<User>(Discord.CurrentUser, Recipient); | |||
| public IEnumerable<IUser> Users => ImmutableArray.Create<IUser>(Discord.CurrentUser, Recipient); | |||
| /// <inheritdoc /> | |||
| ChannelType IChannel.Type => ChannelType.DM; | |||
| /// <inheritdoc /> | |||
| IEnumerable<User> IChannel.Users => Users; | |||
| private readonly MessageManager _messages; | |||
| @@ -45,7 +43,7 @@ namespace Discord | |||
| } | |||
| /// <inheritdoc /> | |||
| public User GetUser(ulong id) | |||
| public IUser GetUser(ulong id) | |||
| { | |||
| if (id == Recipient.Id) | |||
| return Recipient; | |||
| @@ -27,9 +27,9 @@ namespace Discord | |||
| /// <inheritdoc /> | |||
| public DiscordClient Discord => Guild.Discord; | |||
| /// <summary> Gets a collection of all users in this channel. </summary> | |||
| public IEnumerable<GuildUser> Users => _permissions.GetUsers(); | |||
| public IEnumerable<GuildUser> Users => _permissions.GetMembers(); | |||
| /// <inheritdoc /> | |||
| IEnumerable<User> IChannel.Users => _permissions.GetUsers(); | |||
| IEnumerable<IUser> IChannel.Users => _permissions.GetMembers(); | |||
| /// <summary> Gets a collection of permission overwrites for this channel. </summary> | |||
| public IEnumerable<Overwrite> PermissionOverwrites => _permissions.Overwrites; | |||
| @@ -50,13 +50,12 @@ namespace Discord | |||
| } | |||
| /// <summary> Gets a user in this channel with the given id. </summary> | |||
| public GuildUser GetUser(ulong id) | |||
| => _permissions.GetUser(id); | |||
| public GuildUser GetUser(ulong id) => _permissions.GetUser(id); | |||
| /// <inheritdoc /> | |||
| User IChannel.GetUser(ulong id) => GetUser(id); | |||
| IUser IChannel.GetUser(ulong id) => GetUser(id); | |||
| /// <summary> Gets the permission overwrite for a specific user, or null if one does not exist. </summary> | |||
| public OverwritePermissions? GetPermissionOverwrite(GuildUser user) | |||
| public OverwritePermissions? GetPermissionOverwrite(IUser user) | |||
| => _permissions.GetOverwrite(user); | |||
| /// <summary> Gets the permission overwrite for a specific role, or null if one does not exist. </summary> | |||
| public OverwritePermissions? GetPermissionOverwrite(Role role) | |||
| @@ -74,23 +73,23 @@ namespace Discord | |||
| } | |||
| /// <summary> Adds or updates the permission overwrite for the given user. </summary> | |||
| public Task UpdatePermissionOverwrite(GuildUser user, OverwritePermissions permissions) | |||
| public Task UpdatePermissionOverwrite(IUser user, OverwritePermissions permissions) | |||
| => _permissions.AddOrUpdateOverwrite(user, permissions); | |||
| /// <summary> Adds or updates the permission overwrite for the given role. </summary> | |||
| public Task UpdatePermissionOverwrite(Role role, OverwritePermissions permissions) | |||
| => _permissions.AddOrUpdateOverwrite(role, permissions); | |||
| /// <summary> Removes the permission overwrite for the given user, if one exists. </summary> | |||
| public Task RemovePermissionOverwrite(GuildUser user) | |||
| public Task RemovePermissionOverwrite(IUser user) | |||
| => _permissions.RemoveOverwrite(user); | |||
| /// <summary> Removes the permission overwrite for the given role, if one exists. </summary> | |||
| public Task RemovePermissionOverwrite(Role role) | |||
| => _permissions.RemoveOverwrite(role); | |||
| internal ChannelPermissions GetPermissions(GuildUser user) | |||
| internal ChannelPermissions GetPermissions(IUser user) | |||
| => _permissions.GetPermissions(user); | |||
| internal void UpdatePermissions() | |||
| => _permissions.UpdatePermissions(); | |||
| internal void UpdatePermissions(GuildUser user) | |||
| internal void UpdatePermissions(IUser user) | |||
| => _permissions.UpdatePermissions(user); | |||
| /// <summary> Creates a new invite to this channel. </summary> | |||
| @@ -9,9 +9,9 @@ namespace Discord | |||
| /// <summary> Gets the name of this channel. </summary> | |||
| string Name { get; } | |||
| /// <summary> Gets a collection of all users in this channel. </summary> | |||
| IEnumerable<User> Users { get; } | |||
| IEnumerable<IUser> Users { get; } | |||
| /// <summary> Gets a user in this channel with the given id. </summary> | |||
| User GetUser(ulong id); | |||
| IUser GetUser(ulong id); | |||
| } | |||
| } | |||
| @@ -27,9 +27,9 @@ namespace Discord | |||
| private ConcurrentDictionary<ulong, GuildChannel> _channels; | |||
| private ConcurrentDictionary<ulong, Member> _members; | |||
| private ConcurrentDictionary<ulong, GuildPresence> _presences; | |||
| //private ConcurrentDictionary<ulong, GuildPresence> _presences; | |||
| private ConcurrentDictionary<ulong, Role> _roles; | |||
| private ConcurrentDictionary<ulong, VoiceState> _voiceStates; | |||
| //private ConcurrentDictionary<ulong, VoiceState> _voiceStates; | |||
| private ulong _ownerId; | |||
| private ulong? _afkChannelId, _embedChannelId; | |||
| private int _userCount; | |||
| @@ -100,9 +100,9 @@ namespace Discord | |||
| _channels = new ConcurrentDictionary<ulong, GuildChannel>(); | |||
| _members = new ConcurrentDictionary<ulong, Member>(); | |||
| _presences = new ConcurrentDictionary<ulong, GuildPresence>(); | |||
| //_presences = new ConcurrentDictionary<ulong, GuildPresence>(); | |||
| _roles = new ConcurrentDictionary<ulong, Role>(); | |||
| _voiceStates = new ConcurrentDictionary<ulong, VoiceState>(); | |||
| //_voiceStates = new ConcurrentDictionary<ulong, VoiceState>(); | |||
| } | |||
| internal void Update(Model model) | |||
| @@ -207,7 +207,7 @@ namespace Discord | |||
| public GuildUser GetUser(string mention) => GetUser(MentionHelper.GetUserId(mention)); | |||
| private GuildUser GetUser(ulong? id) => id != null ? GetUser(id.Value) : null; | |||
| public async Task<IEnumerable<User>> GetBans() | |||
| public async Task<IEnumerable<IUser>> GetBans() | |||
| { | |||
| var discord = Discord; | |||
| var response = await Discord.RestClient.Send(new GetGuildBansRequest(Id)).ConfigureAwait(false); | |||
| @@ -229,7 +229,7 @@ namespace Discord | |||
| { | |||
| if (name == null) throw new ArgumentNullException(nameof(name)); | |||
| var request = new CreateChannelRequest(Id) { Name = name, Type = ChannelType.Text }; | |||
| var request = new CreateGuildChannelRequest(Id) { Name = name, Type = ChannelType.Text }; | |||
| var response = await Discord.RestClient.Send(request).ConfigureAwait(false); | |||
| return Discord.CreateTextChannel(this, response); | |||
| @@ -238,7 +238,7 @@ namespace Discord | |||
| { | |||
| if (name == null) throw new ArgumentNullException(nameof(name)); | |||
| var request = new CreateChannelRequest(Id) { Name = name, Type = ChannelType.Voice }; | |||
| var request = new CreateGuildChannelRequest(Id) { Name = name, Type = ChannelType.Voice }; | |||
| var response = await Discord.RestClient.Send(request).ConfigureAwait(false); | |||
| return Discord.CreateVoiceChannel(this, response); | |||
| @@ -251,7 +251,7 @@ namespace Discord | |||
| { | |||
| if (name == null) throw new ArgumentNullException(nameof(name)); | |||
| var createRequest = new CreateRoleRequest(Id); | |||
| var createRequest = new CreateGuildRoleRequest(Id); | |||
| var createResponse = await Discord.RestClient.Send(createRequest).ConfigureAwait(false); | |||
| var role = Discord.CreateRole(this, createResponse); | |||
| @@ -347,7 +347,7 @@ namespace Discord | |||
| newPermissions = GuildPermissions.All.RawValue; | |||
| else | |||
| { | |||
| foreach (var role in user.Presence.Roles) | |||
| foreach (var role in user.Roles) | |||
| newPermissions |= role.Permissions.RawValue; | |||
| } | |||
| @@ -11,7 +11,7 @@ namespace Discord | |||
| private static readonly Regex _channelRegex = new Regex(@"<#([0-9]+)>"); | |||
| private static readonly Regex _roleRegex = new Regex(@"@everyone"); | |||
| internal static string Mention(User user) => $"<@{user.Id}>"; | |||
| internal static string Mention(IUser user) => $"<@{user.Id}>"; | |||
| internal static string Mention(IChannel channel) => $"<#{channel.Id}>"; | |||
| internal static string Mention(Role role) => role.IsEveryone ? "@everyone" : ""; | |||
| @@ -29,7 +29,7 @@ namespace Discord | |||
| } | |||
| } | |||
| internal Message Add(Model model, User user) | |||
| internal Message Add(Model model, IUser user) | |||
| => Add(_channel.Discord.CreateMessage(_channel, user, model)); | |||
| private Message Add(Message message) | |||
| { | |||
| @@ -46,7 +46,7 @@ namespace Discord | |||
| UpdatePermissions(); | |||
| } | |||
| public OverwritePermissions? GetOverwrite(GuildUser user) | |||
| public OverwritePermissions? GetOverwrite(IUser user) | |||
| { | |||
| if (user == null) throw new ArgumentNullException(nameof(user)); | |||
| @@ -64,7 +64,7 @@ namespace Discord | |||
| return rule.Permissions; | |||
| return null; | |||
| } | |||
| public Task AddOrUpdateOverwrite(GuildUser user, OverwritePermissions permissions) | |||
| public Task AddOrUpdateOverwrite(IUser user, OverwritePermissions permissions) | |||
| { | |||
| if (user == null) throw new ArgumentNullException(nameof(user)); | |||
| return AddOrUpdateOverwrite(user.Id, permissions); | |||
| @@ -83,7 +83,7 @@ namespace Discord | |||
| }; | |||
| return _channel.Discord.RestClient.Send(request); | |||
| } | |||
| public Task RemoveOverwrite(GuildUser user) | |||
| public Task RemoveOverwrite(IUser user) | |||
| { | |||
| if (user == null) throw new ArgumentNullException(nameof(user)); | |||
| return RemoveOverwrite(user.Id); | |||
| @@ -99,7 +99,7 @@ namespace Discord | |||
| catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||
| } | |||
| public ChannelPermissions GetPermissions(GuildUser user) | |||
| public ChannelPermissions GetPermissions(IUser user) | |||
| { | |||
| if (user == null) throw new ArgumentNullException(nameof(user)); | |||
| @@ -131,7 +131,7 @@ namespace Discord | |||
| } | |||
| } | |||
| } | |||
| public void UpdatePermissions(GuildUser user) | |||
| public void UpdatePermissions(IUser user) | |||
| { | |||
| if (user == null) throw new ArgumentNullException(nameof(user)); | |||
| @@ -147,22 +147,37 @@ namespace Discord | |||
| } | |||
| } | |||
| public ChannelPermissions ResolvePermissions(GuildUser user) | |||
| public ChannelPermissions ResolvePermissions(IUser user) | |||
| { | |||
| var permissions = new ChannelPermissions(); | |||
| ResolvePermissions(user, ref permissions); | |||
| return permissions; | |||
| } | |||
| private ChannelPermissions ResolvePermissions(GuildUser user) | |||
| { | |||
| var permissions = new ChannelPermissions(); | |||
| ResolvePermissions(user, ref permissions); | |||
| return permissions; | |||
| } | |||
| public bool ResolvePermissions(GuildUser user, ref ChannelPermissions permissions) | |||
| public bool ResolvePermissions(IUser user, ref ChannelPermissions permissions) | |||
| { | |||
| if (user == null) throw new ArgumentNullException(nameof(user)); | |||
| GuildUser guildUser = _channel.GetUser(user.Id); | |||
| if (guildUser == null) | |||
| { | |||
| permissions = ChannelPermissions.None; | |||
| return false; | |||
| } | |||
| else | |||
| return ResolvePermissions(user, ref permissions); | |||
| } | |||
| private bool ResolvePermissions(GuildUser user, ref ChannelPermissions permissions) | |||
| { | |||
| uint newPermissions = 0; | |||
| var guild = user.Guild; | |||
| uint mask = ChannelPermissions.All(_channel.Type).RawValue; | |||
| if (user == guild.Owner) | |||
| if (user == user.Guild.Owner) | |||
| newPermissions = mask; //Private messages and owners always have all permissions | |||
| else | |||
| { | |||
| @@ -171,7 +186,7 @@ namespace Discord | |||
| var rules = _rules; | |||
| Overwrite entry; | |||
| var roles = user.Presence.Roles.ToArray(); | |||
| var roles = user.Roles.ToArray(); | |||
| if (roles.Length > 0) | |||
| { | |||
| for (int i = 0; i < roles.Length; i++) | |||
| @@ -228,13 +243,13 @@ namespace Discord | |||
| } | |||
| else if (_channel.Type == ChannelType.Voice) | |||
| { | |||
| if (user.VoiceState?.VoiceChannel == _channel) | |||
| if (user.VoiceChannel == _channel) | |||
| return user; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| public IEnumerable<GuildUser> GetUsers() | |||
| public IEnumerable<GuildUser> GetMembers() | |||
| { | |||
| if (_users != null) | |||
| return _users.Select(x => x.Value.User); | |||
| @@ -247,7 +262,7 @@ namespace Discord | |||
| return users.Where(x => ResolvePermissions(x, ref perms)); | |||
| } | |||
| else if (_channel.Type == ChannelType.Voice) | |||
| return users.Where(x => x.VoiceState?.VoiceChannel == _channel); | |||
| return users.Where(x => x.VoiceChannel == _channel); | |||
| } | |||
| return Enumerable.Empty<GuildUser>(); | |||
| } | |||
| @@ -3,6 +3,7 @@ using Discord.Net; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Linq; | |||
| using System.Net; | |||
| using System.Threading.Tasks; | |||
| using Model = Discord.API.Message; | |||
| @@ -11,27 +12,28 @@ namespace Discord | |||
| { | |||
| public class Message : IEntity<ulong> | |||
| { | |||
| //TODO: Docstrings | |||
| /// <inheritdoc /> | |||
| public ulong Id { get; } | |||
| public IMessageChannel Channel { get; } | |||
| public User User { get; } | |||
| public IUser User { get; } | |||
| public bool IsTTS { get; internal set; } | |||
| public string RawText { get; internal set; } | |||
| public string Text { get; internal set; } | |||
| public DateTime Timestamp { get; internal set; } | |||
| public bool IsTTS { get; private set; } | |||
| public string RawText { get; private set; } | |||
| public string Text { get; private set; } | |||
| public DateTime Timestamp { get; private set; } | |||
| public DateTime? EditedTimestamp { get; private set; } | |||
| public IReadOnlyList<Attachment> Attachments { get; private set; } | |||
| public IReadOnlyList<Embed> Embeds { get; private set; } | |||
| public IReadOnlyList<GuildUser> MentionedUsers { get; private set; } | |||
| public IReadOnlyList<GuildChannel> MentionedChannels { get; private set; } | |||
| public IReadOnlyList<Role> MentionedRoles { get; private set; } | |||
| internal int Nonce { get; set; } | |||
| public DiscordClient Discord => Channel.Discord; | |||
| public bool IsAuthor => false; | |||
| public bool IsAuthor => User.Id == Discord.CurrentUser.Id; | |||
| internal Message(ulong id, IMessageChannel channel, User user) | |||
| internal Message(ulong id, IMessageChannel channel, IUser user) | |||
| { | |||
| Id = id; | |||
| Channel = channel; | |||
| @@ -102,7 +104,28 @@ namespace Discord | |||
| Text = text; | |||
| } | |||
| public bool IsMentioningMe(bool includeRoles = false) => false; | |||
| /// <summary> Returns true if the logged-in user was mentioned. </summary> | |||
| public bool IsMentioningMe(bool includeRoles = false) | |||
| { | |||
| var me = Channel.GetCurrentUser() as GuildUser; | |||
| if (me != null) | |||
| { | |||
| if (includeRoles) | |||
| return MentionedUsers.Contains(me) || MentionedRoles.Any(x => me.HasRole(x)); | |||
| else | |||
| return MentionedUsers.Contains(me); | |||
| } | |||
| return false; | |||
| } | |||
| public async Task Modify(Action<ModifyMessageRequest> func) | |||
| { | |||
| if (func != null) throw new NullReferenceException(nameof(func)); | |||
| var req = new ModifyMessageRequest(Channel.Id, Id); | |||
| func(req); | |||
| await Discord.RestClient.Send(req).ConfigureAwait(false); | |||
| } | |||
| public Task Update() { throw new NotSupportedException(); } //TODO: Not supported yet | |||
| @@ -63,8 +63,8 @@ namespace Discord | |||
| public bool DeafenMembers => PermissionsHelper.GetValue(RawValue, PermissionBit.DeafenMembers); | |||
| /// <summary> If True, a user may move other users between voice channels. </summary> | |||
| public bool MoveMembers => PermissionsHelper.GetValue(RawValue, PermissionBit.MoveMembers); | |||
| /// <summary> If True, a user may use voice activation rather than push-to-talk. </summary> | |||
| public bool UseVoiceActivation => PermissionsHelper.GetValue(RawValue, PermissionBit.UseVoiceActivation); | |||
| /// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary> | |||
| public bool UseVAD => PermissionsHelper.GetValue(RawValue, PermissionBit.UseVAD); | |||
| /// <summary> Creates a new ChannelPermissions with the provided packed value. </summary> | |||
| public ChannelPermissions(uint rawValue) { RawValue = rawValue; } | |||
| @@ -93,7 +93,7 @@ namespace Discord | |||
| PermissionsHelper.SetValue(ref value, muteMembers, PermissionBit.MuteMembers); | |||
| PermissionsHelper.SetValue(ref value, deafenMembers, PermissionBit.DeafenMembers); | |||
| PermissionsHelper.SetValue(ref value, moveMembers, PermissionBit.MoveMembers); | |||
| PermissionsHelper.SetValue(ref value, useVoiceActivation, PermissionBit.UseVoiceActivation); | |||
| PermissionsHelper.SetValue(ref value, useVoiceActivation, PermissionBit.UseVAD); | |||
| RawValue = value; | |||
| } | |||
| @@ -52,8 +52,8 @@ namespace Discord | |||
| public bool DeafenMembers => PermissionsHelper.GetValue(RawValue, PermissionBit.DeafenMembers); | |||
| /// <summary> If True, a user may move other users between voice channels. </summary> | |||
| public bool MoveMembers => PermissionsHelper.GetValue(RawValue, PermissionBit.MoveMembers); | |||
| /// <summary> If True, a user may use voice activation rather than push-to-talk. </summary> | |||
| public bool UseVoiceActivation => PermissionsHelper.GetValue(RawValue, PermissionBit.UseVoiceActivation); | |||
| /// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary> | |||
| public bool UseVAD => PermissionsHelper.GetValue(RawValue, PermissionBit.UseVAD); | |||
| /// <summary> Creates a new GuildPermissions with the provided packed value. </summary> | |||
| public GuildPermissions(uint rawValue) { RawValue = rawValue; } | |||
| @@ -86,7 +86,7 @@ namespace Discord | |||
| PermissionsHelper.SetValue(ref value, muteMembers, PermissionBit.MuteMembers); | |||
| PermissionsHelper.SetValue(ref value, deafenMembers, PermissionBit.DeafenMembers); | |||
| PermissionsHelper.SetValue(ref value, moveMembers, PermissionBit.MoveMembers); | |||
| PermissionsHelper.SetValue(ref value, useVoiceActivation, PermissionBit.UseVoiceActivation); | |||
| PermissionsHelper.SetValue(ref value, useVoiceActivation, PermissionBit.UseVAD); | |||
| RawValue = value; | |||
| } | |||
| @@ -51,8 +51,8 @@ namespace Discord | |||
| public PermValue DeafenMembers => PermissionsHelper.GetValue(AllowValue, DenyValue, PermissionBit.DeafenMembers); | |||
| /// <summary> If True, a user may move other users between voice channels. </summary> | |||
| public PermValue MoveMembers => PermissionsHelper.GetValue(AllowValue, DenyValue, PermissionBit.MoveMembers); | |||
| /// <summary> If True, a user may use voice activation rather than push-to-talk. </summary> | |||
| public PermValue UseVoiceActivation => PermissionsHelper.GetValue(AllowValue, DenyValue, PermissionBit.UseVoiceActivation); | |||
| /// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary> | |||
| public PermValue UseVAD => PermissionsHelper.GetValue(AllowValue, DenyValue, PermissionBit.UseVAD); | |||
| /// <summary> Creates a new OverwritePermissions with the provided allow and deny packed values. </summary> | |||
| public OverwritePermissions(uint allowValue, uint denyValue) | |||
| @@ -83,7 +83,7 @@ namespace Discord | |||
| PermissionsHelper.SetValue(ref allowValue, ref denyValue, muteMembers, PermissionBit.MuteMembers); | |||
| PermissionsHelper.SetValue(ref allowValue, ref denyValue, deafenMembers, PermissionBit.DeafenMembers); | |||
| PermissionsHelper.SetValue(ref allowValue, ref denyValue, moveMembers, PermissionBit.MoveMembers); | |||
| PermissionsHelper.SetValue(ref allowValue, ref denyValue, useVoiceActivation, PermissionBit.UseVoiceActivation); | |||
| PermissionsHelper.SetValue(ref allowValue, ref denyValue, useVoiceActivation, PermissionBit.UseVAD); | |||
| AllowValue = allowValue; | |||
| DenyValue = denyValue; | |||
| @@ -1,33 +0,0 @@ | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Linq; | |||
| using Model = Discord.API.MemberPresence; | |||
| namespace Discord | |||
| { | |||
| public class GuildPresence : Presence | |||
| { | |||
| public Guild Guild { get; } | |||
| public ulong UserId { get; } | |||
| /// <inheritdoc /> | |||
| public IReadOnlyList<Role> Roles { get; private set; } | |||
| internal GuildPresence(ulong userId, Guild guild) | |||
| { | |||
| UserId = userId; | |||
| Guild = guild; | |||
| } | |||
| internal override void Update(Model model) | |||
| { | |||
| base.Update(model); | |||
| Roles = model.Roles.Select(x => Guild.GetRole(x)).ToImmutableArray(); | |||
| } | |||
| public bool HasRole(Role role) => false; | |||
| //TODO: Unsure about these | |||
| /*public Task AddRoles(params Role[] roles) => xxx; | |||
| public Task RemoveRoles(params Role[] roles) => xxx;*/ | |||
| } | |||
| } | |||
| @@ -1,18 +0,0 @@ | |||
| using Model = Discord.API.MemberPresence; | |||
| namespace Discord | |||
| { | |||
| public class Presence | |||
| { | |||
| public string CurrentGame { get; private set; } | |||
| public UserStatus Status { get; private set; } | |||
| internal Presence() { } | |||
| internal virtual void Update(Model model) | |||
| { | |||
| CurrentGame = model.Game?.Name; | |||
| Status = model.Status; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,15 +1,42 @@ | |||
| namespace Discord | |||
| using System; | |||
| using System.Threading.Tasks; | |||
| using Model = Discord.API.User; | |||
| namespace Discord | |||
| { | |||
| public class DMUser : User | |||
| public class DMUser : IUser | |||
| { | |||
| public DMChannel Channel { get; } | |||
| private readonly GlobalUser _user; | |||
| public override DiscordClient Discord => Channel.Discord; | |||
| public DMChannel Channel { get; } | |||
| /// <inheritdoc /> | |||
| public DiscordClient Discord => _user.Discord; | |||
| /// <inheritdoc /> | |||
| public ulong Id => _user.Id; | |||
| /// <inheritdoc /> | |||
| public string Username => _user.Username; | |||
| /// <inheritdoc /> | |||
| public ushort Discriminator => _user.Discriminator; | |||
| /// <inheritdoc /> | |||
| public bool IsBot => _user.IsBot; | |||
| /// <inheritdoc /> | |||
| public string CurrentGame => _user.CurrentGame; | |||
| /// <inheritdoc /> | |||
| public UserStatus Status => _user.Status; | |||
| /// <inheritdoc /> | |||
| public string AvatarUrl => _user.AvatarUrl; | |||
| /// <inheritdoc /> | |||
| public string Mention => _user.Mention; | |||
| internal DMUser(ulong id, DMChannel channel) | |||
| : base(id) | |||
| internal DMUser(GlobalUser user, DMChannel channel) | |||
| { | |||
| _user = user; | |||
| Channel = channel; | |||
| } | |||
| public void Update(Model model) => _user.Update(model); | |||
| public virtual Task Update() { throw new NotSupportedException(); } | |||
| } | |||
| } | |||
| @@ -4,25 +4,29 @@ using Model = Discord.API.User; | |||
| namespace Discord | |||
| { | |||
| public abstract class User : IEntity<ulong> | |||
| public class GlobalUser : IUser, IEntity<ulong> | |||
| { | |||
| private string _avatarId; | |||
| private int _refCount; | |||
| /// <inheritdoc /> | |||
| public ulong Id { get; } | |||
| /// <inheritdoc /> | |||
| public abstract DiscordClient Discord { get; } | |||
| public DiscordClient Discord { get; } | |||
| public string Username { get; private set; } | |||
| public ushort Discriminator { get; private set; } | |||
| public bool IsBot { get; private set; } | |||
| public string CurrentGame { get; private set; } | |||
| public UserStatus Status { get; private set; } | |||
| public string AvatarUrl => CDN.GetUserAvatarUrl(Id, _avatarId); | |||
| public string Mention => MentionHelper.Mention(this); | |||
| internal User(ulong id) | |||
| internal GlobalUser(ulong id, DiscordClient discord) | |||
| { | |||
| Id = id; | |||
| Discord = discord; | |||
| } | |||
| internal virtual void Update(Model model) | |||
| { | |||
| @@ -34,6 +38,18 @@ namespace Discord | |||
| public virtual Task Update() { throw new NotSupportedException(); } | |||
| public async Task<DMChannel> CreateDMChannel() => await Discord.GetOrCreateDMChannel(Id); //TODO: We dont want both this and .Channel to appear on DMUser | |||
| public async Task<DMChannel> CreateDMChannel() => await Discord.GetOrCreateDMChannel(Id); | |||
| internal void Attach(IUser user) | |||
| { | |||
| //Only ever called from the gateway thread | |||
| _refCount++; | |||
| } | |||
| internal void Detach(IUser user) | |||
| { | |||
| //Only ever called from the gateway thread | |||
| if (--_refCount == 0) | |||
| Discord.RemoveUser(this); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,48 +1,81 @@ | |||
| using Discord.API.Rest; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Linq; | |||
| using System.Threading.Tasks; | |||
| using Model = Discord.API.GuildMember; | |||
| namespace Discord | |||
| { | |||
| public class GuildUser : User, IMentionable | |||
| public class GuildUser : IUser | |||
| { | |||
| private readonly GlobalUser _user; | |||
| public Guild Guild { get; } | |||
| public GuildPresence Presence { get; } | |||
| public VoiceState VoiceState { get; } | |||
| /// <inheritdoc /> | |||
| public DateTime JoinedAt { get; private set; } | |||
| public GuildPermissions GuildPermissions { get; internal set; } | |||
| public string CurrentGame { get; private set; } | |||
| /// <inheritdoc /> | |||
| public UserStatus Status { get; private set; } | |||
| public VoiceChannel VoiceChannel { get; private set; } | |||
| public override DiscordClient Discord => Guild.Discord; | |||
| public IEnumerable<TextChannel> TextChannels => Guild.TextChannels.Where(x => GetPermissions(x).ReadMessages); | |||
| /// <inheritdoc /> | |||
| public DiscordClient Discord => _user.Discord; | |||
| /// <inheritdoc /> | |||
| public ulong Id => _user.Id; | |||
| /// <inheritdoc /> | |||
| public string Username => _user.Username; | |||
| /// <inheritdoc /> | |||
| public ushort Discriminator => _user.Discriminator; | |||
| /// <inheritdoc /> | |||
| public bool IsBot => _user.IsBot; | |||
| /// <inheritdoc /> | |||
| public string AvatarUrl => _user.AvatarUrl; | |||
| /// <inheritdoc /> | |||
| public string Mention => _user.Mention; | |||
| internal GuildUser(ulong id, Guild guild, GuildPresence presence, VoiceState voiceState) | |||
| : base(id) | |||
| /// <inheritdoc /> | |||
| public IReadOnlyList<Role> Roles { get; private set; } | |||
| internal GuildUser(GlobalUser user, Guild guild) | |||
| { | |||
| _user = user; | |||
| Guild = guild; | |||
| Presence = presence; | |||
| VoiceState = voiceState; | |||
| } | |||
| internal void Update(Model model) | |||
| { | |||
| base.Update(model.User); | |||
| JoinedAt = model.JoinedAt.Value; | |||
| Roles = model.Roles.Select(x => Guild.GetRole(x)).ToImmutableArray(); | |||
| } | |||
| public bool HasRole(Role role) => false; //TODO: Implement | |||
| public Task Kick() => Discord.RestClient.Send(new RemoveGuildMemberRequest(Guild.Id, Id)); | |||
| public Task Ban(int pruneDays = 0) => Discord.RestClient.Send(new CreateGuildBanRequest(Guild.Id, Id) { PruneDays = pruneDays }); | |||
| public Task Unban() => Discord.RestClient.Send(new RemoveGuildBanRequest(Guild.Id, Id)); | |||
| /// <inheritdoc /> | |||
| public DateTime JoinedAt { get; private set; } | |||
| public GuildPermissions GuildPermissions { get; internal set; } | |||
| public Task<DMChannel> CreateDMChannel() => _user.CreateDMChannel(); | |||
| /// <inheritdoc /> | |||
| public Task Update() { throw new NotSupportedException(); } //TODO: Not supported | |||
| public ChannelPermissions GetPermissions(GuildChannel channel) | |||
| { | |||
| if (channel == null) throw new ArgumentNullException(nameof(channel)); | |||
| return channel.GetPermissions(this); | |||
| } | |||
| /// <inheritdoc /> | |||
| public override Task Update() { throw new NotSupportedException(); } //TODO: Not supported yet | |||
| public Task Kick() => Discord.RestClient.Send(new RemoveGuildMemberRequest(Guild.Id, Id)); | |||
| public Task Ban(int pruneDays = 0) => Discord.RestClient.Send(new CreateGuildBanRequest(Guild.Id, Id) { PruneDays = pruneDays }); | |||
| public Task Unban() => Discord.RestClient.Send(new RemoveGuildBanRequest(Guild.Id, Id)); | |||
| public async Task Modify(Action<ModifyGuildMemberRequest> func) | |||
| { | |||
| if (func != null) throw new NullReferenceException(nameof(func)); | |||
| var req = new ModifyGuildMemberRequest(Guild.Id, Id); | |||
| func(req); | |||
| await Discord.RestClient.Send(req).ConfigureAwait(false); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| namespace Discord | |||
| { | |||
| public interface IUser : IEntity<ulong> | |||
| { | |||
| string Username { get; } | |||
| ushort Discriminator { get; } | |||
| bool IsBot { get; } | |||
| string AvatarUrl { get; } | |||
| string Mention { get; } | |||
| string CurrentGame { get; } | |||
| UserStatus Status { get; } | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| namespace Discord | |||
| { | |||
| public class PublicUser : User | |||
| { | |||
| public override DiscordClient Discord { get; } | |||
| internal PublicUser(ulong id, DiscordClient discord) | |||
| : base(id) | |||
| { | |||
| Discord = discord; | |||
| } | |||
| } | |||
| } | |||
| @@ -2,17 +2,14 @@ | |||
| namespace Discord | |||
| { | |||
| public class SelfUser : User | |||
| public class SelfUser : GlobalUser | |||
| { | |||
| public override DiscordClient Discord { get; } | |||
| public string Email { get; private set; } | |||
| public bool IsVerified { get; private set; } | |||
| internal SelfUser(ulong id, DiscordClient discord) | |||
| : base(id) | |||
| : base(id, discord) | |||
| { | |||
| Discord = discord; | |||
| } | |||
| internal override void Update(Model model) | |||
| @@ -1,8 +1,4 @@ | |||
| using Discord.API.Rest; | |||
| using System; | |||
| using System.Collections.Immutable; | |||
| using System.Linq; | |||
| using System.Threading.Tasks; | |||
| /*using System; | |||
| using Model = Discord.API.MemberVoiceState; | |||
| namespace Discord | |||
| @@ -63,4 +59,4 @@ namespace Discord | |||
| _voiceStates &= ~VoiceStates.Suppressed; | |||
| } | |||
| } | |||
| } | |||
| }*/ | |||
| @@ -26,6 +26,6 @@ | |||
| MuteMembers = 22, | |||
| DeafenMembers = 23, | |||
| MoveMembers = 24, | |||
| UseVoiceActivation = 25 | |||
| UseVAD = 25 | |||
| } | |||
| } | |||
| @@ -2,6 +2,7 @@ | |||
| { | |||
| public enum UserStatus | |||
| { | |||
| Unknown, | |||
| Online, | |||
| Idle, | |||
| Offline | |||
| @@ -5,9 +5,9 @@ namespace Discord | |||
| public class TypingEventArgs : EventArgs | |||
| { | |||
| public IMessageChannel Channel { get; } | |||
| public User User { get; } | |||
| public IUser User { get; } | |||
| public TypingEventArgs(IMessageChannel channel, User user) | |||
| public TypingEventArgs(IMessageChannel channel, IUser user) | |||
| { | |||
| Channel = channel; | |||
| User = user; | |||
| @@ -4,9 +4,9 @@ namespace Discord | |||
| { | |||
| public class UserEventArgs : EventArgs | |||
| { | |||
| public User User { get; } | |||
| public IUser User { get; } | |||
| public UserEventArgs(User user) | |||
| public UserEventArgs(IUser user) | |||
| { | |||
| User = user; | |||
| } | |||
| @@ -2,10 +2,10 @@ | |||
| { | |||
| public class UserUpdatedEventArgs : UserEventArgs | |||
| { | |||
| public User Before { get; } | |||
| public User After => User; | |||
| public IUser Before { get; } | |||
| public IUser After => User; | |||
| public UserUpdatedEventArgs(User before, User after) | |||
| public UserUpdatedEventArgs(IUser before, IUser after) | |||
| : base(after) | |||
| { | |||
| Before = before; | |||
| @@ -2,7 +2,7 @@ | |||
| { | |||
| internal static class InternalExtensions | |||
| { | |||
| public static User GetCurrentUser(this IChannel channel) | |||
| public static IUser GetCurrentUser(this IChannel channel) | |||
| { | |||
| switch (channel.Type) | |||
| { | |||
| @@ -197,7 +197,7 @@ namespace Discord | |||
| //{ | |||
| try | |||
| { | |||
| var request = new UpdateMessageRequest(msg.Channel.Id, msg.Id) | |||
| var request = new ModifyMessageRequest(msg.Channel.Id, msg.Id) | |||
| { | |||
| Content = item.NewText | |||
| }; | |||
| @@ -242,7 +242,7 @@ namespace Discord.Tests | |||
| "MessageUpdated event never received", | |||
| async () => await message.Modify(x => | |||
| { | |||
| x.Text = text + " updated"; | |||
| x.Content = text + " updated"; | |||
| }), | |||
| x => _targetBot.MessageUpdated += x, | |||
| x => _targetBot.MessageUpdated -= x, | |||
| @@ -293,7 +293,11 @@ namespace Discord.Tests | |||
| var user = _testGuild.GetUser(_targetBot.CurrentUser.Id); | |||
| AssertEvent<UserUpdatedEventArgs>( | |||
| "UserUpdated never fired", | |||
| async () => await user.Modify(true, true, null, null), | |||
| async () => await user.Modify(x => | |||
| { | |||
| x.Deaf = true; | |||
| x.Mute = true; | |||
| }), | |||
| x => _targetBot.UserUpdated += x, | |||
| x => _targetBot.UserUpdated -= x); | |||
| } | |||
| @@ -319,7 +323,7 @@ namespace Discord.Tests | |||
| x => _observerBot.UserUpdated -= x, | |||
| (s, e) => e.After.Status == UserStatus.Idle); | |||
| } | |||
| private async Task SetStatus(DiscordClient _client, UserStatus status) | |||
| private Task SetStatus(DiscordClient _client, UserStatus status) | |||
| { | |||
| throw new NotImplementedException(); | |||
| /*_client.SetStatus(status); | |||
| @@ -336,7 +340,7 @@ namespace Discord.Tests | |||
| (s, e) => _targetBot.CurrentUser.CurrentGame == "test game"); | |||
| } | |||
| private async Task SetGame(DiscordClient _client, string game) | |||
| private Task SetGame(DiscordClient _client, string game) | |||
| { | |||
| throw new NotImplementedException(); | |||
| //_client.SetGame(game); | |||