Ejemplo n.º 1
0
        /// <exception cref="ArgumentNullException"></exception>
        async Task <DiscordMessage> CreateMessage(Snowflake channelId, HttpContent fileContent, string fileName,
                                                  CreateMessageOptions options)
        {
            if (string.IsNullOrWhiteSpace(fileName))
            {
                // Technically this is also handled when setting the field on the multipart form data
                throw new ArgumentNullException(nameof(fileName));
            }

            DiscordApiData returnData = await rest.Send(() =>
            {
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,
                                                                    $"{RestClient.BASE_URL}/channels/{channelId}/messages");

                MultipartFormDataContent data = new MultipartFormDataContent();
                data.Add(fileContent, "file", fileName);

                if (options != null)
                {
                    DiscordApiData payloadJson = options.Build();

                    data.Add(new StringContent(payloadJson.SerializeToJson()), "payload_json");
                }

                request.Content = data;

                return(request);
            }, $"channels/{channelId}/messages").ConfigureAwait(false);

            return(new DiscordMessage(this, returnData));
        }
Ejemplo n.º 2
0
        /// <exception cref="DiscordHttpApiException"></exception>
        public Task <DiscordApiData> Patch(string action, DiscordApiData data, string rateLimitRoute,
                                           CancellationToken?cancellationToken = null)
        {
            return(Send(() =>
            {
                HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), $"{BASE_URL}/{action}");
                request.Content = new StringContent(data.SerializeToJson(), Encoding.UTF8, "application/json");

                return request;
            }, rateLimitRoute, cancellationToken));
        }
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="DiscordHttpApiException"></exception>
        async Task <DiscordMessage> ExecuteWebhook(Snowflake webhookId, string token, HttpContent fileContent, string fileName,
                                                   ExecuteWebhookOptions options, bool waitAndReturnMessage)
        {
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }
            if (string.IsNullOrWhiteSpace(token))
            {
                throw new ArgumentException("Token cannot be empty or only contain whitespace characters.", nameof(token));
            }
            if (string.IsNullOrEmpty(fileName))
            {
                // Technically already handled when adding the field to the multipart form data.
                throw new ArgumentNullException(nameof(fileName));
            }

            DiscordApiData returnData = await rest.Send(() =>
            {
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,
                                                                    $"{RestClient.BASE_URL}/webhooks/{webhookId}/{token}");

                MultipartFormDataContent data = new MultipartFormDataContent();
                data.Add(fileContent, "file", fileName);

                if (options != null)
                {
                    DiscordApiData payloadJson = options.Build();
                    data.Add(new StringContent(payloadJson.SerializeToJson()), "payload_json");
                }

                request.Content = data;

                return(request);
            }, $"webhooks/{webhookId}/token").ConfigureAwait(false);

            return(waitAndReturnMessage ? new DiscordMessage(this, returnData) : null);
        }
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="DiscordWebSocketException">Thrown if the payload fails to send because of a WebSocket error.</exception>
        /// <exception cref="InvalidOperationException">Thrown if the socket is not connected.</exception>
        /// <exception cref="JsonWriterException">Thrown if the given data cannot be serialized as JSON.</exception>
        protected async Task SendAsync(DiscordApiData data)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (socket.State != WebSocketState.Open)
            {
                throw new InvalidOperationException("Cannot send data when the socket is not open.");
            }

            // Serialize the data as JSON and convert to bytes
            byte[] bytes = Encoding.UTF8.GetBytes(data.SerializeToJson());

            // Wait for any existing send operations,
            // ClientWebSocket only supports one send operation at a time.
            using (await sendLock.LockAsync().ConfigureAwait(false))
            {
                // Now that we have acquired the lock, check if the socket is still open.
                // If not, just ignore this message so we can effectively cancel any pending sends after close.
                if (socket.State == WebSocketState.Open)
                {
                    try
                    {
                        await SendData(bytes).ConfigureAwait(false);
                    }
                    catch (InvalidOperationException iex) // also catches ObjectDisposedException
                    {
                        throw new DiscordWebSocketException("The WebSocket connection was closed while sending data.",
                                                            DiscordWebSocketError.ConnectionClosed, iex);
                    }
                    catch (OperationCanceledException ocex)
                    {
                        throw new DiscordWebSocketException("The WebSocket connection was aborted while sending data.",
                                                            DiscordWebSocketError.ConnectionClosed, ocex);
                    }
                    catch (WebSocketException wsex)
                    {
                        if (wsex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)
                        {
                            throw new DiscordWebSocketException("The WebSocket connection was closed while sending data.",
                                                                DiscordWebSocketError.ConnectionClosed, wsex);
                        }
                        else
                        {
                            // The only known WebSocketException is ConnectionClosedPrematurely, so
                            // log any others to be handled later.
                            log.LogError($"[SendAsync] Unexpected WebSocketException error: code = {wsex.WebSocketErrorCode}, error = {wsex}");

                            // Should never happen
                            throw new DiscordWebSocketException("An unexpected WebSocket error occured while sending data.",
                                                                DiscordWebSocketError.Unexpected, wsex);
                        }
                    }
                    catch (Exception ex)
                    {
                        // We are not expecting any other exceptions, but since the exceptions thrown from
                        // System.Net.WebSockets.ClientWebSocket.SendAsync is not documented, log any
                        // unknown exceptions so we can handle them later.
                        log.LogError($"[SendAsync] Unhandled exception: {ex}");

                        // Should never happen, but we should consolidate everything into DiscordWebSocketException
                        // so handling exceptions we do not know about is at least consistent.
                        throw new DiscordWebSocketException("An unexpected error occured while sending data.",
                                                            DiscordWebSocketError.Unexpected, ex);
                    }
                }
            }
        }