diff --git a/src/Discord.Net.Core/Entities/Users/IRelationship.cs b/src/Discord.Net.Core/Entities/Users/IRelationship.cs
new file mode 100644
index 000000000..6403184e7
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Users/IRelationship.cs
@@ -0,0 +1,9 @@
+namespace Discord
+{
+ public interface IRelationship
+ {
+ RelationshipType Type { get; }
+
+ IUser User { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Users/IUser.cs b/src/Discord.Net.Core/Entities/Users/IUser.cs
index e3f270f6f..5b0726d25 100644
--- a/src/Discord.Net.Core/Entities/Users/IUser.cs
+++ b/src/Discord.Net.Core/Entities/Users/IUser.cs
@@ -18,7 +18,13 @@ namespace Discord
bool IsWebhook { get; }
/// Gets the username for this user.
string Username { get; }
-
+
+ /// Adds this user as a friend, this will remove a block
+ Task AddFriendAsync(RequestOptions options = null);
+ /// Blocks this user, and removes the user as a friend
+ Task BlockUserAsync(RequestOptions options = null);
+ /// Removes the relationship of this user
+ Task RemoveRelationshipAsync(RequestOptions options = null);
/// Returns a private message channel to this user, creating one if it does not already exist.
Task GetOrCreateDMChannelAsync(RequestOptions options = null);
}
diff --git a/src/Discord.Net.Core/Entities/Users/RelationshipType.cs b/src/Discord.Net.Core/Entities/Users/RelationshipType.cs
new file mode 100644
index 000000000..dc5129aa1
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Users/RelationshipType.cs
@@ -0,0 +1,11 @@
+namespace Discord
+{
+ public enum RelationshipType
+ {
+ None,
+ Friend,
+ Blocked,
+ IncomingPending,
+ OutgoingPending
+ }
+}
diff --git a/src/Discord.Net.Core/IDiscordClient.cs b/src/Discord.Net.Core/IDiscordClient.cs
index 23e8e9c5b..aa4a40013 100644
--- a/src/Discord.Net.Core/IDiscordClient.cs
+++ b/src/Discord.Net.Core/IDiscordClient.cs
@@ -26,6 +26,8 @@ namespace Discord
Task GetGuildAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
Task> GetGuildsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
Task CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null, RequestOptions options = null);
+
+ Task> GetRelationshipsAsync(RequestOptions options = null);
Task GetInviteAsync(string inviteId, RequestOptions options = null);
diff --git a/src/Discord.Net.Core/Utils/Preconditions.cs b/src/Discord.Net.Core/Utils/Preconditions.cs
index 705a15249..42184be4e 100644
--- a/src/Discord.Net.Core/Utils/Preconditions.cs
+++ b/src/Discord.Net.Core/Utils/Preconditions.cs
@@ -192,5 +192,7 @@ namespace Discord
throw new ArgumentOutOfRangeException(name, "Messages must be younger than two weeks old.");
}
}
+
+ public static void LoggedInAs(TokenType token, TokenType existing) { if (token != existing) throw new NotSupportedException($"Must be logged in as a {token} to use this endpoint"); }
}
}
diff --git a/src/Discord.Net.Rest/API/Common/RelationshipType.cs b/src/Discord.Net.Rest/API/Common/RelationshipType.cs
deleted file mode 100644
index 0ed99f396..000000000
--- a/src/Discord.Net.Rest/API/Common/RelationshipType.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma warning disable CS1591
-namespace Discord.API
-{
- internal enum RelationshipType
- {
- Friend = 1,
- Blocked = 2,
- IncomingPending = 3,
- OutgoingPending = 4
- }
-}
diff --git a/src/Discord.Net.Rest/BaseDiscordClient.cs b/src/Discord.Net.Rest/BaseDiscordClient.cs
index ed12ff383..a3bbd5d49 100644
--- a/src/Discord.Net.Rest/BaseDiscordClient.cs
+++ b/src/Discord.Net.Rest/BaseDiscordClient.cs
@@ -122,11 +122,14 @@ namespace Discord.Rest
}
///
public void Dispose() => Dispose(true);
-
+
//IDiscordClient
ConnectionState IDiscordClient.ConnectionState => ConnectionState.Disconnected;
ISelfUser IDiscordClient.CurrentUser => CurrentUser;
-
+
+ Task> IDiscordClient.GetRelationshipsAsync(RequestOptions options)
+ => Task.FromResult>(null);
+
Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) { throw new NotSupportedException(); }
Task IDiscordClient.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options)
diff --git a/src/Discord.Net.Rest/ClientHelper.cs b/src/Discord.Net.Rest/ClientHelper.cs
index 8bc800a7d..89c000758 100644
--- a/src/Discord.Net.Rest/ClientHelper.cs
+++ b/src/Discord.Net.Rest/ClientHelper.cs
@@ -152,5 +152,20 @@ namespace Discord.Rest
var models = await client.ApiClient.GetVoiceRegionsAsync(options).ConfigureAwait(false);
return models.Select(x => RestVoiceRegion.Create(client, x)).FirstOrDefault(x => x.Id == id);
}
+
+ public static async Task> GetRelationshipsAsync(BaseDiscordClient client)
+ {
+ var models = await client.ApiClient.GetRelationshipsAsync().ConfigureAwait(false);
+ return models.Select(r => RestRelationship.Create(client, r)).ToReadOnlyCollection(models);
+ }
+
+ public static async Task AddFriendAsync(BaseDiscordClient client, ulong user, RequestOptions options)
+ => await client.ApiClient.AddFriendAsync(user, options).ConfigureAwait(false);
+
+ public static async Task BlockUserAsync(BaseDiscordClient client, ulong user, RequestOptions options)
+ => await client.ApiClient.BlockUserAsync(user, options).ConfigureAwait(false);
+
+ public static async Task RemoveRelationshipAsync(BaseDiscordClient client, ulong user, RequestOptions options)
+ => await client.ApiClient.RemoveRelationshipAsync(user, options).ConfigureAwait(false);
}
}
diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs
index 78e768ccd..1aa9f6a09 100644
--- a/src/Discord.Net.Rest/DiscordRestApiClient.cs
+++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs
@@ -241,7 +241,7 @@ namespace Discord.API
internal Task SendMultipartAsync(string method, Expression> endpointExpr, IReadOnlyDictionary multipartArgs, BucketIds ids,
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null)
=> SendMultipartAsync(method, GetEndpoint(endpointExpr), multipartArgs, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options);
- public async Task SendMultipartAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs,
+ public async Task SendMultipartAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs,
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null)
{
options = options ?? new RequestOptions();
@@ -730,7 +730,7 @@ namespace Discord.API
Preconditions.NotNullOrWhitespace(args.Name, nameof(args.Name));
Preconditions.NotNullOrWhitespace(args.RegionId, nameof(args.RegionId));
options = RequestOptions.CreateOrClone(options);
-
+
return await SendJsonAsync("POST", () => "guilds", args, new BucketIds(), options: options).ConfigureAwait(false);
}
public async Task DeleteGuildAsync(ulong guildId, RequestOptions options = null)
@@ -940,14 +940,14 @@ namespace Discord.API
{
Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId));
options = RequestOptions.CreateOrClone(options);
-
+
return await SendAsync("DELETE", () => $"invites/{inviteId}", new BucketIds(), options: options).ConfigureAwait(false);
}
public async Task AcceptInviteAsync(string inviteId, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId));
options = RequestOptions.CreateOrClone(options);
-
+
await SendAsync("POST", () => $"invites/{inviteId}", new BucketIds(), options: options).ConfigureAwait(false);
}
@@ -1073,6 +1073,43 @@ namespace Discord.API
}
catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.NotFound) { return null; }
}
+
+ //Relationships
+ public async Task> GetRelationshipsAsync(RequestOptions options = null)
+ {
+ Preconditions.LoggedInAs(TokenType.User, AuthTokenType);
+
+ options = RequestOptions.CreateOrClone(options);
+
+ return await SendAsync>("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));
+ Preconditions.LoggedInAs(TokenType.User, AuthTokenType);
+
+ 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));
+ Preconditions.LoggedInAs(TokenType.User, AuthTokenType);
+
+ 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));
+ Preconditions.LoggedInAs(TokenType.User, AuthTokenType);
+
+ options = RequestOptions.CreateOrClone(options);
+
+ await SendAsync("DELETE", () => $"users/@me/relationships/{userId}", new BucketIds(), options: options).ConfigureAwait(false);
+ }
//Current User/DMs
public async Task GetMyUserAsync(RequestOptions options = null)
@@ -1246,7 +1283,7 @@ namespace Discord.API
int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1));
string fieldName = GetFieldName(methodArgs[argId + 1]);
int? mappedId;
-
+
mappedId = BucketIds.GetIndex(fieldName);
if(!mappedId.HasValue && rightIndex != endIndex && format.Length > rightIndex + 1 && format[rightIndex + 1] == '/') //Ignore the next slash
rightIndex++;
diff --git a/src/Discord.Net.Rest/DiscordRestClient.cs b/src/Discord.Net.Rest/DiscordRestClient.cs
index aa9937008..9228c5c30 100644
--- a/src/Discord.Net.Rest/DiscordRestClient.cs
+++ b/src/Discord.Net.Rest/DiscordRestClient.cs
@@ -92,6 +92,9 @@ namespace Discord.Rest
public Task GetVoiceRegionAsync(string id, RequestOptions options = null)
=> ClientHelper.GetVoiceRegionAsync(this, id, options);
+ public Task> GetRelationshipsAsync()
+ => ClientHelper.GetRelationshipsAsync(this);
+
//IDiscordClient
async Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options)
=> await GetApplicationInfoAsync(options).ConfigureAwait(false);
diff --git a/src/Discord.Net.Rest/Entities/Users/RestRelationship.cs b/src/Discord.Net.Rest/Entities/Users/RestRelationship.cs
new file mode 100644
index 000000000..7061969fe
--- /dev/null
+++ b/src/Discord.Net.Rest/Entities/Users/RestRelationship.cs
@@ -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);
+ }
+ }
+}
diff --git a/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs b/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs
index ab5ec4a3b..4ebe8ee8f 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs
@@ -49,5 +49,14 @@ namespace Discord.Rest
var model = await UserHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false);
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!");
}
}
diff --git a/src/Discord.Net.Rest/Entities/Users/RestUser.cs b/src/Discord.Net.Rest/Entities/Users/RestUser.cs
index d8ade3a6b..6c34aacb0 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestUser.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestUser.cs
@@ -63,6 +63,13 @@ namespace Discord.Rest
public override string ToString() => $"{Username}#{Discriminator}";
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})";
+ public Task AddFriendAsync(RequestOptions options = null)
+ => ClientHelper.AddFriendAsync(Discord, Id, options);
+ public Task BlockUserAsync(RequestOptions options = null)
+ => ClientHelper.BlockUserAsync(Discord, Id, options);
+ public Task RemoveRelationshipAsync(RequestOptions options = null)
+ => ClientHelper.RemoveRelationshipAsync(Discord, Id, options);
+
//IUser
async Task IUser.GetOrCreateDMChannelAsync(RequestOptions options)
=> await GetOrCreateDMChannelAsync(options);
diff --git a/src/Discord.Net.Rpc/Entities/Users/RpcUser.cs b/src/Discord.Net.Rpc/Entities/Users/RpcUser.cs
index c6b0b2fd8..e7bd8b614 100644
--- a/src/Discord.Net.Rpc/Entities/Users/RpcUser.cs
+++ b/src/Discord.Net.Rpc/Entities/Users/RpcUser.cs
@@ -58,7 +58,13 @@ namespace Discord.Rpc
public override string ToString() => $"{Username}#{Discriminator}";
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})";
- //IUser
+ Task IUser.AddFriendAsync(RequestOptions options)
+ => throw new NotSupportedException();
+ Task IUser.BlockUserAsync(RequestOptions options)
+ => throw new NotSupportedException();
+ Task IUser.RemoveRelationshipAsync(RequestOptions options)
+ => throw new NotSupportedException();
+
async Task IUser.GetOrCreateDMChannelAsync(RequestOptions options)
=> await GetOrCreateDMChannelAsync(options);
}
diff --git a/src/Discord.Net.WebSocket/ClientState.cs b/src/Discord.Net.WebSocket/ClientState.cs
index f07976a0a..659b30240 100644
--- a/src/Discord.Net.WebSocket/ClientState.cs
+++ b/src/Discord.Net.WebSocket/ClientState.cs
@@ -15,6 +15,7 @@ namespace Discord.WebSocket
private readonly ConcurrentDictionary _dmChannels;
private readonly ConcurrentDictionary _guilds;
private readonly ConcurrentDictionary _users;
+ private readonly ConcurrentDictionary _relationships;
private readonly ConcurrentHashSet _groupChannels;
internal IReadOnlyCollection Channels => _channels.ToReadOnlyCollection();
@@ -22,6 +23,7 @@ namespace Discord.WebSocket
internal IReadOnlyCollection GroupChannels => _groupChannels.Select(x => GetChannel(x) as SocketGroupChannel).ToReadOnlyCollection(_groupChannels);
internal IReadOnlyCollection Guilds => _guilds.ToReadOnlyCollection();
internal IReadOnlyCollection Users => _users.ToReadOnlyCollection();
+ internal IReadOnlyCollection Relationships => _relationships.ToReadOnlyCollection();
internal IReadOnlyCollection PrivateChannels =>
_dmChannels.Select(x => x.Value as ISocketPrivateChannel).Concat(
@@ -36,6 +38,7 @@ namespace Discord.WebSocket
_dmChannels = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(dmChannelCount * CollectionMultiplier));
_guilds = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(guildCount * CollectionMultiplier));
_users = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedUsersCount * CollectionMultiplier));
+ _relationships = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, 35);
_groupChannels = new ConcurrentHashSet(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(10 * CollectionMultiplier));
}
@@ -116,5 +119,22 @@ namespace Discord.WebSocket
return user;
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;
+ }
}
}
diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs
index fb155e535..ce64101de 100644
--- a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs
+++ b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs
@@ -215,5 +215,19 @@ namespace Discord.WebSocket
remove { _recipientRemovedEvent.Remove(value); }
}
private readonly AsyncEvent> _recipientRemovedEvent = new AsyncEvent>();
+
+ // relationships
+ public event Func RelationshipAdded
+ {
+ add { _relationshipAddedEvent.Add(value); }
+ remove { _relationshipAddedEvent.Remove(value); }
+ }
+ private readonly AsyncEvent> _relationshipAddedEvent = new AsyncEvent>();
+ public event Func RelationshipRemoved
+ {
+ add { _relationshipRemovedEvent.Add(value); }
+ remove { _relationshipRemovedEvent.Remove(value); }
+ }
+ private readonly AsyncEvent> _relationshipRemovedEvent = new AsyncEvent>();
}
}
diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs
index b13ceca1d..c4a4c5ec4 100644
--- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs
+++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs
@@ -68,6 +68,7 @@ namespace Discord.WebSocket
public IReadOnlyCollection GroupChannels
=> State.PrivateChannels.Select(x => x as SocketGroupChannel).Where(x => x != null).ToImmutableArray();
public IReadOnlyCollection VoiceRegions => _voiceRegions.ToReadOnlyCollection();
+ public IReadOnlyCollection Relationships => State.Relationships;
/// Creates a new REST/WebSocket discord client.
public DiscordSocketClient() : this(new DiscordSocketConfig()) { }
@@ -256,8 +257,11 @@ namespace Discord.WebSocket
=> ClientHelper.GetConnectionsAsync(this, new RequestOptions());
///
- public Task GetInviteAsync(string inviteId)
- => ClientHelper.GetInviteAsync(this, inviteId, new RequestOptions());
+ public Task GetInviteAsync(string inviteId, RequestOptions options = null)
+ => ClientHelper.GetInviteAsync(this, inviteId, options);
+
+ public Task> GetRelationshipsAsync()
+ => Task.FromResult(State.Relationships);
///
public SocketUser GetUser(ulong id)
@@ -472,6 +476,8 @@ namespace Discord.WebSocket
}
for (int i = 0; i < data.PrivateChannels.Length; i++)
AddPrivateChannel(data.PrivateChannels[i], state);
+ for (int i = 0; i < data.Relationships.Length; i++)
+ AddRelationship(data.Relationships[i], state);
_sessionId = data.SessionId;
_unavailableGuildCount = unavailableGuilds;
@@ -1495,7 +1501,30 @@ namespace Discord.WebSocket
return;
}
}
- break;
+ return;
+
+ //Relationships
+ case "RELATIONSHIP_ADD":
+ {
+ await _gatewayLogger.DebugAsync("Received Dispatch (RELATIONSHIP_ADD)").ConfigureAwait(false);
+
+ var addedModel = (payload as JToken).ToObject(_serializer);
+ var before = State.GetRelationship(addedModel.Id) ?? SocketRelationship.Create(this, State, new Relationship { Id = addedModel.Id, Type = RelationshipType.None, User = addedModel.User });
+ 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(_serializer);
+ var removed = RemoveRelationship(removedModel.Id);
+
+ await _relationshipRemovedEvent.InvokeAsync(removed);
+ return;
+ }
//Ignored (User only)
case "CHANNEL_PINS_ACK":
@@ -1798,6 +1827,21 @@ namespace Discord.WebSocket
await _gatewayLogger.DebugAsync($"Unsynced Guild ({details}).").ConfigureAwait(false);
}
+ 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);
+ }
+
internal int GetAudioId() => _nextAudioId++;
//IDiscordClient
@@ -1840,5 +1884,8 @@ namespace Discord.WebSocket
=> await StartAsync().ConfigureAwait(false);
async Task IDiscordClient.StopAsync()
=> await StopAsync().ConfigureAwait(false);
+
+ async Task> IDiscordClient.GetRelationshipsAsync(RequestOptions options)
+ => await GetRelationshipsAsync();
}
}
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketRelationship.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketRelationship.cs
new file mode 100644
index 000000000..fb8ddc75e
--- /dev/null
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketRelationship.cs
@@ -0,0 +1,27 @@
+using System.Diagnostics;
+using Model = Discord.API.Relationship;
+
+namespace Discord.WebSocket
+{
+ [DebuggerDisplay("{Type} - {User}")]
+ public class SocketRelationship : IRelationship
+ {
+ public RelationshipType Type { get; internal set; }
+
+ public IUser User { get; internal set; }
+
+ internal SocketRelationship()
+ {
+ }
+
+ internal static SocketRelationship Create(DiscordSocketClient discord, ClientState state, Model model)
+ {
+ SocketGlobalUser user = SocketGlobalUser.Create(discord, state, model.User);
+ return new SocketRelationship
+ {
+ Type = model.Type,
+ User = user
+ };
+ }
+ }
+}
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
index b7c02c2db..b4365baab 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
@@ -57,6 +57,15 @@ namespace Discord.WebSocket
public Task ModifyAsync(Action func, RequestOptions options = null)
=> 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;
}
}
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
index a0c78b93f..c8193f370 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
@@ -20,6 +20,7 @@ namespace Discord.WebSocket
public string Mention => MentionUtils.MentionUser(Id);
public Game? Game => Presence.Game;
public UserStatus Status => Presence.Status;
+ public RelationshipType Relationship => Discord.GetRelationship(Id)?.Type ?? RelationshipType.None;
internal SocketUser(DiscordSocketClient discord, ulong id)
: base(discord, id)
@@ -64,5 +65,12 @@ namespace Discord.WebSocket
public override string ToString() => $"{Username}#{Discriminator}";
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})";
internal SocketUser Clone() => MemberwiseClone() as SocketUser;
+
+ public async Task AddFriendAsync(RequestOptions options = null)
+ => await ClientHelper.AddFriendAsync(Discord, Id, options);
+ public async Task BlockUserAsync(RequestOptions options = null)
+ => await ClientHelper.BlockUserAsync(Discord, Id, options);
+ public async Task RemoveRelationshipAsync(RequestOptions options = null)
+ => await ClientHelper.RemoveRelationshipAsync(Discord, Id, options);
}
}