Simplify token kind resolution

Extra request which makes it less efficient, but much simpler code
This commit is contained in:
Tyrrrz 2022-09-16 22:46:55 +03:00
parent b8cea0d140
commit f8dac2c9d0
2 changed files with 44 additions and 43 deletions

View file

@ -22,65 +22,67 @@ public class DiscordClient
private readonly string _token; private readonly string _token;
private readonly Uri _baseUri = new("https://discord.com/api/v9/", UriKind.Absolute); private readonly Uri _baseUri = new("https://discord.com/api/v9/", UriKind.Absolute);
private TokenKind _tokenKind = TokenKind.Unknown; private TokenKind? _resolvedTokenKind;
public DiscordClient(string token) => _token = token; public DiscordClient(string token) => _token = token;
private async ValueTask<HttpResponseMessage> GetResponseAsync( private async ValueTask<HttpResponseMessage> GetResponseAsync(
string url, string url,
bool isBot, TokenKind tokenKind,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
using var request = new HttpRequestMessage(HttpMethod.Get, new Uri(_baseUri, url)); return await Http.ResponseResiliencePolicy.ExecuteAsync(async innerCancellationToken =>
{
using var request = new HttpRequestMessage(HttpMethod.Get, new Uri(_baseUri, url));
// Don't validate because token can have invalid characters // Don't validate because token can have invalid characters
// https://github.com/Tyrrrz/DiscordChatExporter/issues/828 // https://github.com/Tyrrrz/DiscordChatExporter/issues/828
request.Headers.TryAddWithoutValidation( request.Headers.TryAddWithoutValidation(
"Authorization", "Authorization",
isBot ? $"Bot {_token}" : _token tokenKind == TokenKind.Bot
); ? $"Bot {_token}"
: _token
);
return await Http.Client.SendAsync( return await Http.Client.SendAsync(
request, request,
HttpCompletionOption.ResponseHeadersRead, HttpCompletionOption.ResponseHeadersRead,
innerCancellationToken
);
}, cancellationToken);
}
private async ValueTask<TokenKind> GetTokenKindAsync(CancellationToken cancellationToken = default)
{
// Try authenticating as a user
using var userResponse = await GetResponseAsync(
"users/@me",
TokenKind.User,
cancellationToken cancellationToken
); );
if (userResponse.StatusCode != HttpStatusCode.Unauthorized)
return TokenKind.User;
// Try authenticating as a bot
using var botResponse = await GetResponseAsync(
"users/@me",
TokenKind.Bot,
cancellationToken
);
if (botResponse.StatusCode != HttpStatusCode.Unauthorized)
return TokenKind.Bot;
throw DiscordChatExporterException.Unauthorized();
} }
private async ValueTask<HttpResponseMessage> GetResponseAsync( private async ValueTask<HttpResponseMessage> GetResponseAsync(
string url, string url,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await Http.ResponseResiliencePolicy.ExecuteAsync(async innerCancellationToken => var tokenKind = _resolvedTokenKind ??= await GetTokenKindAsync(cancellationToken);
{ return await GetResponseAsync(url, tokenKind, cancellationToken);
if (_tokenKind == TokenKind.User)
return await GetResponseAsync(url, false, innerCancellationToken);
if (_tokenKind == TokenKind.Bot)
return await GetResponseAsync(url, true, innerCancellationToken);
// Try to authenticate as user
var userResponse = await GetResponseAsync(url, false, innerCancellationToken);
if (userResponse.StatusCode != HttpStatusCode.Unauthorized)
{
_tokenKind = TokenKind.User;
return userResponse;
}
userResponse.Dispose();
// Otherwise, try to authenticate as bot
var botResponse = await GetResponseAsync(url, true, innerCancellationToken);
if (botResponse.StatusCode != HttpStatusCode.Unauthorized)
{
_tokenKind = TokenKind.Bot;
return botResponse;
}
// The token is probably invalid altogether.
// Return the last response anyway, upstream should handle the error.
return botResponse;
}, cancellationToken);
} }
private async ValueTask<JsonElement> GetJsonResponseAsync( private async ValueTask<JsonElement> GetJsonResponseAsync(

View file

@ -2,7 +2,6 @@
public enum TokenKind public enum TokenKind
{ {
Unknown,
User, User,
Bot Bot
} }