/// <summary> /// Parses the rate limit headers. /// </summary> /// <param name="responseHeaders">The headers of the web response.</param> /// <returns>An object that contains the rate-limiting info contained in the response headers</returns> private static RateLimiting ParseRateLimitHeaders(WebHeaderCollection responseHeaders) { RateLimiting rateLimiting = new RateLimiting(); if (responseHeaders.AllKeys.Contains("X-RateLimit-Limit")) { rateLimiting.Total = int.Parse(responseHeaders["X-RateLimit-Limit"], CultureInfo.InvariantCulture); } if (responseHeaders.AllKeys.Contains("X-RateLimit-Remaining")) { rateLimiting.Remaining = int.Parse(responseHeaders["X-RateLimit-Remaining"], CultureInfo.InvariantCulture); } if (!string.IsNullOrEmpty(responseHeaders["X-RateLimit-Reset"])) { rateLimiting.ResetDate = DateTime.SpecifyKind(new DateTime(1970, 1, 1, 0, 0, 0, 0) .AddSeconds(double.Parse(responseHeaders["X-RateLimit-Reset"], CultureInfo.InvariantCulture)), DateTimeKind.Utc); } else if (!string.IsNullOrEmpty(responseHeaders["Retry-After"])) { rateLimiting.ResetDate = DateTime.UtcNow.AddSeconds(Convert.ToInt32(responseHeaders["Retry-After"])); } return(rateLimiting); }
internal static CommandResult ShowRateLimitDetails() { if (!IsInitiated) { return(CommandResult.NotInitiated); } var v = new VerifyCredentialsOptions(); v.UseSSL = true; var Response = TwitterAccount.VerifyCredentials(Tokens, v); if (Response.Result == RequestResult.Success) { TwitterUser acc = Response.ResponseObject; RateLimiting status = Response.RateLimiting; Form.AppendLineToOutput("Screenname : " + acc.ScreenName); Form.AppendLineToOutput("Hourly limit : " + status.Total); Form.AppendLineToOutput("Remaining hits : " + status.Remaining); Form.AppendLineToOutput("Reset time : " + status.ResetDate.ToLocalTime() + " (" + DateTime.Now.ToUniversalTime().Subtract(status.ResetDate).Duration().TotalMinutes + " mins left)"); return(CommandResult.Success); } else { HandleTwitterizerError <TwitterUser>(Response); return(CommandResult.Failure); } }
private void StartDialogDebounced(object sender, EventArgs args) { RateLimiting.Debounce(nameof(StartDialogDebounced), 1000, () => { var tile = Game1.currentLocation?.currentEvent?.getActorByName("Lewis")?.getTileLocation(); if (tile != null) { Vector2 mousePosition = tile.Value.ConvertTileToMouseCoords(); var mouseState = new MouseState(Convert.ToInt32(mousePosition.X), Convert.ToInt32(mousePosition.Y), 0, ButtonState.Released, ButtonState.Released, ButtonState.Pressed, ButtonState.Released, ButtonState.Released); Game1.setMousePosition(new Point(Convert.ToInt32(mousePosition.X), Convert.ToInt32(mousePosition.Y))); Game1.pressActionButton(new KeyboardState(), mouseState, new GamePadState()); ViewportChanged -= StartDialogDebounced; } }); }
/// <summary> /// Parses the rate limit headers. /// </summary> /// <param name="responseHeaders">The headers of the web response.</param> /// <returns>An object that contains the rate-limiting info contained in the response headers</returns> private static RateLimiting ParseRateLimitHeaders(HttpResponseHeaders responseHeaders) { RateLimiting rateLimiting = new RateLimiting(); if (responseHeaders.Contains("X-RateLimit-Limit")) { rateLimiting.Total = int.Parse(responseHeaders.GetValues("X-RateLimit-Limit").First(), CultureInfo.InvariantCulture); } if (responseHeaders.Contains("X-RateLimit-Remaining")) { rateLimiting.Remaining = int.Parse(responseHeaders.GetValues("X-RateLimit-Remaining").First(), CultureInfo.InvariantCulture); } if (responseHeaders.Contains("X-RateLimit-Reset")) { rateLimiting.ResetDate = DateTime.SpecifyKind(new DateTime(1970, 1, 1, 0, 0, 0, 0) .AddSeconds(double.Parse(responseHeaders.GetValues("X-RateLimit-Reset").First(), CultureInfo.InvariantCulture)), DateTimeKind.Utc); } return(rateLimiting); }
/// <summary> /// Sets the status code. /// </summary> /// <param name="twitterResponse">The twitter response.</param> /// <param name="statusCode">The status code.</param> /// <param name="rateLimiting">The rate limiting.</param> private static void SetStatusCode(TwitterResponse <T> twitterResponse, HttpStatusCode statusCode, RateLimiting rateLimiting) { switch (statusCode) { case HttpStatusCode.OK: twitterResponse.Result = RequestResult.Success; break; case HttpStatusCode.BadRequest: twitterResponse.Result = (rateLimiting != null && rateLimiting.Remaining == 0) ? RequestResult.RateLimited : RequestResult.BadRequest; break; case (HttpStatusCode)420: //Rate Limited from Search/Trends API twitterResponse.Result = RequestResult.RateLimited; break; case HttpStatusCode.Unauthorized: twitterResponse.Result = RequestResult.Unauthorized; break; case HttpStatusCode.NotFound: twitterResponse.Result = RequestResult.FileNotFound; break; case HttpStatusCode.ProxyAuthenticationRequired: twitterResponse.Result = RequestResult.ProxyAuthenticationRequired; break; case HttpStatusCode.RequestTimeout: twitterResponse.Result = RequestResult.TwitterIsOverloaded; break; case HttpStatusCode.Forbidden: twitterResponse.Result = RequestResult.Unauthorized; break; default: twitterResponse.Result = RequestResult.Unknown; break; } }
/// <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); }
//todo: factor out this logic from main and add wentToFestival to mod state //TODO: add trace log public void AFKHostingRoutine() { //TODO: need to cancel waiting for player dialog if other players have quit //should be able to ignore events and cutscenes since that should be handled by Context.PlayerCanMove //TODO: cancel cutscenens when they occur //TODO: move player outside house in morning to trigger any cutscenes that might occur //TODO: pause game if no players are online #if DEBUG if (!(IsThisPlayerFree && Context.IsMultiplayer)) { return; } #else if (!(IsThisPlayerFree && RemotePlayersAreOnline && Context.IsMultiplayer)) { return; } #endif //teleport player to festival when its ready if they have not been yet if (IsFestivalDay && IsFestivalReady && !IsThisPlayerAtFestival && !State.WentToTodaysFestival) { var festivalLocation = WhereIsFestival(); if (festivalLocation != Location.None) { void DebouncedTeleportToNPC(object sender, EventArgs args) { RateLimiting.Debounce(nameof(DebouncedTeleportToNPC), 1000, () => { ViewportChanged -= DebouncedTeleportToNPC; var testDialog = new NPCDialogAutomater("Lewis", true, Monitor, Helper, new DialogAction[] { new DialogAction { DialogActionType = DialogActionType.Start }, new DialogAction { DialogActionType = DialogActionType.Next }, new DialogAction { DialogActionType = DialogActionType.Next }, new DialogAction { DialogActionType = DialogActionType.Start }, new DialogAction { DialogActionType = DialogActionType.Answer, AnswerIndex = 0 } }); ViewportChanged += DebouncedRunActions; testDialog.TeleportToNPC(); void DebouncedRunActions(object s, EventArgs e) { RateLimiting.Debounce(nameof(DebouncedRunActions), 1000, () => { ViewportChanged -= DebouncedRunActions; testDialog.RunActions(); }); } }); } ViewportChanged += DebouncedTeleportToNPC; TeleportThisPlayer(festivalLocation, 0, 0); return; } } //should not have to handle where player is waiting for other players to enter festival //as that should be taken care of by StardewAPI.IsThisPlayerFree if (IsFestivalDay && IsThisPlayerAtFestival && !State.WentToTodaysFestival) { //var tile = Game1.currentLocation?.currentEvent?.getActorByName("Lewis")?.getTileLocation(); //if (!tile.HasValue) return; //Game1.player.setTileLocation(new Vector2(tile.Value.X, tile.Value.Y+1)); State.With(s => s.WentToTodaysFestival, true); //Game1.player.team.SetLocalReady("festivalEnd", true); //Game1.activeClickableMenu = (IClickableMenu)new ReadyCheckDialog("festivalEnd", true, new ConfirmationDialog.behavior(Game1.currentLocation.currentEvent.forceEndFestival), (ConfirmationDialog.behavior)null); } //this should run once to trigger the festival leave waiting screen which should teleport to farm //(or just start here if there is no festival) then it will run again to move player to bed if they are not in it //and one more time to trigger wait for sleep //TODO: test how this is affected by time change when festival ends if (!IsFestivalDay || (IsFestivalDay && !IsThisPlayerAtFestival && State.WentToTodaysFestival)) { //TODO: this doesnt work when at a festival, tries to tele repeatedly but nothing happens //test if this waits until the teleport is finished if (!IsThisPlayerInBed) { TeleportThisPlayerToBed(); } else { StartSleepForThisPlayer(Helper); } } //reset festival status on next day //TODO: will this work for night market? if (!IsFestivalDay && State.WentToTodaysFestival) { State.With(s => s.WentToTodaysFestival, false); } //if (Game1.activeClickableMenu is DialogueBox dialogueBox) //{ // var isQuestion = Helper.Reflection.GetField<bool>(dialogueBox, "isQuestion").GetValue(); // if(isQuestion) // { // //TODO: auto answer questions based on a json event/dialog/person configuration file // return; // } // CloseDialogOrMenu(); //} }
public RateLimitingMiddleware(RequestDelegate next, IMemoryCache cache, IOptions <RateLimiting> options) { _next = next; _cache = cache; _config = options.Value; }