| @@ -38,6 +38,7 @@ namespace Discord.API | |||
| public TokenType AuthTokenType { get; private set; } | |||
| public User CurrentUser { get; private set; } | |||
| public RequestQueue RequestQueue { get; private set; } | |||
| internal bool FetchCurrentUser { get; set; } | |||
| public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, JsonSerializer serializer = null, RequestQueue requestQueue = null) | |||
| { | |||
| @@ -45,6 +46,7 @@ namespace Discord.API | |||
| _userAgent = userAgent; | |||
| _serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver() }; | |||
| RequestQueue = requestQueue; | |||
| FetchCurrentUser = true; | |||
| _stateLock = new SemaphoreSlim(1, 1); | |||
| @@ -113,7 +115,8 @@ namespace Discord.API | |||
| _authToken = token; | |||
| _restClient.SetHeader("authorization", GetPrefixedToken(AuthTokenType, _authToken)); | |||
| CurrentUser = await GetMyUserAsync(new RequestOptions { IgnoreState = true }); | |||
| if (FetchCurrentUser) | |||
| CurrentUser = await GetMyUserAsync(new RequestOptions { IgnoreState = true }); | |||
| LoginState = LoginState.LoggedIn; | |||
| } | |||
| @@ -8,6 +8,7 @@ using Newtonsoft.Json; | |||
| using Newtonsoft.Json.Linq; | |||
| using System; | |||
| using System.Collections.Concurrent; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.IO.Compression; | |||
| using System.Text; | |||
| @@ -67,13 +68,16 @@ namespace Discord.API | |||
| public ConnectionState ConnectionState { get; private set; } | |||
| public DiscordRpcApiClient(string clientId, string userAgent, string origin, RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, JsonSerializer serializer = null, RequestQueue requestQueue = null) | |||
| public DiscordRpcApiClient(string clientId, string userAgent, string origin, RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, | |||
| JsonSerializer serializer = null, RequestQueue requestQueue = null) | |||
| : base(restClientProvider, userAgent, serializer, requestQueue) | |||
| { | |||
| _connectionLock = new SemaphoreSlim(1, 1); | |||
| _clientId = clientId; | |||
| _origin = origin; | |||
| FetchCurrentUser = false; | |||
| _requestQueue = requestQueue ?? new RequestQueue(); | |||
| _requests = new ConcurrentDictionary<Guid, RpcRequest>(); | |||
| @@ -169,7 +173,7 @@ namespace Discord.API | |||
| if (!success) | |||
| throw new Exception("Unable to connect to the RPC server."); | |||
| SetBaseUrl($"https://{uuid}.discordapp.io:{port}/"); | |||
| ConnectionState = ConnectionState.Connected; | |||
| } | |||
| @@ -209,7 +213,6 @@ namespace Discord.API | |||
| public async Task<TResponse> SendRpcAsync<TResponse>(string cmd, object payload, Optional<string> evt = default(Optional<string>), RequestOptions options = null) | |||
| where TResponse : class | |||
| { | |||
| options.IgnoreState = false; | |||
| return await SendRpcAsyncInternal<TResponse>(cmd, payload, evt, options).ConfigureAwait(false); | |||
| } | |||
| private async Task<TResponse> SendRpcAsyncInternal<TResponse>(string cmd, object payload, Optional<string> evt, RequestOptions options) | |||
| @@ -246,7 +249,7 @@ namespace Discord.API | |||
| options.IgnoreState = true; | |||
| return await SendRpcAsync<AuthenticateResponse>("AUTHENTICATE", msg, options: options).ConfigureAwait(false); | |||
| } | |||
| public async Task<AuthorizeResponse> SendAuthorizeAsync(string[] scopes, string rpcToken = null, RequestOptions options = null) | |||
| public async Task<AuthorizeResponse> SendAuthorizeAsync(IReadOnlyCollection<string> scopes, string rpcToken = null, RequestOptions options = null) | |||
| { | |||
| options = RequestOptions.CreateOrClone(options); | |||
| var msg = new AuthorizeParams | |||
| @@ -1,5 +1,6 @@ | |||
| #pragma warning disable CS1591 | |||
| using Newtonsoft.Json; | |||
| using System.Collections.Generic; | |||
| namespace Discord.API.Rpc | |||
| { | |||
| @@ -8,7 +9,7 @@ namespace Discord.API.Rpc | |||
| [JsonProperty("client_id")] | |||
| public string ClientId { get; set; } | |||
| [JsonProperty("scopes")] | |||
| public string[] Scopes { get; set; } | |||
| public IReadOnlyCollection<string> Scopes { get; set; } | |||
| [JsonProperty("rpc_token")] | |||
| public Optional<string> RpcToken { get; set; } | |||
| } | |||
| @@ -42,18 +42,18 @@ namespace Discord.Rpc | |||
| private readonly AsyncEvent<Func<Task>> _voiceStateUpdatedEvent = new AsyncEvent<Func<Task>>(); | |||
| //Messages | |||
| public event Func<ulong, IMessage, Task> MessageReceived | |||
| public event Func<RpcMessage, Task> MessageReceived | |||
| { | |||
| add { _messageReceivedEvent.Add(value); } | |||
| remove { _messageReceivedEvent.Remove(value); } | |||
| } | |||
| private readonly AsyncEvent<Func<ulong, IMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<ulong, IMessage, Task>>(); | |||
| public event Func<ulong, IMessage, Task> MessageUpdated | |||
| private readonly AsyncEvent<Func<RpcMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<RpcMessage, Task>>(); | |||
| public event Func<RpcMessage, Task> MessageUpdated | |||
| { | |||
| add { _messageUpdatedEvent.Add(value); } | |||
| remove { _messageUpdatedEvent.Remove(value); } | |||
| } | |||
| private readonly AsyncEvent<Func<ulong, IMessage, Task>> _messageUpdatedEvent = new AsyncEvent<Func<ulong, IMessage, Task>>(); | |||
| private readonly AsyncEvent<Func<RpcMessage, Task>> _messageUpdatedEvent = new AsyncEvent<Func<RpcMessage, Task>>(); | |||
| public event Func<ulong, ulong, Task> MessageDeleted | |||
| { | |||
| add { _messageDeletedEvent.Add(value); } | |||
| @@ -6,6 +6,8 @@ using Discord.Rest; | |||
| using Newtonsoft.Json; | |||
| using Newtonsoft.Json.Linq; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Threading; | |||
| using System.Threading.Tasks; | |||
| @@ -22,11 +24,15 @@ namespace Discord.Rpc | |||
| private bool _canReconnect; | |||
| public ConnectionState ConnectionState { get; private set; } | |||
| public IReadOnlyCollection<string> Scopes { get; private set; } | |||
| public DateTimeOffset TokenExpiresAt { get; private set; } | |||
| //From DiscordRpcConfig | |||
| internal int ConnectionTimeout { get; private set; } | |||
| public new API.DiscordRpcApiClient ApiClient => base.ApiClient as API.DiscordRpcApiClient; | |||
| public new RestSelfUser CurrentUser { get { return base.CurrentUser as RestSelfUser; } private set { base.CurrentUser = value; } } | |||
| public RestApplication CurrentApplication { get; private set; } | |||
| /// <summary> Creates a new RPC discord client. </summary> | |||
| public DiscordRpcClient(string clientId, string origin) | |||
| @@ -58,6 +64,7 @@ namespace Discord.Rpc | |||
| await _rpcLogger.WarningAsync($"Connection Closed").ConfigureAwait(false); | |||
| }; | |||
| } | |||
| private static API.DiscordRpcApiClient CreateApiClient(string clientId, string origin, DiscordRpcConfig config) | |||
| => new API.DiscordRpcApiClient(clientId, DiscordRestConfig.UserAgent, origin, config.RestClientProvider, config.WebSocketProvider, requestQueue: new RequestQueue()); | |||
| @@ -286,19 +293,21 @@ namespace Discord.Rpc | |||
| { | |||
| await _rpcLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false); | |||
| var data = (payload.Value as JToken).ToObject<ReadyEvent>(_serializer); | |||
| var cancelToken = _cancelToken; | |||
| RequestOptions options = new RequestOptions | |||
| { | |||
| //CancellationToken = _cancelToken //TODO: Implement | |||
| }; | |||
| var _ = Task.Run(async () => | |||
| { | |||
| try | |||
| { | |||
| RequestOptions options = new RequestOptions | |||
| { | |||
| //CancellationToken = cancelToken //TODO: Implement | |||
| }; | |||
| if (LoginState != LoginState.LoggedOut) | |||
| await ApiClient.SendAuthenticateAsync(options).ConfigureAwait(false); //Has bearer | |||
| var response = await ApiClient.SendAuthenticateAsync(options).ConfigureAwait(false); | |||
| CurrentUser = RestSelfUser.Create(this, response.User); | |||
| CurrentApplication = RestApplication.Create(this, response.Application); | |||
| Scopes = response.Scopes; | |||
| TokenExpiresAt = response.Expires; | |||
| var __ = _connectTask.TrySetResultAsync(true); //Signal the .Connect() call to complete | |||
| await _rpcLogger.InfoAsync("Ready").ConfigureAwait(false); | |||
| @@ -361,20 +370,20 @@ namespace Discord.Rpc | |||
| //Messages | |||
| case "MESSAGE_CREATE": | |||
| { | |||
| /*await _rpcLogger.DebugAsync("Received Dispatch (MESSAGE_CREATE)").ConfigureAwait(false); | |||
| await _rpcLogger.DebugAsync("Received Dispatch (MESSAGE_CREATE)").ConfigureAwait(false); | |||
| var data = (payload.Value as JToken).ToObject<MessageEvent>(_serializer); | |||
| var msg = new RpcMessage(this, data.Message); | |||
| var msg = RpcMessage.Create(this, data.ChannelId, data.Message); | |||
| await _messageReceivedEvent.InvokeAsync(data.ChannelId, msg).ConfigureAwait(false);*/ | |||
| await _messageReceivedEvent.InvokeAsync(msg).ConfigureAwait(false); | |||
| } | |||
| break; | |||
| case "MESSAGE_UPDATE": | |||
| { | |||
| /*await _rpcLogger.DebugAsync("Received Dispatch (MESSAGE_UPDATE)").ConfigureAwait(false); | |||
| await _rpcLogger.DebugAsync("Received Dispatch (MESSAGE_UPDATE)").ConfigureAwait(false); | |||
| var data = (payload.Value as JToken).ToObject<MessageEvent>(_serializer); | |||
| var msg = new RpcMessage(this, data.Message); | |||
| var msg = RpcMessage.Create(this, data.ChannelId, data.Message); | |||
| await _messageUpdatedEvent.InvokeAsync(data.ChannelId, msg).ConfigureAwait(false);*/ | |||
| await _messageUpdatedEvent.InvokeAsync(msg).ConfigureAwait(false); | |||
| } | |||
| break; | |||
| case "MESSAGE_DELETE": | |||
| @@ -9,7 +9,7 @@ namespace Discord.Rpc | |||
| public const int PortRangeStart = 6463; | |||
| public const int PortRangeEnd = 6472; | |||
| /// <summary> Gets or sets the time, in milliseconds, to wait for a connection to complete before aborting. </summary> | |||
| public int ConnectionTimeout { get; set; } = 30000; | |||