@@ -82,8 +82,8 @@ | |||
<Compile Include="..\Discord.Net\API\Enums\AvatarImageType.cs"> | |||
<Link>API\Enums\AvatarImageType.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Enums\ChannelTypes.cs"> | |||
<Link>API\Enums\ChannelTypes.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Enums\ChannelType.cs"> | |||
<Link>API\Enums\ChannelType.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Enums\PermissionTarget.cs"> | |||
<Link>API\Enums\PermissionTarget.cs</Link> | |||
@@ -91,6 +91,9 @@ | |||
<Compile Include="..\Discord.Net\API\Enums\Regions.cs"> | |||
<Link>API\Enums\Regions.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Enums\StringEnum.cs"> | |||
<Link>API\Enums\StringEnum.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Enums\UserStatus.cs"> | |||
<Link>API\Enums\UserStatus.cs</Link> | |||
</Compile> | |||
@@ -0,0 +1,28 @@ | |||
namespace Discord | |||
{ | |||
public class ChannelType : StringEnum | |||
{ | |||
/// <summary> A text-only channel. </summary> | |||
public static readonly ChannelType Text = new ChannelType("text"); | |||
/// <summary> A voice-only channel. </summary> | |||
public static readonly ChannelType Voice = new ChannelType("voice"); | |||
private ChannelType(string value) | |||
: base(value) { } | |||
public static ChannelType FromString(string value) | |||
{ | |||
switch (value) | |||
{ | |||
case null: | |||
return null; | |||
case "text": | |||
return ChannelType.Text; | |||
case "voice": | |||
return ChannelType.Voice; | |||
default: | |||
return new ChannelType(value); | |||
} | |||
} | |||
} | |||
} |
@@ -1,10 +0,0 @@ | |||
namespace Discord | |||
{ | |||
public static class ChannelTypes | |||
{ | |||
/// <summary> A text-only channel. </summary> | |||
public const string Text = "text"; | |||
/// <summary> A voice-only channel. </summary> | |||
public const string Voice = "voice"; | |||
} | |||
} |
@@ -1,8 +1,28 @@ | |||
namespace Discord | |||
{ | |||
public static class PermissionTarget | |||
{ | |||
public const string Role = "role"; | |||
public const string Member = "member"; | |||
public class PermissionTarget : StringEnum | |||
{ | |||
/// <summary> A text-only channel. </summary> | |||
public static readonly PermissionTarget Role = new PermissionTarget("role"); | |||
/// <summary> A voice-only channel. </summary> | |||
public static readonly PermissionTarget Member = new PermissionTarget("member"); | |||
private PermissionTarget(string value) | |||
: base(value) { } | |||
public static PermissionTarget FromString(string value) | |||
{ | |||
switch (value) | |||
{ | |||
case null: | |||
return null; | |||
case "role": | |||
return PermissionTarget.Role; | |||
case "member": | |||
return PermissionTarget.Member; | |||
default: | |||
return new PermissionTarget(value); | |||
} | |||
} | |||
} | |||
} |
@@ -1,12 +1,38 @@ | |||
namespace Discord | |||
{ | |||
public static class Regions | |||
public class Region : StringEnum | |||
{ | |||
public const string US_West = "us-west"; | |||
public const string US_East = "us-east"; | |||
public const string Singapore = "singapore"; | |||
public const string London = "london"; | |||
public const string Sydney = "sydney"; | |||
public const string Amsterdam = "amsterdam"; | |||
public static readonly Region USWest = new Region("us-west"); | |||
public static readonly Region USEast = new Region("us-east"); | |||
public static readonly Region Singapore = new Region("singapore"); | |||
public static readonly Region London = new Region("london"); | |||
public static readonly Region Sydney = new Region("sydney"); | |||
public static readonly Region Amsterdam = new Region("amsterdam"); | |||
private Region(string value) | |||
: base(value) { } | |||
public static Region FromString(string value) | |||
{ | |||
switch (value) | |||
{ | |||
case null: | |||
return null; | |||
case "us-west": | |||
return Region.USWest; | |||
case "us-east": | |||
return Region.USEast; | |||
case "singapore": | |||
return Region.Singapore; | |||
case "london": | |||
return Region.London; | |||
case "sydney": | |||
return Region.Sydney; | |||
case "amsterdam": | |||
return Region.Amsterdam; | |||
default: | |||
return new Region(value); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
namespace Discord | |||
{ | |||
public abstract class StringEnum | |||
{ | |||
private string _value; | |||
protected StringEnum(string value) | |||
{ | |||
_value = value; | |||
} | |||
public string Value => _value; | |||
public override string ToString() => _value; | |||
public override bool Equals(object obj) | |||
{ | |||
var enum2 = obj as StringEnum; | |||
if (enum2 == (StringEnum)null) | |||
return false; | |||
else | |||
return _value == enum2._value; | |||
} | |||
public override int GetHashCode() | |||
{ | |||
return _value.GetHashCode(); | |||
} | |||
public static bool operator ==(StringEnum a, StringEnum b) | |||
{ | |||
return a?._value == b?._value; | |||
} | |||
public static bool operator !=(StringEnum a, StringEnum b) | |||
{ | |||
return a?._value != b?._value; | |||
} | |||
public static bool operator ==(StringEnum a, string b) | |||
{ | |||
return a?._value == b; | |||
} | |||
public static bool operator !=(StringEnum a, string b) | |||
{ | |||
return a?._value != b; | |||
} | |||
public static bool operator ==(string a, StringEnum b) | |||
{ | |||
return a == b?._value; | |||
} | |||
public static bool operator !=(string a, StringEnum b) | |||
{ | |||
return a != b?._value; | |||
} | |||
} | |||
} |
@@ -1,12 +1,32 @@ | |||
namespace Discord | |||
{ | |||
public static class UserStatus | |||
public class UserStatus : StringEnum | |||
{ | |||
/// <summary> User is currently online and active. </summary> | |||
public const string Online = "online"; | |||
public static readonly UserStatus Online = new UserStatus("online"); | |||
/// <summary> User is currently online but inactive. </summary> | |||
public const string Idle = "idle"; | |||
public static readonly UserStatus Idle = new UserStatus("idle"); | |||
/// <summary> User is offline. </summary> | |||
public const string Offline = "offline"; | |||
public static readonly UserStatus Offline = new UserStatus("offline"); | |||
private UserStatus(string value) | |||
: base(value) { } | |||
public static UserStatus FromString(string value) | |||
{ | |||
switch (value) | |||
{ | |||
case null: | |||
return null; | |||
case "online": | |||
return UserStatus.Online; | |||
case "idle": | |||
return UserStatus.Idle; | |||
case "offline": | |||
return UserStatus.Offline; | |||
default: | |||
return new UserStatus(value); | |||
} | |||
} | |||
} | |||
} |
@@ -35,8 +35,8 @@ namespace Discord | |||
/// <summary> Bans a user from the provided server. </summary> | |||
public Task Ban(Member member) | |||
{ | |||
CheckReady(); | |||
if (member == null) throw new ArgumentNullException(nameof(member)); | |||
CheckReady(); | |||
return _api.Ban(member.ServerId, member.Id); | |||
} | |||
@@ -44,8 +44,8 @@ namespace Discord | |||
/// <summary> Unbans a user from the provided server. </summary> | |||
public async Task Unban(Member member) | |||
{ | |||
CheckReady(); | |||
if (member == null) throw new ArgumentNullException(nameof(member)); | |||
CheckReady(); | |||
try { await _api.Unban(member.ServerId, member.Id).ConfigureAwait(false); } | |||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||
@@ -56,7 +56,7 @@ namespace Discord | |||
/// <summary> Returns all channels with the specified server and name. </summary> | |||
/// <remarks> Name formats supported: Name and #Name. Search is case-insensitive. </remarks> | |||
public IEnumerable<Channel> FindChannels(Server server, string name, string type = null) | |||
public IEnumerable<Channel> FindChannels(Server server, string name, ChannelType type = null) | |||
{ | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
@@ -74,21 +74,21 @@ namespace Discord | |||
string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); | |||
} | |||
if (type != null) | |||
if (type != (string)null) | |||
result = result.Where(x => x.Type == type); | |||
return result; | |||
} | |||
/// <summary> Creates a new channel with the provided name and type (see ChannelTypes). </summary> | |||
public async Task<Channel> CreateChannel(Server server, string name, string type = ChannelTypes.Text) | |||
/// <summary> Creates a new channel with the provided name and type. </summary> | |||
public async Task<Channel> CreateChannel(Server server, string name, ChannelType type) | |||
{ | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
if (name == null) throw new ArgumentNullException(nameof(name)); | |||
if (type == null) throw new ArgumentNullException(nameof(type)); | |||
if (type == (string)null) throw new ArgumentNullException(nameof(type)); | |||
CheckReady(); | |||
var response = await _api.CreateChannel(server.Id, name, type).ConfigureAwait(false); | |||
var response = await _api.CreateChannel(server.Id, name, type.Value).ConfigureAwait(false); | |||
var channel = _channels.GetOrAdd(response.Id, response.GuildId, response.Recipient?.Id); | |||
channel.Update(response); | |||
return channel; | |||
@@ -153,15 +153,16 @@ namespace Discord | |||
{ | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
if (channels == null) throw new ArgumentNullException(nameof(channels)); | |||
CheckReady(); | |||
return _api.ReorderChannels(server.Id, channels.Select(x => x.Id), after.Position); | |||
} | |||
/// <summary> Destroys the provided channel. </summary> | |||
public async Task<Channel> DestroyChannel(Channel channel) | |||
{ | |||
CheckReady(); | |||
if (channel == null) throw new ArgumentNullException(nameof(channel)); | |||
CheckReady(); | |||
try { await _api.DestroyChannel(channel.Id).ConfigureAwait(false); } | |||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||
@@ -10,8 +10,8 @@ namespace Discord | |||
/// <remarks> Supported formats: inviteCode, xkcdCode, https://discord.gg/inviteCode, https://discord.gg/xkcdCode </remarks> | |||
public async Task<Invite> GetInvite(string inviteIdOrXkcd) | |||
{ | |||
CheckReady(); | |||
if (inviteIdOrXkcd == null) throw new ArgumentNullException(nameof(inviteIdOrXkcd)); | |||
CheckReady(); | |||
//Remove trailing slash | |||
if (inviteIdOrXkcd.Length > 0 && inviteIdOrXkcd[inviteIdOrXkcd.Length - 1] == '/') | |||
@@ -35,6 +35,8 @@ namespace Discord | |||
public Task<Invite> CreateInvite(Server server, int maxAge = 1800, int maxUses = 0, bool tempMembership = false, bool hasXkcd = false) | |||
{ | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
CheckReady(); | |||
return CreateInvite(server.DefaultChannel, maxAge, maxUses, tempMembership, hasXkcd); | |||
} | |||
/// <summary> Creates a new invite to the provided channel. </summary> | |||
@@ -59,8 +61,8 @@ namespace Discord | |||
/// <summary> Deletes the provided invite. </summary> | |||
public async Task DestroyInvite(Invite invite) | |||
{ | |||
CheckReady(); | |||
if (invite == null) throw new ArgumentNullException(nameof(invite)); | |||
CheckReady(); | |||
try { await _api.DeleteInvite(invite.Id).ConfigureAwait(false); } | |||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||
@@ -69,8 +71,8 @@ namespace Discord | |||
/// <summary> Accepts the provided invite. </summary> | |||
public Task AcceptInvite(Invite invite) | |||
{ | |||
CheckReady(); | |||
if (invite == null) throw new ArgumentNullException(nameof(invite)); | |||
CheckReady(); | |||
return _api.AcceptInvite(invite.Id); | |||
} | |||
@@ -190,7 +190,7 @@ namespace Discord | |||
CheckReady(); | |||
if (count == 0) return new Message[0]; | |||
if (channel != null && channel.Type == ChannelTypes.Text) | |||
if (channel != null && channel.Type == ChannelType.Text) | |||
{ | |||
try | |||
{ | |||
@@ -8,20 +8,39 @@ namespace Discord | |||
public partial class DiscordClient | |||
{ | |||
public Task SetChannelUserPermissions(Channel channel, Member member, ChannelPermissions allow = null, ChannelPermissions deny = null) | |||
=> SetChannelPermissions(channel, member?.Id, PermissionTarget.Member, allow, deny); | |||
{ | |||
if (channel == null) throw new ArgumentNullException(nameof(channel)); | |||
if (member == null) throw new ArgumentNullException(nameof(member)); | |||
CheckReady(); | |||
return SetChannelPermissions(channel, member?.Id, PermissionTarget.Member, allow, deny); | |||
} | |||
public Task SetChannelUserPermissions(Channel channel, Member member, DualChannelPermissions permissions = null) | |||
=> SetChannelPermissions(channel, member?.Id, PermissionTarget.Member, permissions?.Allow, permissions?.Deny); | |||
{ | |||
if (channel == null) throw new ArgumentNullException(nameof(channel)); | |||
if (member == null) throw new ArgumentNullException(nameof(member)); | |||
CheckReady(); | |||
return SetChannelPermissions(channel, member?.Id, PermissionTarget.Member, permissions?.Allow, permissions?.Deny); | |||
} | |||
public Task SetChannelRolePermissions(Channel channel, Role role, ChannelPermissions allow = null, ChannelPermissions deny = null) | |||
=> SetChannelPermissions(channel, role?.Id, PermissionTarget.Role, allow, deny); | |||
public Task SetChannelRolePermissions(Channel channel, Role role, DualChannelPermissions permissions = null) | |||
=> SetChannelPermissions(channel, role?.Id, PermissionTarget.Role, permissions?.Allow, permissions?.Deny); | |||
private async Task SetChannelPermissions(Channel channel, string targetId, string targetType, ChannelPermissions allow = null, ChannelPermissions deny = null) | |||
{ | |||
if (channel == null) throw new ArgumentNullException(nameof(channel)); | |||
if (role == null) throw new ArgumentNullException(nameof(role)); | |||
CheckReady(); | |||
return SetChannelPermissions(channel, role?.Id, PermissionTarget.Role, allow, deny); | |||
} | |||
public Task SetChannelRolePermissions(Channel channel, Role role, DualChannelPermissions permissions = null) | |||
{ | |||
if (channel == null) throw new ArgumentNullException(nameof(channel)); | |||
if (targetId == null) throw new ArgumentNullException(nameof(targetId)); | |||
if (targetType == null) throw new ArgumentNullException(nameof(targetType)); | |||
if (role == null) throw new ArgumentNullException(nameof(role)); | |||
CheckReady(); | |||
return SetChannelPermissions(channel, role?.Id, PermissionTarget.Role, permissions?.Allow, permissions?.Deny); | |||
} | |||
private async Task SetChannelPermissions(Channel channel, string targetId, PermissionTarget targetType, ChannelPermissions allow = null, ChannelPermissions deny = null) | |||
{ | |||
uint allowValue = allow?.RawValue ?? 0; | |||
uint denyValue = deny?.RawValue ?? 0; | |||
bool changed = false; | |||
@@ -29,7 +48,7 @@ namespace Discord | |||
var perms = channel.PermissionOverwrites.Where(x => x.TargetType != targetType || x.TargetId != targetId).FirstOrDefault(); | |||
if (allowValue != 0 || denyValue != 0) | |||
{ | |||
await _api.SetChannelPermissions(channel.Id, targetId, targetType, allowValue, denyValue); | |||
await _api.SetChannelPermissions(channel.Id, targetId, targetType.Value, allowValue, denyValue); | |||
if (perms != null) | |||
{ | |||
perms.Allow.SetRawValueInternal(allowValue); | |||
@@ -84,19 +103,19 @@ namespace Discord | |||
return RemoveChannelPermissions(channel, role?.Id, PermissionTarget.Role); | |||
} | |||
private async Task RemoveChannelPermissions(Channel channel, string userOrRoleId, string idType) | |||
private async Task RemoveChannelPermissions(Channel channel, string userOrRoleId, PermissionTarget targetType) | |||
{ | |||
try | |||
{ | |||
var perms = channel.PermissionOverwrites.Where(x => x.TargetType != idType || x.TargetId != userOrRoleId).FirstOrDefault(); | |||
var perms = channel.PermissionOverwrites.Where(x => x.TargetType != targetType || x.TargetId != userOrRoleId).FirstOrDefault(); | |||
await _api.DeleteChannelPermissions(channel.Id, userOrRoleId).ConfigureAwait(false); | |||
if (perms != null) | |||
{ | |||
channel.PermissionOverwrites.Where(x => x.TargetType != idType || x.TargetId != userOrRoleId).ToArray(); | |||
channel.PermissionOverwrites.Where(x => x.TargetType != targetType || x.TargetId != userOrRoleId).ToArray(); | |||
if (idType == PermissionTarget.Role) | |||
if (targetType == PermissionTarget.Role) | |||
channel.InvalidatePermissionsCache(); | |||
else if (idType == PermissionTarget.Member) | |||
else if (targetType == PermissionTarget.Member) | |||
channel.InvalidatePermissionsCache(userOrRoleId); | |||
} | |||
} | |||
@@ -63,13 +63,20 @@ namespace Discord | |||
private readonly Roles _roles; | |||
/// <summary> Returns the role with the specified id, or null if none was found. </summary> | |||
public Role GetRole(string id) => _roles[id]; | |||
public Role GetRole(string id) | |||
{ | |||
if (id == null) throw new ArgumentNullException(nameof(id)); | |||
CheckReady(); | |||
return _roles[id]; | |||
} | |||
/// <summary> Returns all roles with the specified server and name. </summary> | |||
/// <remarks> Name formats supported: Name and @Name. Search is case-insensitive. </remarks> | |||
public IEnumerable<Role> FindRoles(Server server, string name) | |||
{ | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
if (name == null) throw new ArgumentNullException(nameof(name)); | |||
CheckReady(); | |||
if (name.StartsWith("@")) | |||
{ | |||
@@ -83,18 +90,16 @@ namespace Discord | |||
string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); | |||
} | |||
} | |||
/// <summary> Note: due to current API limitations, the created role cannot be returned. </summary> | |||
public Task<Role> CreateRole(Server server, string name) | |||
=> CreateRole(server?.Id, name); | |||
/// <summary> Note: due to current API limitations, the created role cannot be returned. </summary> | |||
public async Task<Role> CreateRole(string serverId, string name) | |||
public async Task<Role> CreateRole(Server server, string name) | |||
{ | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
if (name == null) throw new ArgumentNullException(nameof(name)); | |||
CheckReady(); | |||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||
var response = await _api.CreateRole(serverId).ConfigureAwait(false); | |||
var role = _roles.GetOrAdd(response.Id, serverId); | |||
var response = await _api.CreateRole(server.Id).ConfigureAwait(false); | |||
var role = _roles.GetOrAdd(response.Id, server.Id); | |||
role.Update(response); | |||
await EditRole(role, name: name); | |||
@@ -98,48 +98,43 @@ namespace Discord | |||
public IEnumerable<Server> FindServers(string name) | |||
{ | |||
if (name == null) throw new ArgumentNullException(nameof(name)); | |||
CheckReady(); | |||
return _servers.Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); | |||
} | |||
/// <summary> Creates a new server with the provided name and region (see Regions). </summary> | |||
public async Task<Server> CreateServer(string name, string region) | |||
public async Task<Server> CreateServer(string name, Region region) | |||
{ | |||
CheckReady(); | |||
if (name == null) throw new ArgumentNullException(nameof(name)); | |||
if (region == null) throw new ArgumentNullException(nameof(region)); | |||
if (region == (string)null) throw new ArgumentNullException(nameof(region)); | |||
CheckReady(); | |||
var response = await _api.CreateServer(name, region).ConfigureAwait(false); | |||
var response = await _api.CreateServer(name, region.Value).ConfigureAwait(false); | |||
var server = _servers.GetOrAdd(response.Id); | |||
server.Update(response); | |||
return server; | |||
} | |||
/// <summary> Edits the provided server, changing only non-null attributes. </summary> | |||
public Task EditServer(string serverId, string name = null, string region = null, ImageType iconType = ImageType.Png, byte[] icon = null) | |||
=> EditServer(_servers[serverId], name: name, region: region, iconType: iconType, icon: icon); | |||
/// <summary> Edits the provided server, changing only non-null attributes. </summary> | |||
public async Task EditServer(Server server, string name = null, string region = null, ImageType iconType = ImageType.Png, byte[] icon = null) | |||
public async Task EditServer(Server server, string name = null, Region region = null, ImageType iconType = ImageType.Png, byte[] icon = null) | |||
{ | |||
CheckReady(); | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
CheckReady(); | |||
var response = await _api.EditServer(server.Id, name: name ?? server.Name, region: region, iconType: iconType, icon: icon); | |||
var response = await _api.EditServer(server.Id, name: name ?? server.Name, region: region.Value, iconType: iconType, icon: icon); | |||
server.Update(response); | |||
} | |||
/// <summary> Leaves the provided server, destroying it if you are the owner. </summary> | |||
public Task<Server> LeaveServer(Server server) | |||
=> LeaveServer(server?.Id); | |||
/// <summary> Leaves the provided server, destroying it if you are the owner. </summary> | |||
public async Task<Server> LeaveServer(string serverId) | |||
public async Task<Server> LeaveServer(Server server) | |||
{ | |||
if (server == null) throw new ArgumentNullException(nameof(server)); | |||
CheckReady(); | |||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||
try { await _api.LeaveServer(serverId).ConfigureAwait(false); } | |||
try { await _api.LeaveServer(server.Id).ConfigureAwait(false); } | |||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||
return _servers.TryRemove(serverId); | |||
return _servers.TryRemove(server.Id); | |||
} | |||
} | |||
} |
@@ -62,14 +62,18 @@ namespace Discord | |||
ImageType avatarType = ImageType.Png, byte[] avatar = null) | |||
{ | |||
if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword)); | |||
CheckReady(); | |||
return _api.EditUser(currentPassword: currentPassword, | |||
username: username ?? _currentUser?.Name, email: email ?? _currentUser?.GlobalUser.Email, password: password, | |||
avatarType: avatarType, avatar: avatar); | |||
} | |||
public Task SetStatus(string status) | |||
public Task SetStatus(UserStatus status) | |||
{ | |||
if (status == (string)null) throw new ArgumentNullException(nameof(status)); | |||
CheckReady(); | |||
if (status != UserStatus.Online && status != UserStatus.Idle) | |||
throw new ArgumentException($"Invalid status, must be {UserStatus.Online} or {UserStatus.Idle}"); | |||
_status = status; | |||
@@ -77,6 +81,8 @@ namespace Discord | |||
} | |||
public Task SetGame(int? gameId) | |||
{ | |||
CheckReady(); | |||
_gameId = gameId; | |||
return SendStatus(); | |||
} | |||
@@ -19,7 +19,7 @@ namespace Discord | |||
private readonly ConcurrentDictionary<string, DiscordWSClient> _voiceClients; | |||
private bool _sentInitialLog; | |||
private uint _nextVoiceClientId; | |||
private string _status; | |||
private UserStatus _status; | |||
private int? _gameId; | |||
public new DiscordClientConfig Config => _config as DiscordClientConfig; | |||
@@ -11,12 +11,12 @@ namespace Discord | |||
{ | |||
public sealed class PermissionOverwrite | |||
{ | |||
public string TargetType { get; } | |||
public PermissionTarget TargetType { get; } | |||
public string TargetId { get; } | |||
public ChannelPermissions Allow { get; } | |||
public ChannelPermissions Deny { get; } | |||
internal PermissionOverwrite(string targetType, string targetId, uint allow, uint deny) | |||
internal PermissionOverwrite(PermissionTarget targetType, string targetId, uint allow, uint deny) | |||
{ | |||
TargetType = targetType; | |||
TargetId = targetId; | |||
@@ -138,7 +138,7 @@ namespace Discord | |||
if (model.PermissionOverwrites != null) | |||
{ | |||
_permissionOverwrites = model.PermissionOverwrites | |||
.Select(x => new PermissionOverwrite(x.Type, x.Id, x.Allow, x.Deny)) | |||
.Select(x => new PermissionOverwrite(PermissionTarget.FromString(x.Type), x.Id, x.Allow, x.Deny)) | |||
.ToArray(); | |||
InvalidatePermissionsCache(); | |||
} | |||
@@ -62,8 +62,8 @@ namespace Discord | |||
public static ChannelPermissions All(string channelType, bool isPrivate) | |||
{ | |||
if (isPrivate) return PrivateOnly; | |||
else if (channelType == ChannelTypes.Text) return TextOnly; | |||
else if (channelType == ChannelTypes.Voice) return VoiceOnly; | |||
else if (channelType == ChannelType.Text) return TextOnly; | |||
else if (channelType == ChannelType.Voice) return VoiceOnly; | |||
else return None; | |||
} | |||
@@ -8,7 +8,6 @@ namespace Discord | |||
public sealed class Role : CachedObject | |||
{ | |||
private readonly string _serverId; | |||
private Server _server; | |||
/// <summary> Returns the name of this role. </summary> | |||
public string Name { get; private set; } | |||
@@ -26,7 +25,7 @@ namespace Discord | |||
/// <summary> Returns the server this role is a member of. </summary> | |||
[JsonIgnore] | |||
public Server Server => _server; | |||
public Server Server { get; private set; } | |||
/// <summary> Returns true if this is the role representing all users in a server. </summary> | |||
public bool IsEveryone => Id == _serverId; | |||
@@ -48,14 +47,16 @@ namespace Discord | |||
} | |||
internal override void OnCached() | |||
{ | |||
_server = _client.Servers[_serverId]; | |||
_server.AddRole(this); | |||
var server = _client.Servers[_serverId]; | |||
server.AddRole(this); | |||
Server = server; | |||
} | |||
internal override void OnUncached() | |||
{ | |||
if (_server != null) | |||
_server.RemoveRole(this); | |||
_server = null; | |||
var server = Server; | |||
if (server != null) | |||
server.RemoveRole(this); | |||
Server = null; | |||
} | |||
internal void Update(RoleInfo model) | |||
@@ -60,10 +60,10 @@ namespace Discord | |||
public IEnumerable<Channel> Channels => _channels.Select(x => _client.Channels[x.Key]); | |||
/// <summary> Returns a collection of all channels within this server. </summary> | |||
[JsonIgnore] | |||
public IEnumerable<Channel> TextChannels => _channels.Select(x => _client.Channels[x.Key]).Where(x => x.Type == ChannelTypes.Text); | |||
public IEnumerable<Channel> TextChannels => _channels.Select(x => _client.Channels[x.Key]).Where(x => x.Type == ChannelType.Text); | |||
/// <summary> Returns a collection of all channels within this server. </summary> | |||
[JsonIgnore] | |||
public IEnumerable<Channel> VoiceChannels => _channels.Select(x => _client.Channels[x.Key]).Where(x => x.Type == ChannelTypes.Voice); | |||
public IEnumerable<Channel> VoiceChannels => _channels.Select(x => _client.Channels[x.Key]).Where(x => x.Type == ChannelType.Voice); | |||
/// <summary> Returns a collection of all invites to this server. </summary> | |||
[JsonIgnore] | |||
@@ -40,7 +40,7 @@ namespace Discord | |||
/// <summary> Returns the id for the game this user is currently playing. </summary> | |||
public string GameId { get; private set; } | |||
/// <summary> Returns the current status for this user. </summary> | |||
public string Status { get; private set; } | |||
public UserStatus Status { get; private set; } | |||
/// <summary> Returns the time this user last sent/edited a message, started typing or sent voice data in this server. </summary> | |||
public DateTime? LastActivityAt { get; private set; } | |||
/// <summary> Returns the time this user was last seen online in this server. </summary> | |||
@@ -152,7 +152,7 @@ namespace Discord | |||
UpdateRoles(model.Roles); | |||
if (model.Status != null && Status != model.Status) | |||
{ | |||
Status = model.Status; | |||
Status = UserStatus.FromString(model.Status); | |||
if (Status == UserStatus.Offline) | |||
_lastOnline = DateTime.UtcNow; | |||
} | |||
@@ -19,11 +19,14 @@ namespace Discord.Net.Rest | |||
_client = new RestSharp.RestClient(Endpoints.BaseApi) | |||
{ | |||
PreAuthenticate = false, | |||
Proxy = new WebProxy(_config.ProxyUrl, true, new string[0], _config.ProxyCredentials), | |||
ReadWriteTimeout = _config.APITimeout, | |||
UserAgent = _config.UserAgent | |||
}; | |||
_client.RemoveDefaultParameter("Accept"); | |||
if (_config.ProxyUrl != null) | |||
_client.Proxy = new WebProxy(_config.ProxyUrl, true, new string[0], _config.ProxyCredentials); | |||
else | |||
_client.Proxy = null; | |||
_client.RemoveDefaultParameter("Accept"); | |||
_client.AddDefaultHeader("accept", "*/*"); | |||
_client.AddDefaultHeader("accept-encoding", "gzip,deflate"); | |||
} | |||
@@ -38,7 +38,7 @@ namespace Discord.Tests | |||
_observerBot.AllServers.Select(x => _observerBot.LeaveServer(x))); | |||
//Create new server and invite the other bots to it | |||
_testServer = _hostClient.CreateServer("Discord.Net Testing", Regions.US_East).Result; | |||
_testServer = _hostClient.CreateServer("Discord.Net Testing", Region.USEast).Result; | |||
_testServerChannel = _testServer.DefaultChannel; | |||
Invite invite = _hostClient.CreateInvite(_testServer, 60, 1, false, false).Result; | |||
WaitAll( | |||
@@ -49,11 +49,11 @@ namespace Discord.Tests | |||
//Channels | |||
[TestMethod] | |||
public void TestCreateTextChannel() | |||
=> TestCreateChannel(ChannelTypes.Text); | |||
=> TestCreateChannel(ChannelType.Text); | |||
[TestMethod] | |||
public void TestCreateVoiceChannel() | |||
=> TestCreateChannel(ChannelTypes.Voice); | |||
private void TestCreateChannel(string type) | |||
=> TestCreateChannel(ChannelType.Voice); | |||
private void TestCreateChannel(ChannelType type) | |||
{ | |||
Channel channel = null; | |||
string name = $"#test_{_random.Next()}"; | |||
@@ -76,21 +76,21 @@ namespace Discord.Tests | |||
[ExpectedException(typeof(InvalidOperationException))] | |||
public async Task TestCreateChannel_NoName() | |||
{ | |||
await _hostClient.CreateChannel(_testServer, $"", ChannelTypes.Text); | |||
await _hostClient.CreateChannel(_testServer, $"", ChannelType.Text); | |||
} | |||
[TestMethod] | |||
[ExpectedException(typeof(InvalidOperationException))] | |||
public async Task TestCreateChannel_NoType() | |||
{ | |||
string name = $"#test_{_random.Next()}"; | |||
await _hostClient.CreateChannel(_testServer, $"", ""); | |||
await _hostClient.CreateChannel(_testServer, $"", ChannelType.FromString("")); | |||
} | |||
[TestMethod] | |||
[ExpectedException(typeof(InvalidOperationException))] | |||
public async Task TestCreateChannel_BadType() | |||
{ | |||
string name = $"#test_{_random.Next()}"; | |||
await _hostClient.CreateChannel(_testServer, $"", "badtype"); | |||
await _hostClient.CreateChannel(_testServer, $"", ChannelType.FromString("badtype")); | |||
} | |||
//Messages | |||