@@ -25,10 +25,15 @@ namespace Discord.API | |||
private readonly IRestClient _restClient; | |||
private readonly CancellationToken _cancelToken; | |||
private readonly JsonSerializer _serializer; | |||
public TokenType AuthTokenType { get; private set; } | |||
public IRestClient RestClient { get; private set; } | |||
public IRequestQueue RequestQueue { get; private set; } | |||
internal DiscordRawClient(RestClientProvider restClientProvider, CancellationToken cancelToken, TokenType authTokenType, string authToken) | |||
{ | |||
_cancelToken = cancelToken; | |||
AuthTokenType = authTokenType; | |||
switch (authTokenType) | |||
{ | |||
@@ -11,8 +11,6 @@ namespace Discord | |||
int AFKTimeout { get; } | |||
/// <summary> Returns true if this guild is embeddable (e.g. widget) </summary> | |||
bool IsEmbeddable { get; } | |||
/// <summary> Returns true if the current user owns this guild. </summary> | |||
bool IsOwner { get; } | |||
/// <summary> Gets the name of this guild. </summary> | |||
string Name { get; } | |||
int VerificationLevel { get; } | |||
@@ -9,8 +9,6 @@ namespace Discord | |||
{ | |||
/// <summary> Gets the time of this message's last edit, if any. </summary> | |||
DateTime? EditedTimestamp { get; } | |||
/// <summary> Returns true if this message originated from the logged-in account. </summary> | |||
bool IsAuthor { get; } | |||
/// <summary> Returns true if this message was sent as a text-to-speech message. </summary> | |||
bool IsTTS { get; } | |||
/// <summary> Returns the original, unprocessed text for this message. </summary> | |||
@@ -12,8 +12,6 @@ namespace Discord | |||
ushort Discriminator { get; } | |||
/// <summary> Returns true if this user is a bot account. </summary> | |||
bool IsBot { get; } | |||
/// <summary> Returns true is this user is the current logged-in account. </summary> | |||
bool IsCurrentUser { get; } | |||
/// <summary> Gets the current status of this user. </summary> | |||
UserStatus Status { get; } | |||
/// <summary> Gets the username for this user. </summary> | |||
@@ -1,15 +1,18 @@ | |||
using Discord.API; | |||
using Discord.Net.Rest; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Threading.Tasks; | |||
namespace Discord | |||
{ | |||
//TODO: Add docstrings | |||
public interface IDiscordClient | |||
{ | |||
ISelfUser CurrentUser { get; } | |||
TokenType AuthTokenType { get; } | |||
DiscordRawClient BaseClient { get; } | |||
//IMessageQueue MessageQueue { get; } | |||
IRestClient RestClient { get; } | |||
IRequestQueue RequestQueue { get; } | |||
Task Login(TokenType tokenType, string token); | |||
Task Logout(); | |||
@@ -4,6 +4,7 @@ using System.Threading.Tasks; | |||
namespace Discord.Net.Rest | |||
{ | |||
//TODO: Add docstrings | |||
public interface IRestClient | |||
{ | |||
void SetHeader(string key, string value); | |||
@@ -2,6 +2,7 @@ using System.Threading.Tasks; | |||
namespace Discord.Net.Rest | |||
{ | |||
//TODO: Add docstrings | |||
public interface IRequestQueue | |||
{ | |||
Task Clear(GlobalBucket type); | |||
@@ -1,11 +1,13 @@ | |||
using Discord.API.Rest; | |||
using Discord.Logging; | |||
using Discord.Net; | |||
using Discord.Net.Rest; | |||
using Newtonsoft.Json.Linq; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
@@ -22,10 +24,14 @@ namespace Discord.Rest | |||
private CancellationTokenSource _cancelTokenSource; | |||
private bool _isDisposed; | |||
private string _userAgent; | |||
private SelfUser _currentUser; | |||
public bool IsLoggedIn { get; private set; } | |||
internal API.DiscordRawClient BaseClient { get; private set; } | |||
internal SelfUser CurrentUser { get; private set; } | |||
public API.DiscordRawClient BaseClient { get; private set; } | |||
public TokenType AuthTokenType => BaseClient.AuthTokenType; | |||
public IRestClient RestClient => BaseClient.RestClient; | |||
public IRequestQueue RequestQueue => BaseClient.RequestQueue; | |||
public DiscordClient(DiscordConfig config = null) | |||
{ | |||
@@ -64,9 +70,13 @@ namespace Discord.Rest | |||
//MessageQueue = new MessageQueue(RestClient, _restLogger); | |||
//await MessageQueue.Start(_cancelTokenSource.Token).ConfigureAwait(false); | |||
var currentUser = await BaseClient.GetCurrentUser().ConfigureAwait(false); | |||
CurrentUser = new SelfUser(this, currentUser); | |||
try | |||
{ | |||
var currentUser = await BaseClient.GetCurrentUser().ConfigureAwait(false); | |||
_currentUser = new SelfUser(this, currentUser); | |||
} | |||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.Unauthorized && tokenType == TokenType.Bearer) { } //Ignore 401 if Bearer doesnt have identity | |||
_cancelTokenSource = cancelTokenSource; | |||
IsLoggedIn = true; | |||
@@ -173,25 +183,25 @@ namespace Discord.Rest | |||
return new PublicUser(this, model); | |||
return null; | |||
} | |||
public async Task<IUser> GetUser(string username, ushort discriminator) | |||
public async Task<User> GetUser(string username, ushort discriminator) | |||
{ | |||
var model = await BaseClient.GetUser(username, discriminator).ConfigureAwait(false); | |||
if (model != null) | |||
return new PublicUser(this, model); | |||
return null; | |||
} | |||
public async Task<ISelfUser> GetCurrentUser() | |||
public async Task<SelfUser> GetCurrentUser() | |||
{ | |||
var currentUser = CurrentUser; | |||
if (currentUser == null) | |||
var user = _currentUser; | |||
if (user == null) | |||
{ | |||
var model = await BaseClient.GetCurrentUser().ConfigureAwait(false); | |||
currentUser = new SelfUser(this, model); | |||
CurrentUser = currentUser; | |||
user = new SelfUser(this, model); | |||
_currentUser = user; | |||
} | |||
return currentUser; | |||
return user; | |||
} | |||
public async Task<IEnumerable<IUser>> QueryUsers(string query, int limit) | |||
public async Task<IEnumerable<User>> QueryUsers(string query, int limit) | |||
{ | |||
var models = await BaseClient.QueryUsers(query, limit).ConfigureAwait(false); | |||
return models.Select(x => new PublicUser(this, x)); | |||
@@ -225,7 +235,6 @@ namespace Discord.Rest | |||
public void Dispose() => Dispose(true); | |||
API.DiscordRawClient IDiscordClient.BaseClient => BaseClient; | |||
ISelfUser IDiscordClient.CurrentUser => CurrentUser; | |||
async Task<IChannel> IDiscordClient.GetChannel(ulong id) | |||
=> await GetChannel(id).ConfigureAwait(false); | |||
@@ -243,6 +252,10 @@ namespace Discord.Rest | |||
=> await CreateGuild(name, region, jpegIcon).ConfigureAwait(false); | |||
async Task<IUser> IDiscordClient.GetUser(ulong id) | |||
=> await GetUser(id).ConfigureAwait(false); | |||
async Task<IUser> IDiscordClient.GetUser(string username, ushort discriminator) | |||
=> await GetUser(username, discriminator).ConfigureAwait(false); | |||
async Task<ISelfUser> IDiscordClient.GetCurrentUser() | |||
=> await GetCurrentUser().ConfigureAwait(false); | |||
async Task<IEnumerable<IUser>> IDiscordClient.QueryUsers(string query, int limit) | |||
=> await QueryUsers(query, limit).ConfigureAwait(false); | |||
async Task<IEnumerable<IVoiceRegion>> IDiscordClient.GetVoiceRegions() | |||
@@ -20,8 +20,6 @@ namespace Discord.Rest | |||
/// <inheritdoc /> | |||
public DateTime CreatedAt => DateTimeHelper.FromSnowflake(Id); | |||
/// <inheritdoc /> | |||
public IEnumerable<IUser> Users => ImmutableArray.Create<IUser>(Discord.CurrentUser, Recipient); | |||
internal DMChannel(DiscordClient discord, Model model) | |||
{ | |||
@@ -39,20 +37,23 @@ namespace Discord.Rest | |||
} | |||
/// <inheritdoc /> | |||
public IUser GetUser(ulong id) | |||
public async Task<IUser> GetUser(ulong id) | |||
{ | |||
var currentUser = await Discord.GetCurrentUser().ConfigureAwait(false); | |||
if (id == Recipient.Id) | |||
return Recipient; | |||
else if (id == Discord.CurrentUser.Id) | |||
return Discord.CurrentUser; | |||
else if (id == currentUser.Id) | |||
return currentUser; | |||
else | |||
return null; | |||
} | |||
public IEnumerable<IUser> GetUsers() | |||
/// <inheritdoc /> | |||
public async Task<IEnumerable<IUser>> GetUsers() | |||
{ | |||
return ImmutableArray.Create<IUser>(Discord.CurrentUser, Recipient); | |||
var currentUser = await Discord.GetCurrentUser().ConfigureAwait(false); | |||
return ImmutableArray.Create<IUser>(currentUser, Recipient); | |||
} | |||
/// <inheritdoc /> | |||
public async Task<IEnumerable<Message>> GetMessages(int limit = DiscordConfig.MaxMessagesPerBatch) | |||
{ | |||
@@ -124,10 +125,10 @@ namespace Discord.Rest | |||
IDMUser IDMChannel.Recipient => Recipient; | |||
Task<IEnumerable<IUser>> IChannel.GetUsers() | |||
=> Task.FromResult(GetUsers()); | |||
Task<IUser> IChannel.GetUser(ulong id) | |||
=> Task.FromResult(GetUser(id)); | |||
async Task<IEnumerable<IUser>> IChannel.GetUsers() | |||
=> await GetUsers().ConfigureAwait(false); | |||
async Task<IUser> IChannel.GetUser(ulong id) | |||
=> await GetUser(id).ConfigureAwait(false); | |||
Task<IMessage> IMessageChannel.GetMessage(ulong id) | |||
=> throw new NotSupportedException(); | |||
async Task<IEnumerable<IMessage>> IMessageChannel.GetMessages(int limit) | |||
@@ -46,8 +46,6 @@ namespace Discord.Rest | |||
/// <inheritdoc /> | |||
public DateTime CreatedAt => DateTimeHelper.FromSnowflake(Id); | |||
/// <inheritdoc /> | |||
public bool IsOwner => OwnerId == Discord.CurrentUser.Id; | |||
/// <inheritdoc /> | |||
public string IconUrl => API.CDN.GetGuildIconUrl(Id, _iconId); | |||
/// <inheritdoc /> | |||
public string SplashUrl => API.CDN.GetGuildSplashUrl(Id, _splashId); | |||
@@ -157,15 +155,11 @@ namespace Discord.Rest | |||
/// <inheritdoc /> | |||
public async Task Leave() | |||
{ | |||
if (IsOwner) | |||
throw new InvalidOperationException("Unable to leave a guild the current user owns."); | |||
await Discord.BaseClient.LeaveGuild(Id).ConfigureAwait(false); | |||
} | |||
/// <inheritdoc /> | |||
public async Task Delete() | |||
{ | |||
if (!IsOwner) | |||
throw new InvalidOperationException("Unable to delete a guild the current user does not own."); | |||
await Discord.BaseClient.DeleteGuild(Id).ConfigureAwait(false); | |||
} | |||
@@ -317,7 +311,8 @@ namespace Discord.Rest | |||
/// <summary> Gets a the current user. </summary> | |||
public async Task<GuildUser> GetCurrentUser() | |||
{ | |||
return await GetUser(Discord.CurrentUser.Id).ConfigureAwait(false); | |||
var currentUser = await Discord.GetCurrentUser().ConfigureAwait(false); | |||
return await GetUser(currentUser.Id).ConfigureAwait(false); | |||
} | |||
public async Task<int> PruneUsers(int days = 30, bool simulate = false) | |||
{ | |||
@@ -41,8 +41,6 @@ namespace Discord.Rest | |||
/// <inheritdoc /> | |||
public DateTime CreatedAt => DateTimeHelper.FromSnowflake(Id); | |||
/// <inheritdoc /> | |||
public bool IsAuthor => Discord.CurrentUser.Id == Author.Id; | |||
internal DiscordClient Discord => (Channel as TextChannel)?.Discord ?? (Channel as DMChannel).Discord; | |||
internal Message(IMessageChannel channel, Model model) | |||
@@ -84,7 +84,7 @@ namespace Discord.Rest | |||
var args = new ModifyGuildMemberParams(); | |||
func(args); | |||
bool isCurrentUser = IsCurrentUser; | |||
bool isCurrentUser = (await Discord.GetCurrentUser().ConfigureAwait(false)).Id == Id; | |||
if (isCurrentUser && args.Nickname.IsSpecified) | |||
{ | |||
var nickArgs = new ModifyCurrentUserNickParams | |||
@@ -92,6 +92,7 @@ namespace Discord.Rest | |||
Nickname = args.Nickname.Value | |||
}; | |||
await Discord.BaseClient.ModifyCurrentUserNick(Guild.Id, nickArgs).ConfigureAwait(false); | |||
args.Nickname = new API.Optional<string>(); //Remove | |||
} | |||
if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.Roles.IsSpecified) | |||
@@ -28,8 +28,6 @@ namespace Discord.Rest | |||
public string Mention => MentionHelper.Mention(this, false); | |||
/// <inheritdoc /> | |||
public string NicknameMention => MentionHelper.Mention(this, true); | |||
/// <inheritdoc /> | |||
public bool IsCurrentUser => Id == Discord.CurrentUser.Id; | |||
internal User(Model model) | |||
{ | |||