public void ParseTwitterErrorMessage_WithApiV2Error_Parses()
        {
            TwitterErrorDetails errorDetails = TwitterErrorHandler.ParseTwitterErrorMessage(ApiV2ErrorJson);

            Assert.IsNotNull(errorDetails);
            Assert.AreEqual("Invalid Request", errorDetails.Title);
            Assert.AreEqual("One or more parameters to your request was invalid.", errorDetails.Detail);
            Assert.AreEqual("https://api.twitter.com/labs/2/problems/invalid-request", errorDetails.Type);
            List <Error> errors = errorDetails.Errors;

            Assert.IsNotNull(errors);
            Assert.AreEqual(2, errors.Count);
            Error error = errors[1];

            Assert.AreEqual("[q] is not one of [query,start_time,end_time,since_id,until_id,max_results,next_token,expansions,tweet.fields,media.fields,poll.fields,place.fields,user.fields]", error.Message);
            Dictionary <string, string[]> parameters = error.Parameters;

            Assert.IsNotNull(parameters);
            Assert.AreEqual(1, parameters.Count);
            Assert.IsTrue(parameters.ContainsKey("q"));
            string[] values = parameters["q"];
            Assert.IsNotNull(values);
            Assert.AreEqual(1, values.Count());
            string value = values.First();

            Assert.AreEqual("LINQ%20to%20Twitter", value);
        }
        public void ParseTwitterErrorMessage_WithUnrecognizedContent_SendsErrorMessage()
        {
            const string GarbageIn = "This is garbage";

            TwitterErrorDetails errorDetails = TwitterErrorHandler.ParseTwitterErrorMessage(GarbageIn);

            Assert.IsNotNull(errorDetails);
            Assert.IsTrue(errorDetails.Title?.StartsWith("Unhandled Error") ?? false);
            Assert.AreEqual(GarbageIn, errorDetails.Detail);
        }
Пример #3
0
        internal static void BuildAndThrowTwitterQueryException(string responseStr, HttpResponseMessage msg)
        {
            TwitterErrorDetails error = ParseTwitterErrorMessage(responseStr);

            throw new TwitterQueryException(error.Message)
                  {
                      ErrorCode    = error.Code,
                      StatusCode   = msg.StatusCode,
                      ReasonPhrase = msg.ReasonPhrase
                  };
        }
        public void ParseTwitterErrorMessage_WithApiV1RequestError_Parses()
        {
            TwitterErrorDetails errorDetails = TwitterErrorHandler.ParseTwitterErrorMessage(MediaErrorJson);

            Assert.IsNotNull(errorDetails);
            List <Error> errors = errorDetails.Errors;

            Assert.IsNotNull(errors);
            Assert.AreEqual(1, errors.Count);
            Error error = errors.First();

            Assert.AreEqual("/1.1/media/metadata/create.json", error.Request);
            Assert.AreEqual("media_id field must be provided.", error.Message);
        }
        public void ParseTwitterErrorMessage_WithApiV1Error_Parses()
        {
            TwitterErrorDetails errorDetails = TwitterErrorHandler.ParseTwitterErrorMessage(ApiV1ErrorJson);

            Assert.IsNotNull(errorDetails);
            List <Error> errors = errorDetails.Errors;

            Assert.IsNotNull(errors);
            Assert.AreEqual(1, errors.Count);
            Error error = errors.First();

            Assert.AreEqual(144, error.Code);
            Assert.AreEqual("No status found with that ID.", error.Message);
        }
Пример #6
0
        internal async static Task HandleUnauthorizedAsync(HttpResponseMessage msg)
        {
            string responseStr = await msg.Content.ReadAsStringAsync().ConfigureAwait(false);

            TwitterErrorDetails error = ParseTwitterErrorMessage(responseStr);

            string message = error.Message + " - Please visit the LINQ to Twitter FAQ (at the HelpLink) for help on resolving this error.";

            throw new TwitterQueryException(message)
                  {
                      HelpLink     = "https://linqtotwitter.codeplex.com/wikipage?title=LINQ%20to%20Twitter%20FAQ",
                      ErrorCode    = error.Code,
                      StatusCode   = HttpStatusCode.Unauthorized,
                      ReasonPhrase = msg.ReasonPhrase
                  };
        }
Пример #7
0
        internal async static Task HandleUnauthorizedAsync(HttpResponseMessage msg)
        {
            string responseStr = await msg.Content.ReadAsStringAsync();

            TwitterErrorDetails error = ParseTwitterErrorMessage(responseStr);

            string message = error.Message + " - Please visit the LINQ to Twitter FAQ (at the HelpLink) for help on resolving this error.";

            throw new TwitterQueryException(message)
                  {
                      HelpLink     = L2TKeys.FaqHelpUrl,
                      ErrorCode    = error.Code,
                      StatusCode   = HttpStatusCode.Unauthorized,
                      ReasonPhrase = msg.ReasonPhrase
                  };
        }
Пример #8
0
        internal static async Task HandleTooManyRequestsAsync(HttpResponseMessage msg)
        {
            string responseStr = await msg.Content.ReadAsStringAsync();

            TwitterErrorDetails error = ParseTwitterErrorMessage(responseStr);

            string message = error.Message + " - Please visit the LINQ to Twitter FAQ (at the HelpLink) for help on resolving this error.";

            throw new TwitterQueryException(message)
                  {
                      HelpLink     = L2TKeys.FaqHelpUrl,
                      ErrorCode    = error.Code,
                      StatusCode   = HttpStatusCode.SeeOther,
                      ReasonPhrase = msg.ReasonPhrase + " (HTTP 429 - Too Many Requests)"
                  };
        }
Пример #9
0
        /// <summary>
        /// Executes the command.
        /// </summary>
        /// <returns>The results of the command.</returns>
        public TwitterResponse <T> ExecuteCommand()
        {
            TwitterResponse <T> twitterResponse = new TwitterResponse <T>();

            if (this.OptionalProperties.UseSSL)
            {
                this.Uri = new Uri(this.Uri.AbsoluteUri.Replace("http://", "https://"));
            }

            // Loop through all of the custom attributes assigned to the command class
            foreach (Attribute attribute in this.GetType().GetCustomAttributes(false))
            {
                if (attribute is AuthorizedCommandAttribute)
                {
                    if (this.Tokens == null)
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Tokens are required for the \"{0}\" command.", this.GetType()));
                    }

                    if (string.IsNullOrEmpty(this.Tokens.ConsumerKey) ||
                        string.IsNullOrEmpty(this.Tokens.ConsumerSecret) ||
                        string.IsNullOrEmpty(this.Tokens.AccessToken) ||
                        string.IsNullOrEmpty(this.Tokens.AccessTokenSecret))
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Token values cannot be null when executing the \"{0}\" command.", this.GetType()));
                    }
                }
                else if (attribute is RateLimitedAttribute)
                {
                    // Get the rate limiting status
                    if (TwitterRateLimitStatus.GetStatus(this.Tokens).ResponseObject.RemainingHits == 0)
                    {
                        throw new TwitterizerException("You are being rate limited.");
                    }
                }
            }

            // Prepare the query parameters
            Dictionary <string, object> queryParameters = new Dictionary <string, object>();

            foreach (KeyValuePair <string, object> item in this.RequestParameters)
            {
                queryParameters.Add(item.Key, item.Value);
            }

            // Declare the variable to be returned
            twitterResponse.ResponseObject = default(T);
            twitterResponse.RequestUrl     = this.Uri.AbsoluteUri;
            RateLimiting rateLimiting;
            AccessLevel  accessLevel;

            byte[] responseData;

            try
            {
                WebRequestBuilder requestBuilder = new WebRequestBuilder(this.Uri, this.Verb, this.Tokens)
                {
                    Multipart = this.Multipart
                };

#if !SILVERLIGHT
                if (this.OptionalProperties != null)
                {
                    requestBuilder.Proxy = this.OptionalProperties.Proxy;
                }
#endif

                foreach (var item in queryParameters)
                {
                    requestBuilder.Parameters.Add(item.Key, item.Value);
                }

                HttpWebResponse response = requestBuilder.ExecuteRequest();

                if (response == null)
                {
                    twitterResponse.Result = RequestResult.Unknown;
                    return(twitterResponse);
                }

                responseData            = ConversionUtility.ReadStream(response.GetResponseStream());
                twitterResponse.Content = Encoding.UTF8.GetString(responseData, 0, responseData.Length);

                twitterResponse.RequestUrl = requestBuilder.RequestUri.AbsoluteUri;

#if !SILVERLIGHT
                // Parse the rate limiting HTTP Headers
                rateLimiting = ParseRateLimitHeaders(response.Headers);

                // Parse Access Level
                accessLevel = ParseAccessLevel(response.Headers);
#else
                rateLimiting = null;
                accessLevel  = AccessLevel.Unknown;
#endif

                // Lookup the status code and set the status accordingly
                SetStatusCode(twitterResponse, response.StatusCode, rateLimiting);

                twitterResponse.RateLimiting = rateLimiting;
                twitterResponse.AccessLevel  = accessLevel;
            }
            catch (WebException wex)
            {
                if (new[]
                {
#if !SILVERLIGHT
                    WebExceptionStatus.Timeout,
                    WebExceptionStatus.ConnectionClosed,
#endif
                    WebExceptionStatus.ConnectFailure
                }.Contains(wex.Status))
                {
                    twitterResponse.Result       = RequestResult.ConnectionFailure;
                    twitterResponse.ErrorMessage = wex.Message;
                    return(twitterResponse);
                }

                // The exception response should always be an HttpWebResponse, but we check for good measure.
                HttpWebResponse exceptionResponse = wex.Response as HttpWebResponse;

                if (exceptionResponse == null)
                {
                    throw;
                }

                responseData            = ConversionUtility.ReadStream(exceptionResponse.GetResponseStream());
                twitterResponse.Content = Encoding.UTF8.GetString(responseData, 0, responseData.Length);

#if !SILVERLIGHT
                rateLimiting = ParseRateLimitHeaders(exceptionResponse.Headers);

                // Parse Access Level
                accessLevel = ParseAccessLevel(exceptionResponse.Headers);
#else
                rateLimiting = null;
                accessLevel  = AccessLevel.Unknown;
#endif

                // Try to read the error message, if there is one.
                try
                {
                    TwitterErrorDetails errorDetails = SerializationHelper <TwitterErrorDetails> .Deserialize(responseData);

                    twitterResponse.ErrorMessage = errorDetails.ErrorMessage;
                }
                catch (Exception)
                {
                    // Occasionally, Twitter responds with XML error data even though we asked for json.
                    // This is that scenario. We will deal with it by doing nothing. It's up to the developer to deal with it.
                }

                // Lookup the status code and set the status accordingly
                SetStatusCode(twitterResponse, exceptionResponse.StatusCode, rateLimiting);

                twitterResponse.RateLimiting = rateLimiting;
                twitterResponse.AccessLevel  = accessLevel;

                if (wex.Status == WebExceptionStatus.UnknownError)
                {
                    throw;
                }

                return(twitterResponse);
            }

            try
            {
                twitterResponse.ResponseObject = SerializationHelper <T> .Deserialize(responseData, this.DeserializationHandler);
            }
            catch (Newtonsoft.Json.JsonReaderException)
            {
                twitterResponse.ErrorMessage = "Unable to parse JSON";
                twitterResponse.Result       = RequestResult.Unknown;
                return(twitterResponse);
            }
            catch (Newtonsoft.Json.JsonSerializationException)
            {
                twitterResponse.ErrorMessage = "Unable to parse JSON";
                twitterResponse.Result       = RequestResult.Unknown;
                return(twitterResponse);
            }

            // Pass the current oauth tokens into the new object, so method calls from there will keep the authentication.
            twitterResponse.Tokens = this.Tokens;

            return(twitterResponse);
        }
        /// <summary>
        /// Executes the command.
        /// </summary>
        /// <returns>The results of the command.</returns>
        public async Task <TwitterResponse <T> > ExecuteCommand()
        {
            TwitterResponse <T> twitterResponse = new TwitterResponse <T>();

            if (this.OptionalProperties.UseSSL)
            {
                this.Uri = new Uri(this.Uri.AbsoluteUri.Replace("http://", "https://"));
            }

            // Loop through all of the custom attributes assigned to the command class
            foreach (CustomAttributeData attribute in System.Reflection.IntrospectionExtensions.GetTypeInfo(this.GetType()).CustomAttributes)
            {
                if (attribute.AttributeType == typeof(AuthorizedCommandAttribute))
                {
                    if (this.Tokens == null)
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Tokens are required for the \"{0}\" command.", this.GetType()));
                    }

                    if (string.IsNullOrEmpty(this.Tokens.ConsumerKey) ||
                        string.IsNullOrEmpty(this.Tokens.ConsumerSecret) ||
                        string.IsNullOrEmpty(this.Tokens.AccessToken) ||
                        string.IsNullOrEmpty(this.Tokens.AccessTokenSecret))
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Token values cannot be null when executing the \"{0}\" command.", this.GetType()));
                    }
                }
                else if (attribute.AttributeType == typeof(RateLimitedAttribute))
                {
                    //Get the rate limiting status
                    if ((await Account.RateLimitStatusAsync(this.Tokens)).ResponseObject.RemainingHits == 0)
                    {
                        throw new TwitterizerException("You are being rate limited.");
                    }
                }
            }

            // Prepare the query parameters
            Dictionary <string, object> queryParameters = new Dictionary <string, object>();

            foreach (KeyValuePair <string, object> item in this.RequestParameters)
            {
                queryParameters.Add(item.Key, item.Value);
            }

            // Declare the variable to be returned
            twitterResponse.ResponseObject = default(T);
            twitterResponse.RequestUrl     = this.Uri.AbsoluteUri;
            RateLimiting        rateLimiting = null;
            AccessLevel         accessLevel;
            string              responseData = null;
            HttpResponseMessage response     = null;

            try
            {
                WebRequestBuilder requestBuilder = new WebRequestBuilder(this.Uri, this.Verb, this.Tokens)
                {
                    Multipart = this.Multipart
                };

                foreach (var item in queryParameters)
                {
                    requestBuilder.Parameters.Add(item.Key, item.Value);
                }

                try
                {
                    response = await requestBuilder.ExecuteRequestAsync();
                }
                catch
                {
                    ;
                }

                if (response == null)
                {
                    twitterResponse.Result = RequestResult.Unknown;
                    return(twitterResponse);
                }

                responseData = await response.Content.ReadAsStringAsync(); // ConversionUtility.ReadStream(await response.Content.ReadAsStreamAsync());

                twitterResponse.Content = responseData;                    // Encoding.UTF8.GetString(responseData, 0, responseData.Length);

                twitterResponse.RequestUrl = requestBuilder.RequestUri.AbsoluteUri;

                // Parse the rate limiting HTTP Headers
                rateLimiting = ParseRateLimitHeaders(response.Headers);

                // Parse Access Level
                accessLevel = ParseAccessLevel(response.Headers);

                // Lookup the status code and set the status accordingly
                SetStatusCode(twitterResponse, response.StatusCode, rateLimiting);

                twitterResponse.RateLimiting = rateLimiting;
                twitterResponse.AccessLevel  = accessLevel;

                response.EnsureSuccessStatusCode();
            }
            catch (HttpRequestException wex)
            {
                // Lookup the status code and set the status accordingly
                SetStatusCode(twitterResponse, response.StatusCode, rateLimiting);

                twitterResponse.ErrorMessage = wex.Message;

                // Try to read the error message, if there is one.
                try
                {
                    TwitterErrorDetails errorDetails = SerializationHelper <TwitterErrorDetails> .Deserialize(responseData);

                    twitterResponse.ErrorMessage = errorDetails.ErrorMessage;
                }
                catch (Exception)
                {
                    // Occasionally, Twitter responds with XML error data even though we asked for json.
                    // This is that scenario. We will deal with it by doing nothing. It's up to the developer to deal with it.
                }

                return(twitterResponse);
            }

            try
            {
                twitterResponse.ResponseObject = SerializationHelper <T> .Deserialize(responseData, this.DeserializationHandler);
            }
            catch (Newtonsoft.Json.JsonReaderException)
            {
                twitterResponse.ErrorMessage = "Unable to parse JSON";
                twitterResponse.Result       = RequestResult.Unknown;
                return(twitterResponse);
            }
            catch (Newtonsoft.Json.JsonSerializationException jse)
            {
                twitterResponse.ErrorMessage = String.Format("Unable to parse JSON: {0}", jse.Message);
                twitterResponse.Result       = RequestResult.Unknown;
                return(twitterResponse);
            }

            // Pass the current oauth tokens into the new object, so method calls from there will keep the authentication.
            twitterResponse.Tokens = this.Tokens;

            return(twitterResponse);
        }