Browse Source

Merge bfd0d8df2d into d111214bff

pull/369/merge
ObsidianMinor GitHub 8 years ago
parent
commit
1fff85e0e2
20 changed files with 249 additions and 21 deletions
  1. +1
    -1
      src/Discord.Net.Core/Discord.Net.Core.csproj
  2. +9
    -0
      src/Discord.Net.Core/Entities/Users/IRelationship.cs
  3. +7
    -0
      src/Discord.Net.Core/Entities/Users/IUser.cs
  4. +11
    -0
      src/Discord.Net.Core/Entities/Users/RelationshipType.cs
  5. +3
    -1
      src/Discord.Net.Core/IDiscordClient.cs
  6. +0
    -11
      src/Discord.Net.Rest/API/Common/RelationshipType.cs
  7. +5
    -2
      src/Discord.Net.Rest/BaseDiscordClient.cs
  8. +6
    -0
      src/Discord.Net.Rest/ClientHelper.cs
  9. +34
    -6
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  10. +3
    -0
      src/Discord.Net.Rest/DiscordRestClient.cs
  11. +26
    -0
      src/Discord.Net.Rest/Entities/Users/RestRelationship.cs
  12. +9
    -0
      src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs
  13. +7
    -0
      src/Discord.Net.Rest/Entities/Users/RestUser.cs
  14. +7
    -0
      src/Discord.Net.Rpc/Entities/Users/RpcUser.cs
  15. +20
    -0
      src/Discord.Net.WebSocket/ClientState.cs
  16. +14
    -0
      src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs
  17. +47
    -0
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  18. +23
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketRelationship.cs
  19. +9
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
  20. +8
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs

+ 1
- 1
src/Discord.Net.Core/Discord.Net.Core.csproj View File

@@ -1,4 +1,4 @@
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<VersionPrefix>1.0.0</VersionPrefix> <VersionPrefix>1.0.0</VersionPrefix>
<VersionSuffix Condition="'$(BuildNumber)' == ''">rc-dev</VersionSuffix> <VersionSuffix Condition="'$(BuildNumber)' == ''">rc-dev</VersionSuffix>


+ 9
- 0
src/Discord.Net.Core/Entities/Users/IRelationship.cs View File

@@ -0,0 +1,9 @@
namespace Discord
{
public interface IRelationship
{
RelationshipType Type { get; }

IUser User { get; }
}
}

+ 7
- 0
src/Discord.Net.Core/Entities/Users/IUser.cs View File

@@ -21,5 +21,12 @@ namespace Discord
Task<IDMChannel> GetDMChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IDMChannel> GetDMChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> Returns a private message channel to this user, creating one if it does not already exist. </summary> /// <summary> Returns a private message channel to this user, creating one if it does not already exist. </summary>
Task<IDMChannel> CreateDMChannelAsync(RequestOptions options = null); Task<IDMChannel> CreateDMChannelAsync(RequestOptions options = null);
/// <summary> Adds this user as a friend, this will remove a block </summary>
Task AddFriendAsync(RequestOptions options = null);
/// <summary> Blocks this user, and removes the user as a friend </summary>
Task BlockUserAsync(RequestOptions options = null);
/// <summary> Removes the relationship of this user </summary>
Task RemoveRelationshipAsync(RequestOptions options = null);
} }
} }

+ 11
- 0
src/Discord.Net.Core/Entities/Users/RelationshipType.cs View File

@@ -0,0 +1,11 @@
namespace Discord
{
public enum RelationshipType
{
None,
Friend,
Blocked,
IncomingPending,
OutgoingPending
}
}

+ 3
- 1
src/Discord.Net.Core/IDiscordClient.cs View File

@@ -25,12 +25,14 @@ namespace Discord
Task<IGuild> GetGuildAsync(ulong id, CacheMode mode = CacheMode.AllowDownload); Task<IGuild> GetGuildAsync(ulong id, CacheMode mode = CacheMode.AllowDownload);
Task<IReadOnlyCollection<IGuild>> GetGuildsAsync(CacheMode mode = CacheMode.AllowDownload); Task<IReadOnlyCollection<IGuild>> GetGuildsAsync(CacheMode mode = CacheMode.AllowDownload);
Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null); Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null);
Task<IInvite> GetInviteAsync(string inviteId); Task<IInvite> GetInviteAsync(string inviteId);


Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload); Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload);
Task<IUser> GetUserAsync(string username, string discriminator); Task<IUser> GetUserAsync(string username, string discriminator);


Task<IReadOnlyCollection<IRelationship>> GetRelationshipsAsync();

Task<IReadOnlyCollection<IVoiceRegion>> GetVoiceRegionsAsync(); Task<IReadOnlyCollection<IVoiceRegion>> GetVoiceRegionsAsync();
Task<IVoiceRegion> GetVoiceRegionAsync(string id); Task<IVoiceRegion> GetVoiceRegionAsync(string id);
} }


+ 0
- 11
src/Discord.Net.Rest/API/Common/RelationshipType.cs View File

@@ -1,11 +0,0 @@
#pragma warning disable CS1591
namespace Discord.API
{
internal enum RelationshipType
{
Friend = 1,
Blocked = 2,
IncomingPending = 3,
OutgoingPending = 4
}
}

+ 5
- 2
src/Discord.Net.Rest/BaseDiscordClient.cs View File

@@ -121,11 +121,14 @@ namespace Discord.Rest
} }
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() => Dispose(true); public void Dispose() => Dispose(true);
//IDiscordClient //IDiscordClient
ConnectionState IDiscordClient.ConnectionState => ConnectionState.Disconnected; ConnectionState IDiscordClient.ConnectionState => ConnectionState.Disconnected;
ISelfUser IDiscordClient.CurrentUser => CurrentUser; ISelfUser IDiscordClient.CurrentUser => CurrentUser;

Task<IReadOnlyCollection<IRelationship>> IDiscordClient.GetRelationshipsAsync()
=> Task.FromResult<IReadOnlyCollection<IRelationship>>(null);
Task<IApplication> IDiscordClient.GetApplicationInfoAsync() { throw new NotSupportedException(); } Task<IApplication> IDiscordClient.GetApplicationInfoAsync() { throw new NotSupportedException(); }


Task<IChannel> IDiscordClient.GetChannelAsync(ulong id, CacheMode mode) Task<IChannel> IDiscordClient.GetChannelAsync(ulong id, CacheMode mode)


+ 6
- 0
src/Discord.Net.Rest/ClientHelper.cs View File

@@ -128,5 +128,11 @@ namespace Discord.Rest
var models = await client.ApiClient.GetVoiceRegionsAsync().ConfigureAwait(false); var models = await client.ApiClient.GetVoiceRegionsAsync().ConfigureAwait(false);
return models.Select(x => RestVoiceRegion.Create(client, x)).Where(x => x.Id == id).FirstOrDefault(); return models.Select(x => RestVoiceRegion.Create(client, x)).Where(x => x.Id == id).FirstOrDefault();
} }

public static async Task<IReadOnlyCollection<RestRelationship>> GetRelationshipsAsync(BaseDiscordClient client)
{
var models = await client.ApiClient.GetRelationshipsAsync().ConfigureAwait(false);
return models.Select(r => RestRelationship.Create(client, r)).ToImmutableArray();
}
} }
} }

+ 34
- 6
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -241,7 +241,7 @@ namespace Discord.API
internal Task<TResponse> SendMultipartAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, IReadOnlyDictionary<string, object> multipartArgs, BucketIds ids, internal Task<TResponse> SendMultipartAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, IReadOnlyDictionary<string, object> multipartArgs, BucketIds ids,
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null) ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null)
=> SendMultipartAsync<TResponse>(method, GetEndpoint(endpointExpr), multipartArgs, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options); => SendMultipartAsync<TResponse>(method, GetEndpoint(endpointExpr), multipartArgs, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options);
public async Task<TResponse> SendMultipartAsync<TResponse>(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs,
public async Task<TResponse> SendMultipartAsync<TResponse>(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs,
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null) string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null)
{ {
options = options ?? new RequestOptions(); options = options ?? new RequestOptions();
@@ -387,7 +387,7 @@ namespace Discord.API
break; break;
} }
} }
//Channel Messages //Channel Messages
public async Task<Message> GetChannelMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null) public async Task<Message> GetChannelMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{ {
@@ -678,7 +678,7 @@ namespace Discord.API
Preconditions.NotNullOrWhitespace(args.Name, nameof(args.Name)); Preconditions.NotNullOrWhitespace(args.Name, nameof(args.Name));
Preconditions.NotNullOrWhitespace(args.RegionId, nameof(args.RegionId)); Preconditions.NotNullOrWhitespace(args.RegionId, nameof(args.RegionId));
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
return await SendJsonAsync<Guild>("POST", () => "guilds", args, new BucketIds(), options: options).ConfigureAwait(false); return await SendJsonAsync<Guild>("POST", () => "guilds", args, new BucketIds(), options: options).ConfigureAwait(false);
} }
public async Task<Guild> DeleteGuildAsync(ulong guildId, RequestOptions options = null) public async Task<Guild> DeleteGuildAsync(ulong guildId, RequestOptions options = null)
@@ -886,14 +886,14 @@ namespace Discord.API
{ {
Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId)); Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId));
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
return await SendAsync<Invite>("DELETE", () => $"invites/{inviteId}", new BucketIds(), options: options).ConfigureAwait(false); return await SendAsync<Invite>("DELETE", () => $"invites/{inviteId}", new BucketIds(), options: options).ConfigureAwait(false);
} }
public async Task AcceptInviteAsync(string inviteId, RequestOptions options = null) public async Task AcceptInviteAsync(string inviteId, RequestOptions options = null)
{ {
Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId)); Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId));
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
await SendAsync("POST", () => $"invites/{inviteId}", new BucketIds(), options: options).ConfigureAwait(false); await SendAsync("POST", () => $"invites/{inviteId}", new BucketIds(), options: options).ConfigureAwait(false);
} }


@@ -1028,6 +1028,34 @@ namespace Discord.API
} }
catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.NotFound) { return null; } catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.NotFound) { return null; }
} }
//Relationships
public async Task<IReadOnlyCollection<Relationship>> GetRelationshipsAsync(RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);
return await SendAsync<IReadOnlyCollection<Relationship>>("GET", () => "users/@me/relationships", new BucketIds(), options: options).ConfigureAwait(false);
}
public async Task AddFriendAsync(ulong userId, RequestOptions options = null)
{
Preconditions.NotEqual(userId, 0, nameof(userId));
options = RequestOptions.CreateOrClone(options);

await SendJsonAsync("PUT", () => $"users/@me/relationships/{userId}", new object(), new BucketIds(), options: options).ConfigureAwait(false);
}
public async Task BlockUserAsync(ulong userId, RequestOptions options = null)
{
Preconditions.NotEqual(userId, 0, nameof(userId));
options = RequestOptions.CreateOrClone(options);

await SendJsonAsync("PUT", () => $"users/@me/relationships/{userId}", new { type = 2 }, new BucketIds(), options: options).ConfigureAwait(false);
}
public async Task RemoveRelationshipAsync(ulong userId, RequestOptions options = null)
{
Preconditions.NotEqual(userId, 0, nameof(userId));
options = RequestOptions.CreateOrClone(options);

await SendAsync("DELETE", () => $"users/@me/relationships/{userId}", new BucketIds(), options: options).ConfigureAwait(false);
}


//Current User/DMs //Current User/DMs
public async Task<User> GetMyUserAsync(RequestOptions options = null) public async Task<User> GetMyUserAsync(RequestOptions options = null)
@@ -1193,7 +1221,7 @@ namespace Discord.API
int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1)); int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1));
string fieldName = GetFieldName(methodArgs[argId + 1]); string fieldName = GetFieldName(methodArgs[argId + 1]);
int? mappedId; int? mappedId;
mappedId = BucketIds.GetIndex(fieldName); mappedId = BucketIds.GetIndex(fieldName);
if(!mappedId.HasValue && rightIndex != endIndex && format.Length > rightIndex + 1 && format[rightIndex + 1] == '/') //Ignore the next slash if(!mappedId.HasValue && rightIndex != endIndex && format.Length > rightIndex + 1 && format[rightIndex + 1] == '/') //Ignore the next slash
rightIndex++; rightIndex++;


+ 3
- 0
src/Discord.Net.Rest/DiscordRestClient.cs View File

@@ -89,6 +89,9 @@ namespace Discord.Rest
public Task<RestVoiceRegion> GetVoiceRegionAsync(string id) public Task<RestVoiceRegion> GetVoiceRegionAsync(string id)
=> ClientHelper.GetVoiceRegionAsync(this, id); => ClientHelper.GetVoiceRegionAsync(this, id);


public Task<IReadOnlyCollection<RestRelationship>> GetRelationshipsAsync()
=> ClientHelper.GetRelationshipsAsync(this);

//IDiscordClient //IDiscordClient
async Task<IApplication> IDiscordClient.GetApplicationInfoAsync() async Task<IApplication> IDiscordClient.GetApplicationInfoAsync()
=> await GetApplicationInfoAsync().ConfigureAwait(false); => await GetApplicationInfoAsync().ConfigureAwait(false);


+ 26
- 0
src/Discord.Net.Rest/Entities/Users/RestRelationship.cs View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using Model = Discord.API.Relationship;

namespace Discord.Rest
{
public class RestRelationship : IRelationship
{
public RelationshipType Type { get; internal set; }

public IUser User { get; internal set; }

internal RestRelationship(RelationshipType type, IUser user)
{
Type = type;
User = user;
}

internal static RestRelationship Create(BaseDiscordClient discord, Model model)
{
RestUser user = RestUser.Create(discord, model.User);
return new RestRelationship(model.Type, user);
}
}
}

+ 9
- 0
src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs View File

@@ -49,5 +49,14 @@ namespace Discord.Rest
var model = await UserHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); var model = await UserHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false);
Update(model); Update(model);
} }

Task IUser.AddFriendAsync(RequestOptions options) =>
throw new InvalidOperationException("You can't friend yourself!");

Task IUser.BlockUserAsync(RequestOptions options) =>
throw new InvalidOperationException("You can't block yourself!");

Task IUser.RemoveRelationshipAsync(RequestOptions options) =>
throw new InvalidOperationException("You don't have any relations with yourself!");
} }
} }

+ 7
- 0
src/Discord.Net.Rest/Entities/Users/RestUser.cs View File

@@ -53,6 +53,13 @@ namespace Discord.Rest


public override string ToString() => $"{Username}#{Discriminator}"; public override string ToString() => $"{Username}#{Discriminator}";
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})"; private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})";
public Task AddFriendAsync(RequestOptions options = null)
=> Discord.ApiClient.AddFriendAsync(Id, options);
public Task BlockUserAsync(RequestOptions options = null)
=> Discord.ApiClient.BlockUserAsync(Id, options);
public Task RemoveRelationshipAsync(RequestOptions options = null)
=> Discord.ApiClient.RemoveRelationshipAsync(Id, options);


//IUser //IUser
Task<IDMChannel> IUser.GetDMChannelAsync(CacheMode mode, RequestOptions options) Task<IDMChannel> IUser.GetDMChannelAsync(CacheMode mode, RequestOptions options)


+ 7
- 0
src/Discord.Net.Rpc/Entities/Users/RpcUser.cs View File

@@ -54,5 +54,12 @@ namespace Discord.Rpc
=> Task.FromResult<IDMChannel>(null); => Task.FromResult<IDMChannel>(null);
async Task<IDMChannel> IUser.CreateDMChannelAsync(RequestOptions options) async Task<IDMChannel> IUser.CreateDMChannelAsync(RequestOptions options)
=> await CreateDMChannelAsync(options).ConfigureAwait(false); => await CreateDMChannelAsync(options).ConfigureAwait(false);

Task IUser.AddFriendAsync(RequestOptions options)
=> throw new NotSupportedException();
Task IUser.BlockUserAsync(RequestOptions options)
=> throw new NotSupportedException();
Task IUser.RemoveRelationshipAsync(RequestOptions options)
=> throw new NotSupportedException();
} }
} }

+ 20
- 0
src/Discord.Net.WebSocket/ClientState.cs View File

@@ -15,6 +15,7 @@ namespace Discord.WebSocket
private readonly ConcurrentDictionary<ulong, SocketDMChannel> _dmChannels; private readonly ConcurrentDictionary<ulong, SocketDMChannel> _dmChannels;
private readonly ConcurrentDictionary<ulong, SocketGuild> _guilds; private readonly ConcurrentDictionary<ulong, SocketGuild> _guilds;
private readonly ConcurrentDictionary<ulong, SocketGlobalUser> _users; private readonly ConcurrentDictionary<ulong, SocketGlobalUser> _users;
private readonly ConcurrentDictionary<ulong, SocketRelationship> _relationships;
private readonly ConcurrentHashSet<ulong> _groupChannels; private readonly ConcurrentHashSet<ulong> _groupChannels;


internal IReadOnlyCollection<SocketChannel> Channels => _channels.ToReadOnlyCollection(); internal IReadOnlyCollection<SocketChannel> Channels => _channels.ToReadOnlyCollection();
@@ -22,6 +23,7 @@ namespace Discord.WebSocket
internal IReadOnlyCollection<SocketGroupChannel> GroupChannels => _groupChannels.Select(x => GetChannel(x) as SocketGroupChannel).ToReadOnlyCollection(_groupChannels); internal IReadOnlyCollection<SocketGroupChannel> GroupChannels => _groupChannels.Select(x => GetChannel(x) as SocketGroupChannel).ToReadOnlyCollection(_groupChannels);
internal IReadOnlyCollection<SocketGuild> Guilds => _guilds.ToReadOnlyCollection(); internal IReadOnlyCollection<SocketGuild> Guilds => _guilds.ToReadOnlyCollection();
internal IReadOnlyCollection<SocketGlobalUser> Users => _users.ToReadOnlyCollection(); internal IReadOnlyCollection<SocketGlobalUser> Users => _users.ToReadOnlyCollection();
internal IReadOnlyCollection<SocketRelationship> Relationships => _relationships.ToReadOnlyCollection();


internal IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels => internal IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels =>
_dmChannels.Select(x => x.Value as ISocketPrivateChannel).Concat( _dmChannels.Select(x => x.Value as ISocketPrivateChannel).Concat(
@@ -36,6 +38,7 @@ namespace Discord.WebSocket
_dmChannels = new ConcurrentDictionary<ulong, SocketDMChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(dmChannelCount * CollectionMultiplier)); _dmChannels = new ConcurrentDictionary<ulong, SocketDMChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(dmChannelCount * CollectionMultiplier));
_guilds = new ConcurrentDictionary<ulong, SocketGuild>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(guildCount * CollectionMultiplier)); _guilds = new ConcurrentDictionary<ulong, SocketGuild>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(guildCount * CollectionMultiplier));
_users = new ConcurrentDictionary<ulong, SocketGlobalUser>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedUsersCount * CollectionMultiplier)); _users = new ConcurrentDictionary<ulong, SocketGlobalUser>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedUsersCount * CollectionMultiplier));
_relationships = new ConcurrentDictionary<ulong, SocketRelationship>(ConcurrentHashSet.DefaultConcurrencyLevel, 35);
_groupChannels = new ConcurrentHashSet<ulong>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(10 * CollectionMultiplier)); _groupChannels = new ConcurrentHashSet<ulong>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(10 * CollectionMultiplier));
} }


@@ -126,5 +129,22 @@ namespace Discord.WebSocket
return user; return user;
return null; return null;
} }

internal SocketRelationship GetRelationship(ulong id)
{
if (_relationships.TryGetValue(id, out SocketRelationship value))
return value;
return null;
}
internal void AddRelationship(SocketRelationship relationship)
{
_relationships[relationship.User.Id] = relationship;
}
internal SocketRelationship RemoveRelationship(ulong id)
{
if (_relationships.TryRemove(id, out SocketRelationship value))
return value;
return null;
}
} }
} }

+ 14
- 0
src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs View File

@@ -221,5 +221,19 @@ namespace Discord.WebSocket
remove { _recipientRemovedEvent.Remove(value); } remove { _recipientRemovedEvent.Remove(value); }
} }
private readonly AsyncEvent<Func<SocketGroupUser, Task>> _recipientRemovedEvent = new AsyncEvent<Func<SocketGroupUser, Task>>(); private readonly AsyncEvent<Func<SocketGroupUser, Task>> _recipientRemovedEvent = new AsyncEvent<Func<SocketGroupUser, Task>>();
// relationships
public event Func<SocketRelationship, SocketRelationship, Task> RelationshipAdd
{
add { _relationshipAddedEvent.Add(value); }
remove { _relationshipAddedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<SocketRelationship, SocketRelationship, Task>> _relationshipAddedEvent = new AsyncEvent<Func<SocketRelationship, SocketRelationship, Task>>();
public event Func<SocketRelationship, Task> RelationshipRemoved
{
add { _relationshipRemovedEvent.Add(value); }
remove { _relationshipRemovedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<SocketRelationship, Task>> _relationshipRemovedEvent = new AsyncEvent<Func<SocketRelationship, Task>>();
} }
} }

+ 47
- 0
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -70,6 +70,7 @@ namespace Discord.WebSocket
public IReadOnlyCollection<SocketGroupChannel> GroupChannels public IReadOnlyCollection<SocketGroupChannel> GroupChannels
=> State.PrivateChannels.Select(x => x as SocketGroupChannel).Where(x => x != null).ToImmutableArray(); => State.PrivateChannels.Select(x => x as SocketGroupChannel).Where(x => x != null).ToImmutableArray();
public IReadOnlyCollection<RestVoiceRegion> VoiceRegions => _voiceRegions.ToReadOnlyCollection(); public IReadOnlyCollection<RestVoiceRegion> VoiceRegions => _voiceRegions.ToReadOnlyCollection();
public IReadOnlyCollection<SocketRelationship> Relationships => State.Relationships;


/// <summary> Creates a new REST/WebSocket discord client. </summary> /// <summary> Creates a new REST/WebSocket discord client. </summary>
public DiscordSocketClient() : this(new DiscordSocketConfig()) { } public DiscordSocketClient() : this(new DiscordSocketConfig()) { }
@@ -270,6 +271,9 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
public Task<RestInvite> GetInviteAsync(string inviteId) public Task<RestInvite> GetInviteAsync(string inviteId)
=> ClientHelper.GetInviteAsync(this, inviteId); => ClientHelper.GetInviteAsync(this, inviteId);
public Task<IReadOnlyCollection<SocketRelationship>> GetRelationshipsAsync()
=> Task.FromResult(State.Relationships);


/// <inheritdoc /> /// <inheritdoc />
public SocketUser GetUser(ulong id) public SocketUser GetUser(ulong id)
@@ -484,6 +488,8 @@ namespace Discord.WebSocket
} }
for (int i = 0; i < data.PrivateChannels.Length; i++) for (int i = 0; i < data.PrivateChannels.Length; i++)
AddPrivateChannel(data.PrivateChannels[i], state); AddPrivateChannel(data.PrivateChannels[i], state);
for (int i = 0; i < data.Relationships.Length; i++)
AddRelationship(data.Relationships[i], state);


_sessionId = data.SessionId; _sessionId = data.SessionId;
_unavailableGuilds = unavailableGuilds; _unavailableGuilds = unavailableGuilds;
@@ -1499,6 +1505,29 @@ namespace Discord.WebSocket
} }
} }
return; return;
//Relationships
case "RELATIONSHIP_ADD":
{
await _gatewayLogger.DebugAsync("Received Dispatch (RELATIONSHIP_ADD)").ConfigureAwait(false);

var addedModel = (payload as JToken).ToObject<Relationship>(_serializer);
var before = State.GetRelationship(addedModel.Id);
var after = AddRelationship(addedModel, State);

await _relationshipAddedEvent.InvokeAsync(before, after);
return;
}
case "RELATIONSHIP_REMOVE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (RELATIONSHIP_REMOVE)").ConfigureAwait(false);

var removedModel = (payload as JToken).ToObject<Relationship>(_serializer);
var removed = RemoveRelationship(removedModel.Id);

await _relationshipRemovedEvent.InvokeAsync(removed);
return;
}


//Ignored (User only) //Ignored (User only)
case "CHANNEL_PINS_ACK": case "CHANNEL_PINS_ACK":
@@ -1650,6 +1679,21 @@ namespace Discord.WebSocket
return channel; return channel;
} }


internal SocketRelationship GetRelationship(ulong id)
{
return State.GetRelationship(id);
}
internal SocketRelationship AddRelationship(Relationship model, ClientState state)
{
var relationship = SocketRelationship.Create(this, state, model);
state.AddRelationship(SocketRelationship.Create(this, state, model));
return relationship;
}
internal SocketRelationship RemoveRelationship(ulong id)
{
return State.RemoveRelationship(id);
}

//IDiscordClient //IDiscordClient
ConnectionState IDiscordClient.ConnectionState => _connection.State; ConnectionState IDiscordClient.ConnectionState => _connection.State;


@@ -1692,5 +1736,8 @@ namespace Discord.WebSocket
=> await StartAsync().ConfigureAwait(false); => await StartAsync().ConfigureAwait(false);
async Task IDiscordClient.StopAsync() async Task IDiscordClient.StopAsync()
=> await StopAsync().ConfigureAwait(false); => await StopAsync().ConfigureAwait(false);

async Task<IReadOnlyCollection<IRelationship>> IDiscordClient.GetRelationshipsAsync()
=> await GetRelationshipsAsync();
} }
} }

+ 23
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketRelationship.cs View File

@@ -0,0 +1,23 @@
using Model = Discord.API.Relationship;

namespace Discord.WebSocket
{
public class SocketRelationship : IRelationship
{
public RelationshipType Type { get; internal set; }

public IUser User { get; internal set; }

public SocketRelationship(RelationshipType type, IUser user)
{
Type = type;
User = user;
}

internal static SocketRelationship Create(DiscordSocketClient discord, ClientState state, Model model)
{
SocketSimpleUser user = SocketSimpleUser.Create(discord, state, model.User);
return new SocketRelationship(model.Type, user);
}
}
}

+ 9
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs View File

@@ -46,6 +46,15 @@ namespace Discord.WebSocket
public Task ModifyAsync(Action<SelfUserProperties> func, RequestOptions options = null) public Task ModifyAsync(Action<SelfUserProperties> func, RequestOptions options = null)
=> UserHelper.ModifyAsync(this, Discord, func, options); => UserHelper.ModifyAsync(this, Discord, func, options);


Task IUser.AddFriendAsync(RequestOptions options) =>
throw new InvalidOperationException("You can't friend yourself!");

Task IUser.BlockUserAsync(RequestOptions options) =>
throw new InvalidOperationException("You can't block yourself!");

Task IUser.RemoveRelationshipAsync(RequestOptions options) =>
throw new InvalidOperationException("You don't have any relations with yourself!");

internal new SocketSelfUser Clone() => MemberwiseClone() as SocketSelfUser; internal new SocketSelfUser Clone() => MemberwiseClone() as SocketSelfUser;
} }
} }

+ 8
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs View File

@@ -21,6 +21,7 @@ namespace Discord.WebSocket
public string Mention => MentionUtils.MentionUser(Id); public string Mention => MentionUtils.MentionUser(Id);
public Game? Game => Presence.Game; public Game? Game => Presence.Game;
public UserStatus Status => Presence.Status; public UserStatus Status => Presence.Status;
public RelationshipType Relationship => Discord.GetRelationship(Id)?.Type ?? RelationshipType.None;


internal SocketUser(DiscordSocketClient discord, ulong id) internal SocketUser(DiscordSocketClient discord, ulong id)
: base(discord, id) : base(discord, id)
@@ -55,5 +56,12 @@ namespace Discord.WebSocket
=> Task.FromResult<IDMChannel>(GlobalUser.DMChannel); => Task.FromResult<IDMChannel>(GlobalUser.DMChannel);
async Task<IDMChannel> IUser.CreateDMChannelAsync(RequestOptions options) async Task<IDMChannel> IUser.CreateDMChannelAsync(RequestOptions options)
=> await CreateDMChannelAsync(options).ConfigureAwait(false); => await CreateDMChannelAsync(options).ConfigureAwait(false);
public async Task AddFriendAsync(RequestOptions options = null)
=> await Discord.ApiClient.AddFriendAsync(Id, options);
public async Task BlockUserAsync(RequestOptions options = null)
=> await Discord.ApiClient.BlockUserAsync(Id, options);
public async Task RemoveRelationshipAsync(RequestOptions options = null)
=> await Discord.ApiClient.RemoveRelationshipAsync(Id, options);
} }
} }

Loading…
Cancel
Save