// BUG: Testing major changes. This will get seriously refactored soon. private async Task CheckRequest(RequestInfo requestInfo) { TwitchUser requestor = requestInfo.requestor; string request = requestInfo.request; string normalrequest = normalize.NormalizeBeatSaverString(requestInfo.request); var id = GetBeatSaverId(normalize.RemoveSymbols(ref request, normalize._SymbolsNoDash)); if (id != "") { // Remap song id if entry present. This is one time, and not correct as a result. No recursion right now, could be confusing to the end user. if (songremap.ContainsKey(id) && !requestInfo.flags.HasFlag(CmdFlags.NoFilter)) { request = songremap[id]; QueueChatMessage($"Remapping request {requestInfo.request} to {request}"); } string requestcheckmessage = IsRequestInQueue(normalize.RemoveSymbols(ref request, normalize._SymbolsNoDash)); // Check if requested ID is in Queue if (requestcheckmessage != "") { QueueChatMessage(requestcheckmessage); return; } if (RequestBotConfig.Instance.OfflineMode && RequestBotConfig.Instance.offlinepath != "" && !MapDatabase.MapLibrary.ContainsKey(id)) { foreach (string directory in Directory.GetDirectories(RequestBotConfig.Instance.offlinepath, id + "*")) { await MapDatabase.LoadCustomSongs(directory, id); await Task.Run(async() => { while (MapDatabase.DatabaseLoading) { await Task.Delay(25); } }); break; } } } JSONNode result = null; string errorMessage = ""; // Get song query results from beatsaver.com if (!RequestBotConfig.Instance.OfflineMode) { string requestUrl = (id != "") ? $"https://beatsaver.com/api/maps/detail/{normalize.RemoveSymbols(ref request, normalize._SymbolsNoDash)}" : $"https://beatsaver.com/api/search/text/0?q={normalrequest}"; var resp = await Plugin.WebClient.GetAsync(requestUrl, System.Threading.CancellationToken.None); if (resp.IsSuccessStatusCode) { result = resp.ConvertToJsonNode(); } else { errorMessage = $"Invalid BeatSaver ID \"{request}\" specified. {requestUrl}"; } } SongFilter filter = SongFilter.All; if (requestInfo.flags.HasFlag(CmdFlags.NoFilter)) { filter = SongFilter.Queue; } List <JSONObject> songs = GetSongListFromResults(result, request, ref errorMessage, filter, requestInfo.state.sort != "" ? requestInfo.state.sort : AddSortOrder.ToString()); bool autopick = RequestBotConfig.Instance.AutopickFirstSong || requestInfo.flags.HasFlag(CmdFlags.Autopick); // Filter out too many or too few results if (songs.Count == 0) { if (errorMessage == "") { errorMessage = $"No results found for request \"{request}\""; } } else if (!autopick && songs.Count >= 4) { errorMessage = $"Request for '{request}' produces {songs.Count} results, narrow your search by adding a mapper name, or use https://beatsaver.com to look it up."; } else if (!autopick && songs.Count > 1 && songs.Count < 4) { var msg = new QueueLongMessage(1, 5); msg.Header($"@{requestor.DisplayName}, please choose: "); foreach (var eachsong in songs) { msg.Add(new DynamicText().AddSong(eachsong).Parse(BsrSongDetail), ", "); } msg.end("...", $"No matching songs for for {request}"); return; } else { if (!requestInfo.flags.HasFlag(CmdFlags.NoFilter)) { errorMessage = SongSearchFilter(songs[0], false); } } // Display reason why chosen song was rejected, if filter is triggered. Do not add filtered songs if (errorMessage != "") { QueueChatMessage(errorMessage); return; } JSONObject song = songs[0]; // Song requests should try to be current. If the song was local, we double check for a newer version //if ((song["downloadUrl"].Value == "") && !RequestBotConfig.Instance.OfflineMode ) //{ // //QueueChatMessage($"song: {song["id"].Value.ToString()} ,{song["songName"].Value}"); // yield return Utilities.Download($"https://beatsaver.com/api/maps/detail/{song["id"].Value.ToString()}", Utilities.DownloadType.Raw, null, // // Download success // (web) => // { // result = JSON.Parse(web.downloadHandler.text); // var newsong = result["song"].AsObject; // if (result != null && newsong["version"].Value != "") // { // new SongMap(newsong); // song = newsong; // } // }, // // Download failed, song probably doesn't exist on beatsaver // (web) => // { // // Let player know that the song is not current on BeatSaver // requestInfo.requestInfo += " *LOCAL ONLY*"; // ; //errorMessage = $"Invalid BeatSaver ID \"{request}\" specified. {requestUrl}"; // }); //} RequestTracker[requestor.Id].numRequests++; listcollection.add(duplicatelist, song["id"].Value); if ((requestInfo.flags.HasFlag(CmdFlags.MoveToTop))) { RequestQueue.Songs.Insert(0, new SongRequest(song, requestor, requestInfo.requestTime, RequestStatus.Queued, requestInfo.requestInfo)); } else { RequestQueue.Songs.Add(new SongRequest(song, requestor, requestInfo.requestTime, RequestStatus.Queued, requestInfo.requestInfo)); } RequestQueue.Write(); Writedeck(requestor, "savedqueue"); // This can be used as a backup if persistent Queue is turned off. if (!requestInfo.flags.HasFlag(CmdFlags.SilentResult)) { new DynamicText().AddSong(ref song).QueueMessage(AddSongToQueueText.ToString()); } Dispatcher.RunOnMainThread(() => { UpdateRequestUI(); _refreshQueue = true; }); }
private string ProcessSongRequest(ParseState state) { 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); }