Exemplo n.º 1
0
        void ClearSearch(KEY key)
        {
            ClearSearches();

            RequestBot.UpdateRequestUI();
            RequestBot._refreshQueue = true;
        }
Exemplo n.º 2
0
        public static void ClearSearch(KEYBOARD.KEY key)
        {
            ClearSearches();

            RequestBot.UpdateRequestUI();
            RequestBot._refreshQueue = true;
        }
Exemplo n.º 3
0
        private void OnMenuSceneLoadedFresh()
        {
            // setup settings ui
            BSMLSettings.instance.AddSettingsMenu("SRM", "SongRequestManager.Views.SongRequestManagerSettings.bsml", SongRequestManagerSettings.instance);

            // main load point
            RequestBot.OnLoad();
            RequestBotConfig.Save(true);
        }
Exemplo n.º 4
0
        public static bool HasPermission(TwitchUser inputUser, int permissionLevel)
        {
            // explicitly check a permission level of a user and an action
            int userPermissionLevel = RequestBot.getPermissionLevel(inputUser);

            if ((userPermissionLevel & permissionLevel) >= 1)
            {
                return(true);
            }
            return(false);
        }
Exemplo n.º 5
0
 void ClearSearches()
 {
     for (int i = 0; i < RequestQueue.Songs.Count; i++)
     {
         var entry = RequestQueue.Songs[i];
         if (entry.status == RequestBot.RequestStatus.SongSearch)
         {
             RequestBot.DequeueRequest(i, false);
             i--;
         }
     }
 }
Exemplo n.º 6
0
        private void OnMenuSceneLoadedFresh()
        {
            try
            {
                Settings.OnLoad();
            }
            catch (Exception ex)
            {
                Plugin.Log($"{ex}");
            }

            RequestBot.OnLoad();
            RequestBotConfig.Save(true);
        }
Exemplo n.º 7
0
        public static string ConstructStringForPermissionLevel(int specificPermissionLevelToCheck)
        {
            // create a string the lazy and inefficient way
            string returnValue   = "";
            string delimiter     = ", ";
            bool   isSub         = RequestBot.CheckSpecificPermission(specificPermissionLevelToCheck, (int)RequestBot.Sub);
            bool   isMod         = RequestBot.CheckSpecificPermission(specificPermissionLevelToCheck, (int)RequestBot.Mod);
            bool   isVip         = RequestBot.CheckSpecificPermission(specificPermissionLevelToCheck, (int)RequestBot.VIP);
            bool   isBroadcaster = RequestBot.CheckSpecificPermission(specificPermissionLevelToCheck, (int)RequestBot.Broadcaster);

            if (isSub)
            {
                returnValue += "Subs";
            }
            if (isSub && (isMod || isVip || isBroadcaster))
            {
                returnValue += delimiter;
            }

            if (isMod)
            {
                returnValue += "Mods";
            }
            if (isMod && (isVip || isBroadcaster))
            {
                returnValue += delimiter;
            }

            if (isVip)
            {
                returnValue += "VIPs";
            }
            if (isVip && (isMod || isBroadcaster))
            {
                returnValue += delimiter;
            }

            if (isBroadcaster && (isMod || isVip || isSub))
            {
                returnValue += " and ";
            }
            if (isBroadcaster)
            {
                returnValue += "Hosts";
            }

            return(returnValue);
        }
        private void OnLateMenuSceneLoadedFresh(ScenesTransitionSetupDataSO scenesTransitionSetupData)
        {
            // setup settings ui
            BSMLSettings.instance.AddSettingsMenu("SRM", "SongRequestManager.Views.SongRequestManagerSettings.bsml", SongRequestManagerSettings.instance);

            var onlinePlayButton    = Resources.FindObjectsOfTypeAll <Button>().First(x => x.name == "OnlineButton");
            var soloFreePlayButton  = Resources.FindObjectsOfTypeAll <Button>().First(x => x.name == "SoloButton");
            var partyFreePlayButton = Resources.FindObjectsOfTypeAll <Button>().First(x => x.name == "PartyButton");
            var campaignButton      = Resources.FindObjectsOfTypeAll <Button>().First(x => x.name == "CampaignButton");

            onlinePlayButton.onClick.AddListener(() => { gameMode = GameMode.Online; });
            soloFreePlayButton.onClick.AddListener(() => { gameMode = GameMode.Solo; });
            partyFreePlayButton.onClick.AddListener(() => { gameMode = GameMode.Solo; });
            campaignButton.onClick.AddListener(() => { gameMode = GameMode.Solo; });

            // main load point
            RequestBot.OnLoad();
            RequestBotConfig.Save(true);
        }
Exemplo n.º 9
0
        private void Awake()
        {
            DontDestroyOnLoad(gameObject);
            Instance = this;

            #if UNRELEASED
            var startingmem = GC.GetTotalMemory(true);

            //var folder = Path.Combine(Environment.CurrentDirectory, "userdata","streamcore");

            //List<FileInfo> files = new List<FileInfo>();  // List that will hold the files and subfiles in path
            //List<DirectoryInfo> folders = new List<DirectoryInfo>(); // List that hold direcotries that cannot be accessed

            //DirectoryInfo di = new DirectoryInfo(folder);

            //Dictionary<string, string> remap = new Dictionary<string, string>();

            //foreach (var entry in listcollection.OpenList("all.list").list)
            //    {
            //    //Instance.QueueChatMessage($"Map {entry}");

            //    string[] remapparts = entry.Split('-');
            //    if (remapparts.Length == 2)
            //    {
            //        int o;
            //        if (Int32.TryParse(remapparts[1], out o))
            //        {
            //            try
            //            {
            //                remap.Add(remapparts[0], o.ToString("x"));
            //            }
            //            catch
            //            { }
            //            //Instance.QueueChatMessage($"Map {remapparts[0]} : {o.ToString("x")}");
            //        }
            //    }
            //}

            //Instance.QueueChatMessage($"Scanning lists");

            //FullDirList(di, "*.deck");
            //void FullDirList(DirectoryInfo dir, string searchPattern)
            //{
            //    try
            //    {
            //        foreach (FileInfo f in dir.GetFiles(searchPattern))
            //        {
            //            var List = listcollection.OpenList(f.Name).list;
            //            for (int i=0;i<List.Count;i++)
            //                {
            //                if (remap.ContainsKey(List[i]))
            //                {
            //                    //Instance.QueueChatMessage($"{List[i]} : {remap[List[i]]}");
            //                    List[i] = remap[List[i]];
            //                }
            //                }
            //            listcollection.OpenList(f.Name).Writefile(f.Name);
            //        }
            //    }
            //    catch
            //    {
            //        Console.WriteLine("Directory {0}  \n could not be accessed!!!!", dir.FullName);
            //        return;
            //    }
            //}

            //NOTJSON.UNITTEST();
#endif

            playedfilename = Path.Combine(Plugin.DataPath, "played.dat"); // Record of all the songs played in the current session

            try
            {
                string filesToDelete = Path.Combine(Environment.CurrentDirectory, "FilesToDelete");
                if (Directory.Exists(filesToDelete))
                {
                    EmptyDirectory(filesToDelete);
                }


                try
                {
                    DateTime LastBackup;
                    if (!DateTime.TryParse(RequestBotConfig.Instance.LastBackup, out LastBackup))
                    {
                        LastBackup = DateTime.MinValue;
                    }
                    TimeSpan TimeSinceBackup = DateTime.Now - LastBackup;
                    if (TimeSinceBackup > TimeSpan.FromHours(RequestBotConfig.Instance.SessionResetAfterXHours))
                    {
                        Backup();
                    }
                }
                catch (Exception ex)
                {
                    Plugin.Log(ex.ToString());
                    Instance.QueueChatMessage("Failed to run Backup");
                }

                try
                {
                    TimeSpan PlayedAge = GetFileAgeDifference(playedfilename);
                    if (PlayedAge < TimeSpan.FromHours(RequestBotConfig.Instance.SessionResetAfterXHours))
                    {
                        played = ReadJSON(playedfilename);                                                                                // Read the songsplayed file if less than x hours have passed
                    }
                }
                catch (Exception ex)
                {
                    Plugin.Log(ex.ToString());
                    Instance.QueueChatMessage("Failed to clear played file");
                }

                if (RequestBotConfig.Instance.PPSearch)
                {
                    GetPPData();                                     // Start loading PP data
                }
                MapDatabase.LoadDatabase();

                if (RequestBotConfig.Instance.LocalSearch)
                {
                    MapDatabase.LoadCustomSongs(); // This is a background process
                }
                RequestQueue.Read();               // Might added the timespan check for this too. To be decided later.
                RequestHistory.Read();
                listcollection.OpenList("banlist.unique");

#if UNRELEASED
                //GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
                //GC.Collect();
                //Instance.QueueChatMessage($"hashentries: {SongMap.hashcount} memory: {(GC.GetTotalMemory(false) - startingmem) / 1048576} MB");
#endif

                listcollection.ClearOldList("duplicate.list", TimeSpan.FromHours(RequestBotConfig.Instance.SessionResetAfterXHours));

                UpdateRequestUI();
                InitializeCommands();

                //EnhancedStreamChat.ChatHandler.ChatMessageFilters += MyChatMessageHandler; // TODO: Reimplement this filter maybe? Or maybe we put it directly into EnhancedStreamChat


                COMMAND.CommandConfiguration();
                RunStartupScripts();


                ProcessRequestQueue();

                RequestBotConfig.Instance.ConfigChangedEvent += OnConfigChangedEvent;
            }
            catch (Exception ex)
            {
                Plugin.Log(ex.ToString());
                Instance.QueueChatMessage(ex.ToString());
            }
        }
Exemplo n.º 10
0
        private string ProcessSongRequest(ParseState state)
        {
            if (!RequestBot.HasPermission(state.user, RequestBotConfig.Instance.SongRequestPermissionLevel))
            {
                QueueChatMessage(RequestBotConfig.Instance.PermissionLevelNotAcceptedText);
                return(success);
            }
            try
            {
                if (RequestBotConfig.Instance.RequestQueueOpen == false && !state.flags.HasFlag(CmdFlags.NoFilter) && !state.flags.HasFlag(CmdFlags.Local)) // BUG: Complex permission, Queue state message needs to be handled higher up
                {
                    QueueChatMessage($"Queue is currently closed.");
                    return(success);
                }

                if (!RequestTracker.ContainsKey(state.user.Id))
                {
                    RequestTracker.Add(state.user.Id, new RequestUserTracker());
                }

                int limit = RequestBotConfig.Instance.UserRequestLimit;
                if (state.user.IsSubscriber)
                {
                    limit = Math.Max(limit, RequestBotConfig.Instance.SubRequestLimit);
                }
                if (state.user.IsModerator)
                {
                    limit = Math.Max(limit, RequestBotConfig.Instance.ModRequestLimit);
                }
                if (state.user.IsVip)
                {
                    limit += RequestBotConfig.Instance.VipBonusRequests;                   // Current idea is to give VIP's a bonus over their base subscription class, you can set this to 0 if you like
                }
                if (!state.user.IsBroadcaster)
                {
                    if (RequestTracker[state.user.Id].numRequests >= limit)
                    {
                        if (RequestBotConfig.Instance.LimitUserRequestsToSession)
                        {
                            new DynamicText().Add("Requests", RequestTracker[state.user.Id].numRequests.ToString()).Add("RequestLimit", RequestBotConfig.Instance.SubRequestLimit.ToString()).QueueMessage("You've already used %Requests% requests this stream. Subscribers are limited to %RequestLimit%.");
                        }
                        else
                        {
                            new DynamicText().Add("Requests", RequestTracker[state.user.Id].numRequests.ToString()).Add("RequestLimit", RequestBotConfig.Instance.SubRequestLimit.ToString()).QueueMessage("You already have %Requests% on the queue. You can add another once one is played. Subscribers are limited to %RequestLimit%.");
                        }

                        return(success);
                    }
                }

                // BUG: Need to clean up the new request pipeline
                string testrequest = normalize.RemoveSymbols(ref state.parameter, normalize._SymbolsNoDash);

                RequestInfo newRequest = new RequestInfo(state.user, state.parameter, DateTime.UtcNow, _digitRegex.IsMatch(testrequest) || _beatSaverRegex.IsMatch(testrequest), state, state.flags, state.info);

                if (!newRequest.isBeatSaverId && state.parameter.Length < 2)
                {
                    QueueChatMessage($"Request \"{state.parameter}\" is too short- Beat Saver searches must be at least 3 characters!");
                }
                if (!UnverifiedRequestQueue.Contains(newRequest))
                {
                    UnverifiedRequestQueue.Enqueue(newRequest);
                }
            }
            catch (Exception ex)
            {
                Plugin.Log(ex.ToString());
            }
            return(success);
        }
Exemplo n.º 11
0
        private async void SetDataFromLevelAsync(SongRequest request, LevelListTableCell _tableCell, int row)
        {
            var favouritesBadge = _tableCell.GetField <Image, LevelListTableCell>("_favoritesBadgeImage");

            favouritesBadge.enabled = false;

            var highlight = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');

            var msg = highlight ? "MSG" : "";

            var hasMessage  = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');
            var isChallenge = request.requestInfo.IndexOf("!challenge", StringComparison.OrdinalIgnoreCase) >= 0;

            var pp      = "";
            var ppvalue = request.song["pp"].AsInt;

            if (ppvalue > 0)
            {
                pp = $" {ppvalue} PP";
            }

            var dt = new RequestBot.DynamicText().AddSong(request.song).AddUser(ref request.requestor); // Get basic fields

            dt.Add("Status", request.status.ToString());
            dt.Add("Info", (request.requestInfo != "") ? " / " + request.requestInfo : "");
            dt.Add("RequestTime", request.requestTime.ToLocalTime().ToString("hh:mm"));

            var songDurationText = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText");

            songDurationText.text = request.song["songlength"].Value;

            var songBpm = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText");

            (songBpm.transform as RectTransform).anchoredPosition = new Vector2(-2.5f, -1.8f);
            (songBpm.transform as RectTransform).sizeDelta       += new Vector2(15f, 0f);

            var k = new List <string>();

            if (hasMessage)
            {
                k.Add("MSG");
            }
            if (isChallenge)
            {
                k.Add("VS");
            }
            k.Add(request.song["id"]);
            songBpm.text = string.Join(" - ", k);

            var songBmpIcon = _tableCell.GetComponentsInChildren <Image>().LastOrDefault(c => string.Equals(c.name, "BpmIcon", StringComparison.OrdinalIgnoreCase));

            if (songBmpIcon != null)
            {
                Destroy(songBmpIcon);
            }

            var songName = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songNameText");

            songName.richText = true;
            songName.text     = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size>";

            var author = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songAuthorText");

            author.richText = true;
            author.text     = dt.Parse(RequestBot.QueueListRow2);

            var image    = _tableCell.GetField <Image, LevelListTableCell>("_coverImage");
            var imageSet = false;

            if (SongCore.Loader.AreSongsLoaded)
            {
                var level = CustomLevelForRow(row);
                if (level != null)
                {
                    // set image from song's cover image
                    var sprite = await level.GetCoverImageAsync(System.Threading.CancellationToken.None);

                    image.sprite = sprite;
                    imageSet     = true;
                }
            }

            if (!imageSet)
            {
                var url = request.song["coverURL"].Value;

                if (!_cachedTextures.TryGetValue(url, out var tex))
                {
                    var b = await Plugin.WebClient.DownloadImage($"{url}", System.Threading.CancellationToken.None);

                    tex = new Texture2D(2, 2);
                    tex.LoadImage(b);

                    try
                    {
                        _cachedTextures.Add(url, tex);
                    }
                    catch (Exception)
                    {
                        // ignored
                    }
                }

                image.sprite = Base64Sprites.Texture2DToSprite(tex);
            }

            UIHelper.AddHintText(_tableCell.transform as RectTransform, dt.Parse(RequestBot.SongHintText));
        }
Exemplo n.º 12
0
        protected override void DidActivate(bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling)
        {
            if (firstActivation)
            {
                if (!SongCore.Loader.AreSongsLoaded)
                {
                    SongCore.Loader.SongsLoadedEvent += SongLoader_SongsLoadedEvent;
                }

                Plugin.Log("DidActivate 001");

                // get table cell instance
                _requestListTableCellInstance = Resources.FindObjectsOfTypeAll <LevelListTableCell>().First((LevelListTableCell x) => x.name == "LevelListTableCell");

                // initialize Yes/No modal
                YesNoModal.instance.Setup();

                Plugin.Log("DidActivate 002");

                _songPreviewPlayer = Resources.FindObjectsOfTypeAll <SongPreviewPlayer>().FirstOrDefault();

                RectTransform container = new GameObject("RequestBotContainer", typeof(RectTransform)).transform as RectTransform;
                container.SetParent(rectTransform, false);

                #region TableView Setup and Initialization
                var go = new GameObject("SongRequestTableView", typeof(RectTransform));
                go.SetActive(false);

                go.AddComponent <ScrollRect>();
                go.AddComponent <Touchable>();
                go.AddComponent <EventSystemListener>();

                ScrollView scrollView = go.AddComponent <ScrollView>();

                _songListTableView = go.AddComponent <TableView>();
                go.AddComponent <RectMask2D>();
                _songListTableView.transform.SetParent(container, false);

                _songListTableView.SetField("_preallocatedCells", new TableView.CellsGroup[0]);
                _songListTableView.SetField("_isInitialized", false);
                _songListTableView.SetField("_scrollView", scrollView);

                var viewport = new GameObject("Viewport").AddComponent <RectTransform>();
                viewport.SetParent(go.GetComponent <RectTransform>(), false);
                go.GetComponent <ScrollRect>().viewport         = viewport;
                (viewport.transform as RectTransform).sizeDelta = new Vector2(70f, 70f);

                RectTransform content = new GameObject("Content").AddComponent <RectTransform>();
                content.SetParent(viewport, false);

                scrollView.SetField("_contentRectTransform", content);
                scrollView.SetField("_viewport", viewport);

                _songListTableView.SetDataSource(this, false);

                _songListTableView.LazyInit();

                go.SetActive(true);

                (_songListTableView.transform as RectTransform).sizeDelta        = new Vector2(70f, 70f);
                (_songListTableView.transform as RectTransform).anchoredPosition = new Vector2(3f, 0f);

                _songListTableView.didSelectCellWithIdxEvent += DidSelectRow;

                _pageUpButton = UIHelper.CreateUIButton("SRMPageUpButton",
                                                        container,
                                                        "PracticeButton",
                                                        new Vector2(0f, 38.5f),
                                                        new Vector2(15f, 7f),
                                                        () => { scrollView.PageUpButtonPressed(); },
                                                        "˄");
                Destroy(_pageUpButton.GetComponentsInChildren <ImageView>().FirstOrDefault(x => x.name == "Underline"));

                _pageDownButton = UIHelper.CreateUIButton("SRMPageDownButton",
                                                          container,
                                                          "PracticeButton",
                                                          new Vector2(0f, -38.5f),
                                                          new Vector2(15f, 7f),
                                                          () => { scrollView.PageDownButtonPressed(); },
                                                          "˅");
                Destroy(_pageDownButton.GetComponentsInChildren <ImageView>().FirstOrDefault(x => x.name == "Underline"));
                #endregion

                CenterKeys = new KEYBOARD(container, "", false, -15, 15);

#if UNRELEASED
                // BUG: Need additional modes disabling one shot buttons
                // BUG: Need to make sure the buttons are usable on older headsets

                Plugin.Log("DidActivate 005");

                _CurrentSongName                    = BeatSaberUI.CreateText(container, "", new Vector2(-35, 37f));
                _CurrentSongName.fontSize           = 3f;
                _CurrentSongName.color              = Color.cyan;
                _CurrentSongName.alignment          = TextAlignmentOptions.Left;
                _CurrentSongName.enableWordWrapping = false;
                _CurrentSongName.text               = "";

                _CurrentSongName2                    = BeatSaberUI.CreateText(container, "", new Vector2(-35, 34f));
                _CurrentSongName2.fontSize           = 3f;
                _CurrentSongName2.color              = Color.cyan;
                _CurrentSongName2.alignment          = TextAlignmentOptions.Left;
                _CurrentSongName2.enableWordWrapping = false;
                _CurrentSongName2.text               = "";

                //CenterKeys.AddKeys(SONGLISTKEY);
                if (!RequestBot.AddKeyboard(CenterKeys, "mainpanel.kbd"))
                {
                    CenterKeys.AddKeys(SONGLISTKEY);
                }

                ColorDeckButtons(CenterKeys, Color.white, Color.magenta);
#endif

                RequestBot.AddKeyboard(CenterKeys, "CenterPanel.kbd");

                CenterKeys.DefaultActions();

                #region History button
                // History button
                _historyButton = UIHelper.CreateUIButton("SRMHistory", container, "PracticeButton", new Vector2(53f, 30f),
                                                         new Vector2(25f, 15f),
                                                         () =>
                {
                    isShowingHistory = !isShowingHistory;
                    RequestBot.SetTitle(isShowingHistory ? "Song Request History" : "Song Request Queue");
                    if (NumberOfCells() > 0)
                    {
                        _songListTableView.ScrollToCellWithIdx(0, TableView.ScrollPositionType.Beginning, false);
                        _songListTableView.SelectCellWithIdx(0);
                        _selectedRow = 0;
                    }
                    else
                    {
                        _selectedRow = -1;
                    }
                    UpdateRequestUI(true);
                    SetUIInteractivity();
                    _lastSelection = -1;
                }, "History");

                _historyButton.ToggleWordWrapping(false);
                _historyHintText = UIHelper.AddHintText(_historyButton.transform as RectTransform, "");
                #endregion

                #region Blacklist button
                // Blacklist button
                _blacklistButton = UIHelper.CreateUIButton("SRMBlacklist", container, "PracticeButton", new Vector2(53f, 10f),
                                                           new Vector2(25f, 15f),
                                                           () =>
                {
                    if (NumberOfCells() > 0)
                    {
                        void _onConfirm()
                        {
                            RequestBot.Blacklist(_selectedRow, isShowingHistory, true);
                            if (_selectedRow > 0)
                            {
                                _selectedRow--;
                            }
                            confirmDialogActive = false;
                        }

                        // get song
                        var song = SongInfoForRow(_selectedRow).song;

                        // indicate dialog is active
                        confirmDialogActive = true;

                        // show dialog
                        YesNoModal.instance.ShowDialog("Blacklist Song Warning", $"Blacklisting {song["songName"].Value} by {song["authorName"].Value}\r\nDo you want to continue?", _onConfirm, () => { confirmDialogActive = false; });
                    }
                }, "Blacklist");

                _blacklistButton.ToggleWordWrapping(false);
                UIHelper.AddHintText(_blacklistButton.transform as RectTransform, "Block the selected request from being queued in the future.");
                #endregion

                #region Skip button
                // Skip button
                _skipButton = UIHelper.CreateUIButton("SRMSkip", container, "PracticeButton", new Vector2(53f, 0f),
                                                      new Vector2(25f, 15f),
                                                      () =>
                {
                    if (NumberOfCells() > 0)
                    {
                        // get song
                        var song = SongInfoForRow(_selectedRow).song;

                        void _onConfirm()
                        {
                            // get selected song
                            currentsong = SongInfoForRow(_selectedRow);

                            // skip it
                            RequestBot.Skip(_selectedRow);

                            // select previous song if not first song
                            if (_selectedRow > 0)
                            {
                                _selectedRow--;
                            }

                            // indicate dialog is no longer active
                            confirmDialogActive = false;
                        }

                        // indicate dialog is active
                        confirmDialogActive = true;

                        // show dialog
                        YesNoModal.instance.ShowDialog("Skip Song Warning", $"Skipping {song["songName"].Value} by {song["authorName"].Value}\r\nDo you want to continue?", _onConfirm, () => { confirmDialogActive = false; });
                    }
                }, "Skip");

                _skipButton.ToggleWordWrapping(false);
                UIHelper.AddHintText(_skipButton.transform as RectTransform, "Remove the selected request from the queue.");
                #endregion

                #region Play button
                // Play button
                _playButton = UIHelper.CreateUIButton("SRMPlay", container, "ActionButton", new Vector2(53f, -10f),
                                                      new Vector2(25f, 15f),
                                                      () =>
                {
                    if (NumberOfCells() > 0)
                    {
                        currentsong = SongInfoForRow(_selectedRow);
                        RequestBot.played.Add(currentsong.song);
                        RequestBot.WriteJSON(RequestBot.playedfilename, ref RequestBot.played);

                        SetUIInteractivity(false);
                        RequestBot.Process(_selectedRow, isShowingHistory);
                        _selectedRow = -1;
                    }
                }, "Play");

                _playButton.ToggleWordWrapping(false);
                _playButton.interactable = ((isShowingHistory && RequestHistory.Songs.Count > 0) || (!isShowingHistory && RequestQueue.Songs.Count > 0));
                UIHelper.AddHintText(_playButton.transform as RectTransform, "Download and scroll to the currently selected request.");
                #endregion

                #region Queue button
                // Queue button
                _queueButton = UIHelper.CreateUIButton("SRMQueue", container, "PracticeButton", new Vector2(53f, -30f),
                                                       new Vector2(25f, 15f),
                                                       () =>
                {
                    RequestBotConfig.Instance.RequestQueueOpen = !RequestBotConfig.Instance.RequestQueueOpen;
                    RequestBotConfig.Instance.Save();
                    RequestBot.WriteQueueStatusToFile(RequestBotConfig.Instance.RequestQueueOpen ? "Queue is open." : "Queue is closed.");
                    RequestBot.Instance.QueueChatMessage(RequestBotConfig.Instance.RequestQueueOpen ? "Queue is open." : "Queue is closed.");
                    UpdateRequestUI();
                }, RequestBotConfig.Instance.RequestQueueOpen ? "Queue Open" : "Queue Closed");

                _queueButton.ToggleWordWrapping(true);
                _queueButton.SetButtonUnderlineColor(RequestBotConfig.Instance.RequestQueueOpen ? Color.green : Color.red);
                _queueButton.SetButtonTextSize(3.5f);
                UIHelper.AddHintText(_queueButton.transform as RectTransform, "Open/Close the queue.");
                #endregion

                // Set default RequestFlowCoordinator title
                RequestBot.SetTitle(isShowingHistory ? "Song Request History" : "Song Request Queue");
            }
            base.DidActivate(firstActivation, addedToHierarchy, screenSystemEnabling);

            if (addedToHierarchy)
            {
                _selectedRow = -1;
                _songListTableView.ClearSelection();
            }

            UpdateRequestUI();
            SetUIInteractivity(true);
        }
Exemplo n.º 13
0
        private async void SetDataFromLevelAsync(SongRequest request, LevelListTableCell _tableCell, int row)
        {
            bool highlight = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');

            string msg = highlight ? "MSG" : "";

            var hasMessage  = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');
            var isChallenge = request.requestInfo.IndexOf("!challenge", StringComparison.OrdinalIgnoreCase) >= 0;

            var beatmapCharacteristicImages = _tableCell.GetPrivateField <UnityEngine.UI.Image[]>("_beatmapCharacteristicImages"); // NEW VERSION

            foreach (var i in beatmapCharacteristicImages)
            {
                i.enabled = false;
            }
            _tableCell.SetPrivateField("_beatmapCharacteristicAlphas", new float[3] {
                0f, 1f, 1f
            });
            // set message icon if request has a message // NEW VERSION
            if (hasMessage)
            {
                beatmapCharacteristicImages.Last().sprite  = Base64Sprites.InfoIcon;
                beatmapCharacteristicImages.Last().enabled = true;
            }

            // set challenge icon if song is a challenge
            if (isChallenge)
            {
                var el = beatmapCharacteristicImages.ElementAt(1);

                el.sprite  = Base64Sprites.VersusChallengeIcon;
                el.enabled = true;
            }

            string pp      = "";
            int    ppvalue = request.song["pp"].AsInt;

            if (ppvalue > 0)
            {
                pp = $" {ppvalue} PP";
            }

            var dt = new RequestBot.DynamicText().AddSong(request.song).AddUser(ref request.requestor); // Get basic fields

            dt.Add("Status", request.status.ToString());
            dt.Add("Info", (request.requestInfo != "") ? " / " + request.requestInfo : "");
            dt.Add("RequestTime", request.requestTime.ToLocalTime().ToString("hh:mm"));

            var songName = _tableCell.GetPrivateField <TextMeshProUGUI>("_songNameText");

            //songName.text = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size> <color=#ff00ff>{msg}</color>";
            songName.text = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size>"; // NEW VERSION

            var author = _tableCell.GetPrivateField <TextMeshProUGUI>("_authorText");

            author.text = dt.Parse(RequestBot.QueueListRow2);

            var image    = _tableCell.GetPrivateField <RawImage>("_coverRawImage");
            var imageSet = false;

            if (SongCore.Loader.AreSongsLoaded)
            {
                CustomPreviewBeatmapLevel level = CustomLevelForRow(row);
                if (level != null)
                {
                    Plugin.Log("custom level found");
                    // set image from song's cover image
                    var tex = await level.GetCoverImageTexture2DAsync(System.Threading.CancellationToken.None);

                    image.texture = tex;
                    imageSet      = true;
                }
            }

            if (!imageSet)
            {
                string url = request.song["coverURL"].Value;
                var    s   = GetSongCoverArt(url, (sprite) => { _cachedSprites[url] = sprite; _customListTableView.ReloadData(); });
                image.texture = s.texture;
            }

            BeatSaberUI.AddHintText(_tableCell.transform as RectTransform, dt.Parse(RequestBot.SongHintText));
        }
Exemplo n.º 14
0
        //static bool test(string x)
        //{
        //    File.AppendAllText("c:\\sehria\\objects.txt", x + "\r\n");
        //    return false;
        //}
        protected override void DidActivate(bool firstActivation, ActivationType type)
        {
            if (firstActivation)
            {
                if (!SongCore.Loader.AreSongsLoaded)
                {
                    SongCore.Loader.SongsLoadedEvent += SongLoader_SongsLoadedEvent;
                }

                // get table cell instance
                _requestListTableCellInstance = Resources.FindObjectsOfTypeAll <LevelListTableCell>().First((LevelListTableCell x) => x.name == "LevelListTableCell");

                InitConfirmationDialog();

                //Resources.FindObjectsOfTypeAll<UnityEngine.Object>().Any(x => (test(x.name))); ;

                _songListTableCellInstance = Resources.FindObjectsOfTypeAll <LevelListTableCell>().First(o => (o.name == "LevelListTableCell"));
                _songPreviewPlayer         = Resources.FindObjectsOfTypeAll <SongPreviewPlayer>().FirstOrDefault();
                DidSelectRowEvent         += DidSelectRow;

                RectTransform container = new GameObject("RequestBotContainer", typeof(RectTransform)).transform as RectTransform;
                container.SetParent(rectTransform, false);
                container.sizeDelta = new Vector2(60f, 0f);

                try
                {
                    InitKeyboardDialog();
                }
                catch (Exception ex)
                {
                    Plugin.Log(ex.ToString());
                }

                CenterKeys = new KEYBOARD(container, "", false, -15, 15);

#if UNRELEASED
                // BUG: Need additional modes disabling one shot buttons
                // BUG: Need to make sure the buttons are usable on older headsets

                _CurrentSongName                    = BeatSaberUI.CreateText(container, "", new Vector2(-35, 37f));
                _CurrentSongName.fontSize           = 3f;
                _CurrentSongName.color              = Color.cyan;
                _CurrentSongName.alignment          = TextAlignmentOptions.Left;
                _CurrentSongName.enableWordWrapping = false;
                _CurrentSongName.text               = "";

                _CurrentSongName2                    = BeatSaberUI.CreateText(container, "", new Vector2(-35, 34f));
                _CurrentSongName2.fontSize           = 3f;
                _CurrentSongName2.color              = Color.cyan;
                _CurrentSongName2.alignment          = TextAlignmentOptions.Left;
                _CurrentSongName2.enableWordWrapping = false;
                _CurrentSongName2.text               = "";

                //CenterKeys.AddKeys(SONGLISTKEY);
                RequestBot.AddKeyboard(CenterKeys, "mainpanel.kbd");
                ColorDeckButtons(CenterKeys, Color.white, Color.magenta);
#endif

                RequestBot.AddKeyboard(CenterKeys, "CenterPanel.kbd");

                CenterKeys.DefaultActions();

                // History button
                _historyButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _historyButton.ToggleWordWrapping(false);
                (_historyButton.transform as RectTransform).anchoredPosition = new Vector2(90f, 30f);
                _historyButton.SetButtonText("History");
                _historyButton.onClick.RemoveAllListeners();
                _historyButton.onClick.AddListener(delegate()
                {
                    isShowingHistory = !isShowingHistory;
                    Resources.FindObjectsOfTypeAll <VRUIScreenSystem>().First().title = isShowingHistory ? "Song Request History" : "Song Request Queue";
                    UpdateRequestUI(true);
                    SetUIInteractivity();
                    _lastSelection = -1;
                });
                _historyHintText = BeatSaberUI.AddHintText(_historyButton.transform as RectTransform, "");

                // Blacklist button
                _blacklistButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _blacklistButton.ToggleWordWrapping(false);
                (_blacklistButton.transform as RectTransform).anchoredPosition = new Vector2(90f, 10f);
                _blacklistButton.SetButtonText("Blacklist");
                //_blacklistButton.GetComponentInChildren<Image>().color = Color.red;
                _blacklistButton.onClick.RemoveAllListeners();
                _blacklistButton.onClick.AddListener(delegate()
                {
                    if (NumberOfCells() > 0)
                    {
                        _onConfirm = () =>
                        {
                            RequestBot.Blacklist(_selectedRow, isShowingHistory, true);
                            if (_selectedRow > 0)
                            {
                                _selectedRow--;
                            }
                        };
                        var song             = SongInfoForRow(_selectedRow).song;
                        _warningTitle.text   = "Blacklist Song Warning";
                        _warningMessage.text = $"Blacklisting {song["songName"].Value} by {song["authorName"].Value}\r\nDo you want to continue?";
                        confirmDialogActive  = true;
                        _confirmationDialog.Present();
                    }
                });
                BeatSaberUI.AddHintText(_blacklistButton.transform as RectTransform, "Block the selected request from being queued in the future.");

                // Skip button
                _skipButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _skipButton.ToggleWordWrapping(false);
                (_skipButton.transform as RectTransform).anchoredPosition = new Vector2(90f, 0f);
                _skipButton.SetButtonText("Skip");
                //_skipButton.GetComponentInChildren<Image>().color = Color.yellow;
                _skipButton.onClick.RemoveAllListeners();
                _skipButton.onClick.AddListener(delegate()
                {
                    if (NumberOfCells() > 0)
                    {
                        _onConfirm = () =>
                        {
                            currentsong = SongInfoForRow(_selectedRow);
                            RequestBot.Skip(_selectedRow);
                            if (_selectedRow > 0)
                            {
                                _selectedRow--;
                            }
                        };
                        var song             = SongInfoForRow(_selectedRow).song;
                        _warningTitle.text   = "Skip Song Warning";
                        _warningMessage.text = $"Skipping {song["songName"].Value} by {song["authorName"].Value}\r\nDo you want to continue?";
                        confirmDialogActive  = true;
                        _confirmationDialog.Present();
                    }
                });
                BeatSaberUI.AddHintText(_skipButton.transform as RectTransform, "Remove the selected request from the queue.");

                // Play button
                _playButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _playButton.ToggleWordWrapping(false);
                (_playButton.transform as RectTransform).anchoredPosition = new Vector2(90f, -10f);
                _playButton.SetButtonText("Play");
                _playButton.GetComponentInChildren <Image>().color = Color.green;
                _playButton.onClick.RemoveAllListeners();
                _playButton.onClick.AddListener(delegate()
                {
                    if (NumberOfCells() > 0)
                    {
                        currentsong = SongInfoForRow(_selectedRow);
                        RequestBot.played.Add(currentsong.song);
                        RequestBot.WriteJSON(RequestBot.playedfilename, ref RequestBot.played);

                        SetUIInteractivity(false);
                        RequestBot.Process(_selectedRow, isShowingHistory);
                        _selectedRow = -1;
                    }
                });
                BeatSaberUI.AddHintText(_playButton.transform as RectTransform, "Download and scroll to the currently selected request.");

                // Queue button
                _queueButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _queueButton.ToggleWordWrapping(false);
                _queueButton.SetButtonTextSize(3.5f);
                (_queueButton.transform as RectTransform).anchoredPosition = new Vector2(90f, -30f);
                _queueButton.SetButtonText(RequestBotConfig.Instance.RequestQueueOpen ? "Queue Open" : "Queue Closed");
                _queueButton.GetComponentInChildren <Image>().color = RequestBotConfig.Instance.RequestQueueOpen ? Color.green : Color.red;;
                _queueButton.interactable = true;
                _queueButton.onClick.RemoveAllListeners();
                _queueButton.onClick.AddListener(delegate()
                {
                    RequestBotConfig.Instance.RequestQueueOpen = !RequestBotConfig.Instance.RequestQueueOpen;
                    RequestBotConfig.Instance.Save();
                    RequestBot.WriteQueueStatusToFile(RequestBotConfig.Instance.RequestQueueOpen ? "Queue is open." : "Queue is closed.");
                    RequestBot.Instance.QueueChatMessage(RequestBotConfig.Instance.RequestQueueOpen ? "Queue is open." : "Queue is closed.");
                    UpdateRequestUI();
                });
                BeatSaberUI.AddHintText(_queueButton.transform as RectTransform, "Open/Close the queue.");
            }
            base.DidActivate(firstActivation, type);
            UpdateRequestUI();
            SetUIInteractivity(true);
        }
        private async void SetDataFromLevelAsync(SongRequest request, LevelListTableCell _tableCell, int row)
        {
            var favouritesBadge = _tableCell.GetField <RawImage, LevelListTableCell>("_favoritesBadgeImage");

            favouritesBadge.enabled = false;

            bool highlight = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');

            string msg = highlight ? "MSG" : "";

            var hasMessage  = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');
            var isChallenge = request.requestInfo.IndexOf("!challenge", StringComparison.OrdinalIgnoreCase) >= 0;

            var beatmapCharacteristicImages = _tableCell.GetField <UnityEngine.UI.Image[], LevelListTableCell>("_beatmapCharacteristicImages"); // NEW VERSION

            foreach (var i in beatmapCharacteristicImages)
            {
                i.enabled = false;
            }

            // causing a nullex?
            //_tableCell.SetField("_beatmapCharacteristicAlphas", new float[5] { 1f, 1f, 1f, 1f, 1f });

            // set message icon if request has a message // NEW VERSION
            if (hasMessage)
            {
                beatmapCharacteristicImages.Last().sprite  = Base64Sprites.InfoIcon;
                beatmapCharacteristicImages.Last().enabled = true;
            }

            // set challenge icon if song is a challenge
            if (isChallenge)
            {
                var el = beatmapCharacteristicImages.ElementAt(beatmapCharacteristicImages.Length - 2);

                el.sprite  = Base64Sprites.VersusChallengeIcon;
                el.enabled = true;
            }

            string pp      = "";
            int    ppvalue = request.song["pp"].AsInt;

            if (ppvalue > 0)
            {
                pp = $" {ppvalue} PP";
            }

            var dt = new RequestBot.DynamicText().AddSong(request.song).AddUser(ref request.requestor); // Get basic fields

            dt.Add("Status", request.status.ToString());
            dt.Add("Info", (request.requestInfo != "") ? " / " + request.requestInfo : "");
            dt.Add("RequestTime", request.requestTime.ToLocalTime().ToString("hh:mm"));

            var songName = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songNameText");

            //songName.text = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size> <color=#ff00ff>{msg}</color>";
            songName.text = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size>"; // NEW VERSION

            var author = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_authorText");

            author.text = dt.Parse(RequestBot.QueueListRow2);

            var image    = _tableCell.GetField <RawImage, LevelListTableCell>("_coverRawImage");
            var imageSet = false;

            if (SongCore.Loader.AreSongsLoaded)
            {
                CustomPreviewBeatmapLevel level = CustomLevelForRow(row);
                if (level != null)
                {
                    //Plugin.Log("custom level found");
                    // set image from song's cover image
                    var tex = await level.GetCoverImageTexture2DAsync(System.Threading.CancellationToken.None);

                    image.texture = tex;
                    imageSet      = true;
                }
            }

            if (!imageSet)
            {
                string url = request.song["coverURL"].Value;

                if (!_cachedTextures.TryGetValue(url, out var tex))
                {
                    var b = await Plugin.WebClient.DownloadImage($"https://beatsaver.com{url}", System.Threading.CancellationToken.None);

                    tex = new Texture2D(2, 2);
                    tex.LoadImage(b);

                    try
                    {
                        _cachedTextures.Add(url, tex);
                    }
                    catch (Exception)
                    {
                    }
                }

                image.texture = tex;
            }

            UIHelper.AddHintText(_tableCell.transform as RectTransform, dt.Parse(RequestBot.SongHintText));
        }
        protected override void DidActivate(bool firstActivation, ActivationType type)
        {
            if (firstActivation)
            {
                if (!SongCore.Loader.AreSongsLoaded)
                {
                    SongCore.Loader.SongsLoadedEvent += SongLoader_SongsLoadedEvent;
                }

                // get table cell instance
                _requestListTableCellInstance = Resources.FindObjectsOfTypeAll <LevelListTableCell>().First((LevelListTableCell x) => x.name == "LevelListTableCell");

                // initialize Yes/No modal
                YesNoModal.instance.Setup();

                _songPreviewPlayer = Resources.FindObjectsOfTypeAll <SongPreviewPlayer>().FirstOrDefault();

                RectTransform container = new GameObject("RequestBotContainer", typeof(RectTransform)).transform as RectTransform;
                container.SetParent(rectTransform, false);
                container.sizeDelta = new Vector2(60f, 0f);

                #region TableView Setup and Initialization
                var go = new GameObject("SongRequestTableView", typeof(RectTransform));
                go.SetActive(false);
                _songListTableView = go.AddComponent <TableView>();
                _songListTableView.gameObject.AddComponent <RectMask2D>();
                _songListTableView.transform.SetParent(container, false);

                _songListTableView.SetField("_preallocatedCells", new TableView.CellsGroup[0]);
                _songListTableView.SetField("_isInitialized", false);

                var viewport = new GameObject("Viewport").AddComponent <RectTransform>();
                viewport.SetParent(go.GetComponent <RectTransform>(), false);
                (viewport.transform as RectTransform).sizeDelta = new Vector2(0, 0);
                (viewport.transform as RectTransform).anchorMin = new Vector2(0, 0);
                (viewport.transform as RectTransform).anchorMax = new Vector2(1, 1);
                go.GetComponent <ScrollRect>().viewport         = viewport;

                _songListTableView.InvokeMethod <object, TableView>("Init");

                _songListTableView.dataSource = this;

                go.SetActive(true);

                (_songListTableView.transform as RectTransform).anchorMin        = new Vector2(0f, 0f);
                (_songListTableView.transform as RectTransform).anchorMax        = new Vector2(1f, 1f);
                (_songListTableView.transform as RectTransform).sizeDelta        = new Vector2(0f, 60f);
                (_songListTableView.transform as RectTransform).anchoredPosition = new Vector2(0f, -3f);

                _songListTableView.didSelectCellWithIdxEvent += DidSelectRow;

                rectTransform.anchorMin = new Vector2(0.5f, 0f);
                rectTransform.anchorMax = new Vector2(0.5f, 1f);
                rectTransform.sizeDelta = new Vector2(74f, 0f);
                rectTransform.pivot     = new Vector2(0.4f, 0.5f);

                var _songListTableViewScroller = _songListTableView.GetField <TableViewScroller, TableView>("_scroller");

                _pageUpButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().Last(x => (x.name == "PageUpButton")), container, false);
                (_pageUpButton.transform as RectTransform).anchoredPosition = new Vector2(0f, 35f);
                _pageUpButton.interactable = true;
                _pageUpButton.onClick.AddListener(delegate()
                {
                    _songListTableViewScroller.PageScrollUp();
                });

                _pageDownButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(x => (x.name == "PageDownButton")), container, false);
                (_pageDownButton.transform as RectTransform).anchoredPosition = new Vector2(0f, -41f);
                _pageDownButton.interactable = true;
                _pageDownButton.onClick.AddListener(delegate()
                {
                    _songListTableViewScroller.PageScrollDown();
                });
                #endregion

                CenterKeys = new KEYBOARD(container, "", false, -15, 15);

#if UNRELEASED
                // BUG: Need additional modes disabling one shot buttons
                // BUG: Need to make sure the buttons are usable on older headsets

                _CurrentSongName                    = BeatSaberUI.CreateText(container, "", new Vector2(-35, 37f));
                _CurrentSongName.fontSize           = 3f;
                _CurrentSongName.color              = Color.cyan;
                _CurrentSongName.alignment          = TextAlignmentOptions.Left;
                _CurrentSongName.enableWordWrapping = false;
                _CurrentSongName.text               = "";

                _CurrentSongName2                    = BeatSaberUI.CreateText(container, "", new Vector2(-35, 34f));
                _CurrentSongName2.fontSize           = 3f;
                _CurrentSongName2.color              = Color.cyan;
                _CurrentSongName2.alignment          = TextAlignmentOptions.Left;
                _CurrentSongName2.enableWordWrapping = false;
                _CurrentSongName2.text               = "";

                //CenterKeys.AddKeys(SONGLISTKEY);
                if (!RequestBot.AddKeyboard(CenterKeys, "mainpanel.kbd"))
                {
                    CenterKeys.AddKeys(SONGLISTKEY);
                }

                ColorDeckButtons(CenterKeys, Color.white, Color.magenta);
#endif

                RequestBot.AddKeyboard(CenterKeys, "CenterPanel.kbd");

                CenterKeys.DefaultActions();

                #region History button
                // History button
                _historyButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _historyButton.ToggleWordWrapping(false);
                (_historyButton.transform as RectTransform).anchoredPosition = new Vector2(90f, 30f);
                _historyButton.SetButtonText("History");
                _historyButton.onClick.RemoveAllListeners();
                _historyButton.onClick.AddListener(delegate()
                {
                    isShowingHistory = !isShowingHistory;
                    RequestBot.SetTitle(isShowingHistory ? "Song Request History" : "Song Request Queue");
                    UpdateRequestUI(true);
                    SetUIInteractivity();
                    _lastSelection = -1;
                });
                _historyHintText = UIHelper.AddHintText(_historyButton.transform as RectTransform, "");
                #endregion

                #region Blacklist button
                // Blacklist button
                _blacklistButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _blacklistButton.ToggleWordWrapping(false);
                (_blacklistButton.transform as RectTransform).anchoredPosition = new Vector2(90f, 10f);
                _blacklistButton.SetButtonText("Blacklist");
                //_blacklistButton.GetComponentInChildren<Image>().color = Color.red;
                _blacklistButton.onClick.RemoveAllListeners();
                _blacklistButton.onClick.AddListener(delegate()
                {
                    if (NumberOfCells() > 0)
                    {
                        void _onConfirm()
                        {
                            RequestBot.Blacklist(_selectedRow, isShowingHistory, true);
                            if (_selectedRow > 0)
                            {
                                _selectedRow--;
                            }
                            confirmDialogActive = false;
                        }

                        // get song
                        var song = SongInfoForRow(_selectedRow).song;

                        // indicate dialog is active
                        confirmDialogActive = true;

                        // show dialog
                        YesNoModal.instance.ShowDialog("Blacklist Song Warning", $"Blacklisting {song["songName"].Value} by {song["authorName"].Value}\r\nDo you want to continue?", _onConfirm, () => { confirmDialogActive = false; });
                    }
                });
                UIHelper.AddHintText(_blacklistButton.transform as RectTransform, "Block the selected request from being queued in the future.");
                #endregion

                #region Skip button
                // Skip button
                _skipButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _skipButton.ToggleWordWrapping(false);
                (_skipButton.transform as RectTransform).anchoredPosition = new Vector2(90f, 0f);
                _skipButton.SetButtonText("Skip");
                //_skipButton.GetComponentInChildren<Image>().color = Color.yellow;
                _skipButton.onClick.RemoveAllListeners();
                _skipButton.onClick.AddListener(delegate()
                {
                    if (NumberOfCells() > 0)
                    {
                        void _onConfirm()
                        {
                            // get selected song
                            currentsong = SongInfoForRow(_selectedRow);

                            // skip it
                            RequestBot.Skip(_selectedRow);

                            // select previous song if not first song
                            if (_selectedRow > 0)
                            {
                                _selectedRow--;
                            }

                            // indicate dialog is no longer active
                            confirmDialogActive = false;
                        }

                        // get song
                        var song = SongInfoForRow(_selectedRow).song;

                        // indicate dialog is active
                        confirmDialogActive = true;

                        // show dialog
                        YesNoModal.instance.ShowDialog("Skip Song Warning", $"Skipping {song["songName"].Value} by {song["authorName"].Value}\r\nDo you want to continue?", _onConfirm, () => { confirmDialogActive = false; });
                    }
                });
                UIHelper.AddHintText(_skipButton.transform as RectTransform, "Remove the selected request from the queue.");
                #endregion

                #region Play button
                // Play button
                _playButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _playButton.ToggleWordWrapping(false);
                (_playButton.transform as RectTransform).anchoredPosition = new Vector2(90f, -10f);
                _playButton.SetButtonText("Play");
                _playButton.GetComponentInChildren <Image>().color = Color.green;
                _playButton.onClick.RemoveAllListeners();
                _playButton.onClick.AddListener(delegate()
                {
                    if (NumberOfCells() > 0)
                    {
                        currentsong = SongInfoForRow(_selectedRow);
                        RequestBot.played.Add(currentsong.song);
                        RequestBot.WriteJSON(RequestBot.playedfilename, ref RequestBot.played);

                        SetUIInteractivity(false);
                        RequestBot.Process(_selectedRow, isShowingHistory);
                        _selectedRow = -1;
                    }
                });
                UIHelper.AddHintText(_playButton.transform as RectTransform, "Download and scroll to the currently selected request.");
                #endregion

                #region Queue button
                // Queue button
                _queueButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(o => (o.name == "OkButton")), container, false);
                _queueButton.ToggleWordWrapping(false);
                _queueButton.SetButtonTextSize(3.5f);
                (_queueButton.transform as RectTransform).anchoredPosition = new Vector2(90f, -30f);
                _queueButton.SetButtonText(RequestBotConfig.Instance.RequestQueueOpen ? "Queue Open" : "Queue Closed");
                _queueButton.GetComponentInChildren <Image>().color = RequestBotConfig.Instance.RequestQueueOpen ? Color.green : Color.red;;
                _queueButton.interactable = true;
                _queueButton.onClick.RemoveAllListeners();
                _queueButton.onClick.AddListener(delegate()
                {
                    RequestBotConfig.Instance.RequestQueueOpen = !RequestBotConfig.Instance.RequestQueueOpen;
                    RequestBotConfig.Instance.Save();
                    RequestBot.WriteQueueStatusToFile(RequestBotConfig.Instance.RequestQueueOpen ? "Queue is open." : "Queue is closed.");
                    RequestBot.Instance.QueueChatMessage(RequestBotConfig.Instance.RequestQueueOpen ? "Queue is open." : "Queue is closed.");
                    UpdateRequestUI();
                });
                UIHelper.AddHintText(_queueButton.transform as RectTransform, "Open/Close the queue.");
                #endregion

                // Set default RequestFlowCoordinator title
                RequestBot.SetTitle(isShowingHistory ? "Song Request History" : "Song Request Queue");
            }
            base.DidActivate(firstActivation, type);
            UpdateRequestUI();
            SetUIInteractivity(true);
        }