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); }
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); }
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 }; }
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 }; }
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)" }; }
/// <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); }