public ChannelPointRedemption(Variant srcObj) { _id = srcObj["id"]; _username = srcObj["user"]["display_name"]; _userID = srcObj["user"]["id"]; Reward = new ChannelPointReward(srcObj["reward"]); }
public override void OnUpdate() { base.OnUpdate(); if (Game.instance is null) { return; } if (!_syncStarted && TwitchAuthed && !_twitchSynced) { //MelonLogger.Msg("Sync start"); _syncStarted = true; MelonLogger.Msg("Syncing Channel Point Rewards with Twitch..."); if (!File.Exists(RewardsPath)) { //MelonLogger.Msg("Creating file!"); var stream = File.CreateText(RewardsPath); stream.WriteAsync("{}").Wait(); stream.FlushAsync().Wait(); stream.Close(); } try { var content = JSON.Load(File.ReadAllText(RewardsPath)); var foundOnTwitch = new Dictionary <RewardType, bool>(); var availableRewards = Enum.GetValues(typeof(RewardType)); foreach (RewardType type in availableRewards) { foundOnTwitch[type] = false; } foreach (var value in (RewardType[])Enum.GetValues(typeof(RewardType))) { try { string id = content[value.ToString()]["id"]; ChannelPointReward.SetRewardTypeID(value, id); } catch (KeyNotFoundException) { } } Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _twitchToken); Task <HttpResponseMessage> t = Client.GetAsync( "https://api.twitch.tv/helix/channel_points/custom_rewards?only_manageable_rewards=true&broadcaster_id=" + _twitchID); t.Wait(); HttpResponseMessage response = t.Result; Task <string> t2 = response.Content.ReadAsStringAsync(); t2.Wait(); var responseContent = t2.Result; MelonLogger.Msg("Rewards response: " + responseContent); var responseJson = JSON.Load(responseContent); var data = responseJson["data"]; MelonLogger.Msg("data acquired. Moving along."); foreach (var reward in (ProxyArray)data) { ChannelPointReward rewardObj = new ChannelPointReward(reward); try { var type = rewardObj.GetRewardType(); ChannelPointReward.SetRewardTypeID(type, rewardObj.id); foundOnTwitch[type] = true; } catch (Exception) { MelonLogger.Msg("Could not map reward " + rewardObj.id + " to a local type. Ignoring."); } } async void CreateRewards() { bool hadIssues = false; foreach (KeyValuePair <RewardType, bool> keyValuePair in foundOnTwitch) { if (!keyValuePair.Value) { //If reward not found yet, create it! try { HttpResponseMessage postResponse; do { var obj = JSON.Load("{\"title\":\"" + ChannelPointReward .GetDescriptionFromType(keyValuePair.Key) + "\"," + "\"cost\":1000,\"is_enabled\":false," + "\"background_color\":\"" + ChannelPointReward.GetColorFromType(keyValuePair.Key) + "\"" + "\"should_redemptions_skip_request_queue\":true}"); postResponse = await Client.PostAsync( "https://api.twitch.tv/helix/channel_points/custom_rewards?broadcaster_id=" + _twitchID, new StringContent(JSON.Dump(obj), Encoding.UTF8, "application/json")); if (postResponse.StatusCode == (HttpStatusCode)429) { MelonLogger.Msg("Rate limit hit. Waiting"); } else { //MelonLogger.Msg("Status: " + postResponse.StatusCode.ToString()); } } while (postResponse.StatusCode == (HttpStatusCode)429); var postResponseContent = await postResponse.Content.ReadAsStringAsync(); //MelonLogger.Msg("Content: " + postResponseContent); var postResponseContentJson = JSON.Load(postResponseContent); content[keyValuePair.Key.ToString()] = postResponseContentJson["data"][0]; //MelonLogger.Msg("Setting up " + keyValuePair.Key.ToString()); ChannelPointReward.SetRewardTypeID(keyValuePair.Key, postResponseContentJson["data"][0]["id"]); } catch (Exception e) { MelonLogger.Error(e.ToString()); hadIssues = true; } } } var stream = File.CreateText(RewardsPath); await stream.WriteAsync(JSON.Dump(content)); //a await stream.FlushAsync(); stream.Close(); if (hadIssues) { PopupsToDisplay.Enqueue(new MyPopup(PopupType.Yesno, "Something went wrong trying to create the rewards.\n" + "You must have access to Channel Points for this to work! Also note that you may need to delete other rewards with the same name!\n" + "Try again?", "Twitch Integration Error", "Yes", "No", CreateRewards)); } else { PopupsToDisplay.Enqueue(new MyPopup(PopupType.Yesonly, title: "Rewards created!\nRemember to enable them so they can be used!", okCallback: SyncFinished)); } } var foundAll = foundOnTwitch.All(keyValuePair => keyValuePair.Value); if (foundAll) { SyncFinished(); } else { PopupsToDisplay.Enqueue(new MyPopup(PopupType.Yesno, "One or more Rewards were not found on Twitch.\n\nDo you want to create a new set of Rewards now?", "Twitch Integration", "yes", "no", CreateRewards)); } } catch (Exception e) { MelonLogger.Error("Error loading Rewards: " + e); PopupsToDisplay.Enqueue(new MyPopup(PopupType.Yesno, "Error loading Rewards.\n\nTry again?", "Twitch Integration Error", "Yes", "no", () => { _syncStarted = false; })); return; } } if (PopupsToDisplay.Count >= 1 && StreamingSetupMainMenuHook.Seen) { if (2 < Game.instance.GetPopupScreen().activePopupHandles._size) { //goto afterif; // Don't show popup if too many are already active. } //MelonLogger.Msg("Showing popup..."); var currentPopup = PopupsToDisplay.Dequeue(); switch (currentPopup.Type) { case PopupType.Yesno: Game.instance.GetPopupScreen().ShowPopup(PopupScreen.Placement.menuCenter, currentPopup.Title, currentPopup.Body, currentPopup.OkCallback, currentPopup.OkText, currentPopup.CancelCallback, currentPopup.CancelText, Popup.TransitionAnim.Scale); break; case PopupType.Yesonly: Game.instance.GetPopupScreen().ShowWelcomePopup(PopupScreen.Placement.menuCenter, currentPopup.Title, currentPopup.OkCallback, currentPopup.OkText, currentPopup.CancelCallback, "THIS IS NEVER USED SMH", Popup.TransitionAnim.Scale); break; default: throw new ArgumentOutOfRangeException(); } } if (InGame.instance is null) { return; } if ((!InGame.instance.IsCoop) && (!InGame.instance.IsInOdyssey()) && RewardActionsToRunInInGameThread.Count >= 1) { var action = RewardActionsToRunInInGameThread.Dequeue(); action.Invoke(); } }