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