/// <summary> /// Adds the cheat to the selected library. /// </summary> /// <param name="cheat">The cheat to add.</param> private void AddCheatToLibrary(Cheat cheat) { if (!this.CheatsAvailable.Contains(cheat)) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unable to add cheat to library"); return; } AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; try { SqualrApi.AddCheatToLibrary(accessTokens.AccessToken, this.ActiveLibrary.LibraryId, cheat.CheatId); cheat.LoadDefaultStreamSettings(); this.cheatsAvailable.Remove(cheat); this.cheatsInLibrary.Insert(0, cheat); this.RaisePropertyChanged(nameof(this.CheatsAvailable)); this.RaisePropertyChanged(nameof(this.CheatsInLibrary)); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error adding cheat to library", ex); } }
/// <summary> /// Attempts to unlock the provided cheat. /// </summary> /// <param name="cheat">The cheat to unlock</param> private void UnlockCheat(Cheat cheat) { if (!this.LockedCheatList.Contains(cheat)) { throw new Exception("Cheat must be a locked cheat"); } AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; // We need the unlocked cheat, since the locked one does not include the payload try { UnlockedCheat unlockedCheat = SqualrApi.UnlockCheat(accessTokens.AccessToken, cheat.CheatId); BrowseViewModel.GetInstance().SetCoinAmount(unlockedCheat.RemainingCoins); this.LockedCheatList.Remove(cheat); this.UnlockedCheatList.Insert(0, unlockedCheat.Cheat); LibraryViewModel.GetInstance().OnUnlock(unlockedCheat.Cheat); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error unlocking cheat", ex); } }
/// <summary> /// Deletes the selected library after prompting the user. /// </summary> private void DeleteLibrary() { if (this.ActiveLibrary == null) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "No library selected"); return; } MessageBoxResult result = CenteredDialogBox.Show( "Delete library '" + this.ActiveLibrary.LibraryName + "'?", "Confirm Library Delete", MessageBoxButton.YesNoCancel, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { Task.Run(() => { try { AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; SqualrApi.DeleteLibrary(accessTokens?.AccessToken, this.ActiveLibrary.LibraryId); this.libraries.Remove(this.ActiveLibrary); this.ActiveLibrary = null; this.RaisePropertyChanged(nameof(this.Libraries)); this.RaisePropertyChanged(nameof(this.ActiveLibrary)); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error deleting library", ex); } }); } }
/// <summary> /// Determine if the user is logged in to Twitch. /// </summary> private void UpdateLoginStatus() { this.IsLoginStatusLoading = true; try { AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; if (accessTokens == null || accessTokens.AccessToken.IsNullOrEmpty()) { this.IsLoggedIn = false; return; } User user = SqualrApi.GetTwitchUser(accessTokens.AccessToken); SqualrApi.Connect(accessTokens.AccessToken); this.ActiveUser = user; this.IsLoggedIn = true; } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Warn, "Unable to log in using stored credentials", ex); this.IsLoggedIn = false; } finally { this.IsLoginStatusLoading = false; } }
/// <summary> /// Selects a specific game for which to view the store. /// </summary> /// <param name="game">The selected game.</param> public void SelectGame(Game game) { // Deselect current game this.IsCheatListLoading = true; this.LockedCheatList = null; this.UnlockedCheatList = null; Task.Run(() => { try { // Select new game AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; StoreCheats storeCheats = SqualrApi.GetStoreCheats(accessTokens.AccessToken, game.GameId); this.LockedCheatList = new FullyObservableCollection <Cheat>(storeCheats.LockedCheats); this.UnlockedCheatList = new FullyObservableCollection <Cheat>(storeCheats.UnlockedCheats); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error loading cheats", ex); BrowseViewModel.GetInstance().NavigateBack(); } finally { this.IsCheatListLoading = false; } }); }
private void UpdateStreamMeta() { Task.Run(() => { try { SqualrApi.UpdateCheatStreamMeta(SettingsViewModel.GetInstance().AccessTokens?.AccessToken, this); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error updating stream with local change. Try again.", ex); } }); }
/// <summary> /// Adds a new library to the current selected game. /// </summary> private void AddNewLibrary() { Task.Run(() => { try { AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; Library newLibrary = SqualrApi.CreateLibrary(accessTokens?.AccessToken, this.SelectedGame.GameId); this.libraries.Add(newLibrary); this.RaisePropertyChanged(nameof(this.Libraries)); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error creating library", ex); } }); }
/// <summary> /// Attempts to load icons from the Squalr api. /// </summary> private void LoadIcons() { Task.Run(() => { try { this.streamIcons = SqualrApi.GetStreamIcons(); this.RaisePropertyChanged(nameof(this.FilteredStreamIconList)); this.IsStreamIconListLoading = false; this.NotifyIconsLoaded(); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error loading icons", ex); } }); }
/// <summary> /// Gets the twitch oauth access tokens using the provided code. /// </summary> /// <param name="code">The one time use exchange code to receive the access tokens.</param> private void PerformLogin(String code) { try { AccessTokens accessTokens = SqualrApi.GetAccessTokens(code); User user = SqualrApi.GetTwitchUser(accessTokens.AccessToken); SqualrApi.Connect(accessTokens.AccessToken); SettingsViewModel.GetInstance().AccessTokens = accessTokens; BrowseViewModel.GetInstance().ActiveUser = user; BrowseViewModel.GetInstance().IsLoggedIn = true; } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, "Error authorizing Twitch", ex); } }
/// <summary> /// Called when the scheduled task is updated. /// </summary> /// <param name="cancellationToken">The cancellation token for handling canceled tasks.</param> protected override void OnUpdate(CancellationToken cancellationToken) { try { AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; if (accessTokens == null || accessTokens.AccessToken.IsNullOrEmpty()) { return; } User user = SqualrApi.GetTwitchUser(accessTokens.AccessToken); this.UpdateAction?.Invoke(user.Coins); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error refreshing user", ex); } }
/// <summary> /// Selects a specific game for which to view the store. /// </summary> /// <param name="library">The selected library.</param> private void SelectLibrary(Library library) { BrowseViewModel.GetInstance().Navigate(NavigationPage.LibraryEdit); Task.Run(() => { try { this.IsLibraryLoading = true; // Deselect current library this.ActiveLibrary = null; this.CheatsAvailable = null; this.CheatsInLibrary = null; this.RaisePropertyChanged(nameof(this.CheatsAvailable)); this.RaisePropertyChanged(nameof(this.CheatsInLibrary)); // Select library AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; LibraryCheats libraryCheats = SqualrApi.GetCheats(accessTokens.AccessToken, library.LibraryId); SqualrApi.SetActiveLibrary(accessTokens.AccessToken, library.LibraryId); this.ActiveLibrary = library; this.CheatsAvailable = new ObservableCollection <Cheat>(libraryCheats.CheatsAvailable); this.CheatsInLibrary = new ObservableCollection <Cheat>(libraryCheats.CheatsInLibrary); this.RaisePropertyChanged(nameof(this.CheatsAvailable)); this.RaisePropertyChanged(nameof(this.CheatsInLibrary)); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error loading cheats", ex); } finally { this.IsLibraryLoading = false; } }); }
/// <summary> /// Selects a specific game for which to view the store. /// </summary> /// <param name="game">The selected game.</param> private void SelectGame(Game game) { // Deselect current game this.SelectedGame = null; this.Libraries = null; this.IsLibraryListLoading = true; this.ActiveLibrary = null; this.RaisePropertyChanged(nameof(this.Libraries)); BrowseViewModel.GetInstance().Navigate(NavigationPage.LibrarySelect); Task.Run(() => { try { StoreViewModel.GetInstance().SelectGame(game); // Select new game AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; IEnumerable <Library> libraries = SqualrApi.GetLibraries(accessTokens.AccessToken, game.GameId); this.Libraries = new ObservableCollection <Library>(libraries); this.RaisePropertyChanged(nameof(this.Libraries)); this.SelectedGame = game; } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error loading libraries", ex); BrowseViewModel.GetInstance().Navigate(NavigationPage.GameSelect); } finally { this.IsLibraryListLoading = false; } }); }
/// <summary> /// Removes the cheat from the selected library. /// </summary> /// <param name="cheat">The cheat to remove.</param> private void RemoveCheatFromLibrary(Cheat cheat) { if (!this.CheatsInLibrary.Contains(cheat)) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unable to remove cheat from library"); return; } AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; try { SqualrApi.RemoveCheatFromLibrary(accessTokens.AccessToken, this.ActiveLibrary.LibraryId, cheat.CheatId); this.cheatsInLibrary.Remove(cheat); this.cheatsAvailable.Insert(0, cheat); this.RaisePropertyChanged(nameof(this.CheatsAvailable)); this.RaisePropertyChanged(nameof(this.CheatsInLibrary)); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error removing cheat from library", ex); } }
/// <summary> /// Loads the list of games from the API. /// </summary> private void LoadGameList() { this.IsGameListLoading = true; this.GameList = null; Task.Run(() => { try { AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; this.GameList = SqualrApi.GetOwnedGameList(accessTokens.AccessToken); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error fetching game list", ex); BrowseViewModel.GetInstance().NavigateBack(); } finally { this.IsGameListLoading = false; } }); }
/// <summary> /// Event fired when the stream commands need to be update. /// </summary> private void OnUpdate() { if (!this.IsConnected) { return; } try { lock (this.VoteLock) { if (!this.IsConnected || !BrowseViewModel.GetInstance().IsLoggedIn) { return; } AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; IEnumerable <CheatVotes> cheatVotes = SqualrApi.GetStreamActivationIds(accessTokens.AccessToken); IEnumerable <Cheat> candidateCheats = LibraryViewModel.GetInstance().CheatsInLibrary; if (candidateCheats == null || this.PreviousCheatVotes == null || cheatVotes == null || this.PreviousCheatVotes.Count() != cheatVotes.Count()) { this.PreviousCheatVotes = cheatVotes; return; } // Get cheat IDs to activate based on increased vote counts IEnumerable <Int32> cheatIdsToActivate = cheatVotes .Join( this.PreviousCheatVotes, currentVote => currentVote.CheatId, previousVote => previousVote.CheatId, (currentVote, previousVote) => new { cheatId = currentVote.CheatId, currentCount = currentVote.VoteCount, previousCount = previousVote.VoteCount }) .Where(combinedVote => combinedVote.currentCount != combinedVote.previousCount) .Select(combinedVote => combinedVote.cheatId); // Add in new votes with no previous vote count cheatIdsToActivate = cheatVotes .Select(vote => vote.CheatId) .Except(this.PreviousCheatVotes.Select(vote => vote.CheatId)) .Concat(cheatIdsToActivate) .Distinct(); IEnumerable <Cheat> projectItemsToActivate = cheatIdsToActivate .Join( candidateCheats, cheatId => cheatId, projectItem => projectItem?.CheatId, (cheatId, projectItem) => projectItem); IEnumerable <Cheat> projectItemsToDeactivate = cheatVotes .Join( candidateCheats, cheatVote => cheatVote.CheatId, projectItem => projectItem?.CheatId, (cheatId, projectItem) => projectItem) .Except(projectItemsToActivate); // Handle activations projectItemsToActivate.ForEach(item => { item.IsActivated = true; // Reset duration always item.Duration = 0.0f; }); // Notify which project items were activated such that Squalr can update the stream overlay if (projectItemsToActivate.Count() > 0) { Task.Run(() => { IEnumerable <Cheat> activatedProjectItems = candidateCheats .Select(item => item) .Where(item => !item.IsStreamDisabled) .Where(item => item.IsActivated); IEnumerable <OverlayMeta> overlayMeta = activatedProjectItems .Select(item => new OverlayMeta(item.CheatId, item.Cooldown, item.Duration)); if (overlayMeta.Count() > 0) { try { SqualrApi.UpdateOverlayMeta(accessTokens.AccessToken, overlayMeta.ToArray()); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error updating overlay cooldowns and durations", ex); } } }); } this.PreviousCheatVotes = cheatVotes; } } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Warn, "Error fetching activated cheats", ex); } }